Journeys allows you to engage with your users through in-app messages, feedback widgets, or lets you record data on behalf of them without code changes with respect to conditions and triggers you set.
For an overview of Journeys and what you can do with them please check our Journeys Explained quick guide:
SDK integration for the Journeys is quite straight forward. Only parts that would need some extra steps are creating engagement blocks (in-app messages and surveys.)
Creating Engagement Blocks
To show in-app messages or surveys you need to:
-
Create a Content: Journeys > Library > Content Block > New Block. For detailed instructions, refer to the Content Builder documentation.
OR
Create a survey: Feedback > Surveys > New Survey. For detailed instructions, refer to the Surveys documentation.PS: You can skip this step and create content/survey while creating a Journey.
- Set up a Journey: After creating the content block or the survey widget, configure a Journey to define when and how the engagement block will be presented to your users. For more information on creating a journey, refer to the Journeys documentation.
Integrating Journeys in SDKs
Integrating journeys with the SDKs is straightforward and requires just a single line of code for all supported SDKs. Please note that all functions must be called after initializing the SDK; otherwise, the call will not be executed successfully.
This call will retrieve and display the most up-to-date engagement block available for the user. By making this request, the system ensures that the user receives the latest content.
Countly.sharedInstance().contents().enterContentZone();[Countly.sharedInstance.content enterContentZone];Countly.content.enterContentZone();Countly.instance.content.enterContentZone()
Countly.content.enterContentZone();
Current Limitations
Engagement blocks may not appear immediately, as content is fetched periodically from the server. This means that there could be a slight delay in displaying the latest messages to users, depending on the fetch interval set for the content.
Frequent manual fetching can increase server load and lead to performance issues.
If you need to achieve an instant fetch, you can manually trigger a content refresh by using the "refresh" function, which will force the SDK to fetch the content immediately, bypassing the timer interval.
Countly.sharedInstance().contents().refreshContentZone();[Countly.sharedInstance.content refreshContentZone];Countly.content.refreshContentZone();Countly.instance.content.refreshContentZone()
Countly.content.refreshContentZone();
For detailed information on content-related methods, you can refer to the Content Zone section in the SDKs documentation of your respective platform. For understanding the SDK-Server communication related to Journeys you can check this article:
User Consent
If your app requires GDPR compliance or uses Countly's consent management feature, you must grant the relevant consents for Journeys to function. Engagement blocks rendered as in-app messages require the content consent. Engagement blocks rendered as surveys require the feedback consent. Without these consents, the SDK will not fetch or display Journey content for the user.
// Give content consent during initialization
config.setConsentEnabled(new String[]{"content", "feedback"});
// Or after initialization
Countly.sharedInstance().consent().giveConsent(new String[]{"content", "feedback"});
// Revoke consent
Countly.sharedInstance().consent().removeConsent(new String[]{"content", "feedback"});// Give content consent during initialization
config.consents = @[CLYConsentContent, CLYConsentFeedback];
// Or after initialization
[Countly.sharedInstance giveConsentForFeatures:@[CLYConsentContent, CLYConsentFeedback]];
// Revoke consent
[Countly.sharedInstance cancelConsentForFeatures:@[CLYConsentContent, CLYConsentFeedback]];// Give content consent during initialization
Countly.init({ app_key: "APP_KEY", url: "https://YOUR_SERVER", require_consent: true });
Countly.add_consent(["content", "feedback"]);
// Revoke consent
Countly.remove_consent(["content", "feedback"]);// Give content consent during initialization
config.setConsentEnabled([CountlyConsent.content, CountlyConsent.feedback]);
// Or after initialization
Countly.giveConsent([CountlyConsent.content, CountlyConsent.feedback]);
// Revoke consent
Countly.removeConsent([CountlyConsent.content, CountlyConsent.feedback]);// Give content consent during initialization
countlyConfig.giveConsent(["content", "feedback"]);
// Or after initialization
Countly.giveConsent(["content", "feedback"]);
// Revoke consent
Countly.removeConsent(["content", "feedback"]);Separating Marketing and Informative In-App Messages
SDK consent acts as a channel-wide gate. When the content consent is not granted, no engagement blocks reach the user, including informative ones such as feature announcements or in-product onboarding. To deliver informative in-app messages to every user while reserving marketing messages for opted-in users, grant SDK consent unconditionally and segment journeys on the server through a custom user property.
-
Grant SDK consent unconditionally. Regardless of the user's marketing preference, grant the
contentconsent (andfeedbackif you use survey-based engagement blocks). This keeps the user eligible to receive any engagement block, whether informative or marketing. -
Track the marketing preference as a custom user property. When the user accepts or declines marketing communications in your app, record that decision as a user property such as
marketing_consent:// Android Countly.sharedInstance().userProfile().setProperty("marketing_consent", "true"); Countly.sharedInstance().userProfile().save();Equivalent user-profile methods exist in every Countly SDK. See the User Profile section of the SDK documentation for your platform.
-
Segment journeys in Countly. Use
marketing_consentas a segmentation filter when configuring a journey:-
Informative journeys (feature announcements, onboarding nudges): no filter on
marketing_consent, so every consented user is reachable. -
Marketing journeys (promotions, cross-sell): filter by
marketing_consent = "true", so only opted-in users receive them.
-
Informative journeys (feature announcements, onboarding nudges): no filter on
Set marketing_consent explicitly for every user during onboarding, even when the user skips the consent prompt. If the property is never recorded, those users may unintentionally pass through marketing filters depending on how the journey condition is configured.