-
Notifications
You must be signed in to change notification settings - Fork 56
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
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,50 @@ | ||
--- | ||
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—such as from your main website to a subdomain, partner site, or mobile app—their user identity is typically lost. This creates gaps in your user journey data and makes it difficult to understand the complete customer experience across your digital properties. | ||
|
||
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. | ||
|
||
## Querystring properties | ||
|
||
The `_sp` querystring parameter has two different formats: extended or short. You can also configure exactly which properties you want to include. | ||
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. You can only configure them when using extended; |
||
|
||
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: | ||
|
||
``` | ||
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}`. | ||
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. Maybe note some of these fields may be empty/null because the fields to attach is configured in 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 old 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 | ||
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. TIL, cool! This kind of makes the I'd say embed the example as well, but this is about as boring as enrichment configs get so I'm not sure it matters. 😅 I guess it makes it easy to copy/paste? 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's not documented but apparently we can change the "See full example on GitHub" text too if that doesn't make sense in this context. ```json reference title="Schema" referenceLinkText="See schema on Github" |
||
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" | ||
|
||
|
@@ -28,10 +32,10 @@ import TestingWithMicro from "@site/docs/reusable/test-enrichment-with-micro/_in | |
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 | ||
- The `referer` URI extracted from corresponding HTTP header in the raw event | ||
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 would drop this list and just say |
||
|
||
## 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). | ||
jethron marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Also, it continues to populate `refr_domain_userid` and `refr_dvce_tstamp` enriched event fields as before. |
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,23 @@ 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). | ||
|
||
For example, calling `decorateLink` on `appSchema://path/to/page` will produce the following result: | ||
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. | ||
|
||
``` | ||
appSchema://path/to/page?_sp=domainUserId.timestamp.sessionId.subjectUserId.sourceId.platform.reason | ||
``` | ||
Choose which parameters to include using a `CrossDeviceParameterConfiguration` object. The `domainUserId` and `timestamp` are always included automatically. | ||
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. Should this link to the API docs or something? The table below implies to me that we need to pass the values from the Controller/Configurations, but instead we actually just need to pass booleans (or a string for the |
||
|
||
The `decorateLink` function adds the following information to the link (configurable using the `CrossDeviceParameterConfiguration` object passed to the method): | ||
This table shows the options: | ||
|
||
- `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. | ||
| Property | Description | Value used | | ||
| ---------------- | -------------------------------- | ---------------------------------- | | ||
| `sessionId` | Current session UUID identifier | `SessionController.sessionId` | | ||
| `subjectUserId` | Custom business user identifier | `SubjectController.userId` | | ||
| `sourceId` | Application identifier | `TrackerConfiguration.appId` | | ||
| `sourcePlatform` | Platform of the current device | `TrackerController.devicePlatform` | | ||
| `reason` | Custom information or identifier | Custom string | | ||
Comment on lines
+227
to
+231
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. Should this note what is/isn't enabled by default, and perhaps the reasoning for that? E.g. |
||
|
||
<Tabs groupId="platform" queryString> | ||
<TabItem value="ios" label="iOS" default> | ||
|
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.
Subdomains should be covered by
discoverRootDomain
(now the default), so I'm hesitant to put it here unqualified as it's a bit misleading. It's usually a special case to want per-subdomain identities and need these settings to apply there.