-
Notifications
You must be signed in to change notification settings - Fork 4
Add more details about cross-domain tracking #1210
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
63fe8fb
fc2f463
d86dfc6
3f6e704
4bce90d
314d6e4
f724caa
1ea0333
4fd1a93
cb15319
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| --- | ||
| title: "Cross-navigation tracking" | ||
| description: "Configure cross-domain tracking to maintain user identity between different domains in your ecosystem" | ||
| date: "2025-07-26" | ||
| sidebar_position: 5 | ||
| --- | ||
|
|
||
| When users navigate between different domains in your ecosystem, their user identity may get fragmented. Examples include navigation from your main website to a partner site, or to a mobile app. This creates gaps in your user journey data and makes it difficult to understand the complete customer experience across your digital properties. | ||
|
|
||
| :::info Web subdomains | ||
| This problem doesn't usually apply for navigation between web subdomains, as the web trackers have `discoverRootDomain` [enabled by default](/docs/sources/trackers/web-trackers/tracker-setup/initialization-options/index.md). | ||
| ::: | ||
|
|
||
| Cross-navigation (also called cross-domain) tracking solves this problem by passing user identification data in URL parameters when users click links to other domains. This enables you to maintain user continuity across your applications. | ||
|
|
||
| To use cross-navigation tracking, configure the [web](/docs/sources/trackers/web-trackers/cross-domain-tracking/index.md) or [native mobile](/docs/sources/trackers/mobile-trackers/tracking-events/session-tracking/index.md#decorating-outgoing-links-using-cross-navigation-tracking) trackers to add an additional parameter, named `_sp`, to the querystring of outbound links. This process is called "link decoration". | ||
|
|
||
| Link decoration makes the added values visible in the `url` field of events on the destination page or URI. The querystring is added only to the events at the destination: it doesn't persist throughout the user's session. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this meant to be "at the destination URL" or "destination page" or similar? It doesn't seem unreasonable to think "the destination" is the entire site/app you're linking to. |
||
|
|
||
| ## Querystring properties | ||
|
|
||
| The `_sp` querystring parameter has two different formats: extended or short. You can also configure exactly which properties you want to include. | ||
mscwilson marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| Available properties: | ||
|
|
||
| | Property | Description | Extended | Short | | ||
| | ---------------- | ---------------------------------------------- | -------- | ----- | | ||
| | `domainUserId` | Current tracker-generated UUID user identifier | ✅ | ✅ | | ||
| | `timestamp` | Current epoch timestamp, millisecond precision | ✅ | ✅ | | ||
| | `sessionId` | Current session UUID identifier | ✅ | | | ||
| | `subjectUserId` | Custom business user identifier | ✅ | | | ||
| | `sourceId` | Application identifier | ✅ | | | ||
| | `sourcePlatform` | Platform of the current device | ✅ | | | ||
| | `reason` | Custom information or identifier | ✅ | | | ||
|
|
||
| For example, the link `appSchema://path/to/page` would look like this after decoration with the full extended format: | ||
|
|
||
| ``` | ||
| appSchema://path/to/page?_sp=domainUserId.timestamp.sessionId.subjectUserId.sourceId.sourcePlatform.reason | ||
| ``` | ||
|
|
||
| ## How are the querystring parameters processed? | ||
|
|
||
| By default, your pipeline will process only the short format querystring `_sp={domainUserId}.{timestamp}`, even if you've decorated the links with the extended format. To process the extra properties, you'll need to configure the [cross-navigation enrichment](/docs/pipeline/enrichments/available-enrichments/cross-navigation-enrichment/index.md). | ||
|
|
||
| Both default and extended formats will populate the [atomic](/docs/fundamentals/canonical-event/index.md) `refr_domain_userid` and `refr_dvce_tstamp` fields. The enrichment also adds a `cross_navigation` entity to the event. | ||
|
|
||
| | Feature | Default behavior | With cross-navigation enrichment | | ||
| | ------------------------------------------------------- | ---------------- | -------------------------------- | | ||
| | Processes short format `_sp={domainUserId}.{timestamp}` | ✅ | ✅ | | ||
| | Processes extended format properties | ❌ | ✅ | | ||
| | Populates `refr_domain_userid` field | ✅ | ✅ | | ||
| | Populates `refr_dvce_tstamp` field | ✅ | ✅ | | ||
| | Adds `cross_navigation` entity | ❌ | ✅ | | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,22 +1,26 @@ | ||
| --- | ||
| title: "Cross Navigation Enrichment" | ||
| title: "Cross-navigation enrichment" | ||
| sidebar_position: 5 | ||
| sidebar_label: Cross Navigation | ||
| sidebar_label: Cross-navigation | ||
| --- | ||
|
|
||
| This enrichment parses the extended cross navigation format in `_sp` querystring parameter and attaches the `cross_navigation` context to an event. | ||
| This enrichment parses the extended cross-navigation format in the `_sp` querystring parameter, and attaches a `cross_navigation` entity to an event. | ||
|
|
||
| The `_sp` parameter can be attached by our Web ([see cross-domain tracking](/docs/sources/trackers/web-trackers/cross-domain-tracking/index.md)) and [mobile trackers](/docs/sources/trackers/mobile-trackers/tracking-events/session-tracking/index.md#decorating-outgoing-links-using-cross-navigation-tracking) and contains user, session and app identifiers (e.g., domain user and session IDs, business user ID, source app ID). The information to include in the parameters is configurable in the trackers. This is useful for tracking the movement of users across different apps and platforms. | ||
| Check out the [cross-navigation](/docs/events/cross-navigation/index.md) page to learn why this can be useful. | ||
|
|
||
| The extended cross navigation format can be described by `_sp={domainUserId}.{timestamp}.{sessionId}.{subjectUserId}.{sourceId}.{platform}.{reason}` | ||
| The extended cross-navigation format is `_sp={domainUserId}.{timestamp}.{sessionId}.{subjectUserId}.{sourceId}.{sourcePlatform}.{reason}`. The `domainUserId` and `timestamp` fields will always be present, but some of the other fields may be null or empty. They're configured within the tracker. | ||
|
|
||
| If this enrichment isn't enabled, Enrich parses `_sp` querystring parameter according to the old format, `_sp={domainUserId}.{timestamp}` | ||
| If this enrichment isn't enabled, Enrich parses the `_sp` querystring parameter according to the short format, `_sp={domainUserId}.{timestamp}` | ||
|
|
||
| ## Configuration | ||
|
|
||
| - [Schema](https://github.com/snowplow/iglu-central/blob/master/schemas/com.snowplowanalytics.snowplow.enrichments/cross_navigation_config/jsonschema/1-0-0) | ||
| - [Example](https://github.com/snowplow/enrich/blob/master/config/enrichments/cross_navigation_config.json) | ||
|
|
||
| ```json reference | ||
| https://github.com/snowplow/enrich/blob/master/config/enrichments/cross_navigation_config.json | ||
| ``` | ||
|
|
||
| ```mdx-code-block | ||
| import TestingWithMicro from "@site/docs/reusable/test-enrichment-with-micro/_index.md" | ||
|
|
||
|
|
@@ -25,13 +29,10 @@ import TestingWithMicro from "@site/docs/reusable/test-enrichment-with-micro/_in | |
|
|
||
| ## Input | ||
|
|
||
| This enrichment extracts `_sp` querystring parameter from the following inputs: | ||
|
|
||
| - The `page_url` field from the Snowplow event | ||
| - The referer uri extracted from corresponding HTTP header in the raw event | ||
| This enrichment extracts the `_sp` querystring parameter from the `page_url` field from the Snowplow event. | ||
|
|
||
| ## Output | ||
|
|
||
| This enrichment adds a new derived context to the enriched event with [this schema](https://github.com/snowplow/iglu-central/blob/master/schemas/com.snowplowanalytics.snowplow/cross_navigation/jsonschema/1-0-0). | ||
| This enrichment adds a new derived entity to the enriched event based on [this schema](https://github.com/snowplow/iglu-central/blob/master/schemas/com.snowplowanalytics.snowplow/cross_navigation/jsonschema/1-0-0). | ||
|
|
||
| Also, it continues to populate `refr_domain_userid` and `refr_dvce_tstamp` enriched event fields as before. | ||
| Also, it populates the `refr_domain_userid` and `refr_dvce_tstamp` enriched event fields. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's worth having the qualifier here; this page ranks highly for those two fields in search now and this implies this enrichment is required for them to populate, but they will populate even if it is disabled (even if it's super clear on the other page). |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -103,7 +103,7 @@ For instance, with this configuration: | |
| SessionConfiguration( | ||
| foregroundTimeout: Measurement(value: 360, unit: .seconds), | ||
| backgroundTimeout: Measurement(value: 15, unit: .seconds) | ||
| ) | ||
| ) | ||
| ``` | ||
|
|
||
| </TabItem> | ||
|
|
@@ -212,30 +212,25 @@ Snowplow.createTracker(getApplicationContext(), namespace, networkConfig, sessio | |
|
|
||
| ## Decorating outgoing links using cross-navigation tracking | ||
|
|
||
| :::note Not available before v6 | ||
| :::note | ||
| This feature was introduced in version 6.0.0 of the iOS and Android trackers. | ||
| ::: | ||
|
|
||
| The tracker provides a `decorateLink` API to decorate outgoing links from the mobile app to another mobile app or to a website. | ||
| This API adds an `_sp` parameter to the links containing information about the user, app, and current session. | ||
| This is useful for tracking the movement of users across different apps and platforms. | ||
| It is part of our cross-navigation solution and is equivalent to [cross-domain tracking on the JavaScript tracker](/docs/sources/trackers/web-trackers/cross-domain-tracking/index.md). | ||
| The `decorateLink` function is part of Snowplow's [cross-navigation solution](/docs/events/cross-navigation/index.md) for tracking the movement of users across different apps and platforms. | ||
|
|
||
| For example, calling `decorateLink` on `appSchema://path/to/page` will produce the following result: | ||
| Choose which parameters to include using a `CrossDeviceParameterConfiguration` object. The `domainUserId` and `timestamp` are always included automatically. Use booleans to select which properties to include in the link decoration. The tracker will derive the required values from its configuration. | ||
|
|
||
| ``` | ||
| appSchema://path/to/page?_sp=domainUserId.timestamp.sessionId.subjectUserId.sourceId.platform.reason | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Oh, it moved to the general page, nevermind! |
||
| ``` | ||
| This table shows the options: | ||
|
|
||
| The `decorateLink` function adds the following information to the link (configurable using the `CrossDeviceParameterConfiguration` object passed to the method): | ||
| | Property | Description | Type | Included by default? | Value used | | ||
| | ---------------- | -------------------------------- | ------- | -------------------- | ---------------------------------- | | ||
| | `sessionId` | Current session UUID identifier | Boolean | ✅ | `SessionController.sessionId` | | ||
| | `subjectUserId` | Custom business user identifier | Boolean | ❌ | `SubjectController.userId` | | ||
| | `sourceId` | Application identifier | Boolean | ✅ | `TrackerConfiguration.appId` | | ||
| | `sourcePlatform` | Platform of the current device | Boolean | ❌ | `TrackerController.devicePlatform` | | ||
| | `reason` | Custom information or identifier | String | ❌ | Custom string provided by you | | ||
|
|
||
| - `domainUserId` – The current tracker generated user identifier (value of `SessionController.userId`) – required. | ||
| - `timestamp` – The current ms precision epoch timestamp – required. | ||
| - `sessionId` - The current session identifier (value of `SessionController.sessionId`) – optional. | ||
| - `subjectUserId` - The custom business user identifier (value of `SubjectController.userId`) – optional. | ||
| - `sourceId` – The `appId` (value of `TrackerConfiguration.appId`) – optional. | ||
| - `platform` - The platform of the current device (value of `TrackerController.devicePlatform` – optional. | ||
| - `reason` – Identifier/information for cross-navigation – optional. | ||
| The `subjectUserId` property is not included by default, in case it contains personal data. | ||
|
|
||
| <Tabs groupId="platform" queryString> | ||
| <TabItem value="ios" label="iOS" default> | ||
|
|
@@ -245,7 +240,7 @@ let link = URL(string: "https://example.com")! | |
| let decoratedLink = Snowplow.defaultTracker()?.decorateLink( | ||
| link, | ||
| // optional configuration for which information to be added to the link | ||
| extendedParameters: CrossDeviceParameterConfiguration(sessionId: true, subjectUserId: true) | ||
| extendedParameters: CrossDeviceParameterConfiguration(sessionId: false, subjectUserId: true) | ||
| ) | ||
| ``` | ||
|
|
||
|
|
@@ -257,7 +252,7 @@ val link = Uri.parse("http://example.com") | |
| val decoratedLink = Snowplow.defaultTracker.decorateLink( | ||
| link, | ||
| // optional configuration for which information to be added to the link | ||
| CrossDeviceParameterConfiguration(sessionId = true, subjectUserId = true) | ||
| CrossDeviceParameterConfiguration(sessionId = false, subjectUserId = true) | ||
| ) | ||
| ``` | ||
|
|
||
|
|
@@ -267,7 +262,7 @@ val decoratedLink = Snowplow.defaultTracker.decorateLink( | |
| ```java | ||
| Uri link = Uri.parse("http://example.com"); | ||
| Uri decoratedLink = Snowplow.getDefaultTracker().decorateLink(link, new CrossDeviceParameterConfiguration( | ||
| true, // sessionId | ||
| false, // sessionId | ||
| true, // subjectUserId | ||
| false, // sourceId | ||
| false, // sourcePlatform | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this have an example to avoid being jargon?