Anonymous tracking
Snowplow enables you to track events without collecting personally identifiable information (PII). Use anonymous tracking to respect user privacy preferences, comply with regulations such as GDPR, or track events before a user has provided consent.
Every Snowplow event includes a number of identifiers. Read more about them in the overview and out-of-the-box tracking pages. You can configure your trackers to prevent the collection of these identifiers, as well as IP addresses and cookies, using anonymous tracking.
Some Snowplow trackers also provide options for tracking user consent interactions and GDPR basis for processing.
Anonymization levels
Snowplow trackers support multiple levels of anonymization to balance privacy requirements with analytics needs. Combine client-side and server-side anonymization to achieve the desired level of privacy.
As well as anonymous tracking, you can also use enrichments to pseudonymize or mask identifiers for tracked events, before they arrive at the data warehouse. This uses the PII pseudonymization or IP anonymization enrichments.
For more details on web cookie behavior, see Cookies and local storage.
Some tracker APIs use the British English spelling: "anonymisation" rather than "anonymization".
Full client-side anonymization
When configured for full client-side anonymization, the tracker does not track any client-side user or session identifiers. Events can still be collected, but can't be grouped by user or session.
Here's some example code for enabling full client-side anonymization when creating a tracker on web or mobile:
- JavaScript
- iOS
- Android
snowplow('newTracker', 'sp', '{{collector_url_here}}', {
// No user or session identifiers will be added to events
// Network identifiers will be tracked
anonymousTracking: true,
});
By default, the tracker uses cookies and local storage to persist user and session information, as well as for buffering events. When anonymous tracking is enabled, identifiers are not saved to cookies or local storage.
Snowplow.createTracker(namespace: "appTracker", endpoint: "https://snowplow-collector-url.com") {
TrackerConfiguration()
.userAnonymisation(true) // User identifiers in mobile entity (IDFA and IDFV) will not be tracked
.sessionContext(false) // Session entity won't be added to events
// Network identifiers will be tracked
}
createTracker(
applicationContext,
"appTracker",
NetworkConfiguration("https://snowplow-collector-url.com"),
TrackerConfiguration("appId")
.userAnonymisation(true) // User identifiers in mobile entity (IDFA and IDFV) will not be tracked
.sessionContext(false) // Session entity won't be added to events
// Network identifiers will be tracked
)
Client-side anonymization with session tracking
In this mode, the tracker doesn't include user identifiers but preserves session tracking. You can analyze session-level behavior without identifying individual users.
Here's some example code for enabling client-side anonymization with session tracking when creating a tracker on web or mobile:
- JavaScript
- iOS
- Android
snowplow('newTracker', 'sp', '{{collector_url_here}}', {
// User identifiers won't be added to events
// Session and network identifiers will be tracked
anonymousTracking: { withSessionTracking: true },
});
The tracker uses cookies and local storage by default. With this configuration it will store session identifiers, but not user identifiers.
Snowplow.createTracker(namespace: "appTracker", endpoint: "https://snowplow-collector-url.com") {
TrackerConfiguration()
.userAnonymisation(true) // User identifiers in mobile entity (IDFA and IDFV) will not be tracked
.sessionContext(true) // Session entity will be added to events but with userId as a null UUID
// Network identifiers will be tracked
}
createTracker(
applicationContext,
"appTracker",
NetworkConfiguration("https://snowplow-collector-url.com"),
TrackerConfiguration("appId")
.userAnonymisation(true) // User identifiers in mobile entity (IDFA and IDFV) will not be tracked
.sessionContext(true) // Session entity will be added to events but with userId as a null UUID
// Network identifiers will be tracked
)
Server-side anonymization
Server-side anonymization prevents the event Collector setting the sp cookie for network_userid, or from capturing IP addresses.
Setting server-side anonymization will add a SP-Anonymous HTTP header to requests sent to the Collector. This requires the request method to be POST, which is the default for most trackers. When the SP-Anonymous header is present, the Collector doesn't set or read the sp cookie.
An alternative method for preventing IP address tracking is to set a null value, such as 0.0.0.0 within the tracker. Most Snowplow trackers support this option, although not the JavaScript trackers.
In the JavaScript trackers, setting server-side anonymization also sets full client-side anonymization. In the native mobile trackers, it's a separate configuration. You can choose either client-side anonymization, server-side anonymization, or both.
Here's some example code for enabling server-side anonymization when creating a tracker on web or mobile:
- JavaScript
- iOS
- Android
snowplow('newTracker', 'sp', '{{collector_url_here}}', {
// No user, session, or network identifiers will be tracked
anonymousTracking: { withServerAnonymisation: true },
});
For fully cookieless web tracking, configure the tracker with:
snowplow('newTracker', 'sp', '{{collector_url_here}}', {
// No user, session, or network identifiers will be tracked
// No data will be stored in the browser
anonymousTracking: { withServerAnonymisation: true },
stateStorageStrategy: 'none',
});
This configuration prevents the tracker from storing any data in cookies or local storage.
Snowplow.createTracker(namespace: "appTracker", endpoint: "https://snowplow-collector-url.com") {
// User and session identifiers will be tracked
// Network identifiers won't be added to events
EmitterConfiguration().serverAnonymisation(true)
}
createTracker(
applicationContext,
"appTracker",
NetworkConfiguration("https://snowplow-collector-url.com"),
// User and session identifiers will be tracked
// Network identifiers won't be added to events
EmitterConfiguration().serverAnonymisation(true)
)
Tracker support
This table shows the support for anonymous tracking across the main Snowplow tracker SDKs:
| Tracker | Supported | Since version | Client-side | Server-side | Notes |
|---|---|---|---|---|---|
| Web | ✅ | 3.0.0 | ✅ | ✅ | |
| iOS | ✅ | 4.0.0 | ✅ | ✅ | |
| Android | ✅ | 4.0.0 | ✅ | ✅ | |
| React Native | ❌/✅ | 1.3.0 | ❌/✅ | ✅ | Version 4.x only supports server-side anonymization |
| Flutter | ✅ | 0.3.0 | ✅ | ✅ | |
| Roku | ✅ | 0.3.0 | ✅ | ✅ | Use Subject configuration to manage client-side anonymization |
| Node.js | ✅ | 3.21.0 | ❌ | ✅ | |
| Golang | ❌ | ||||
| .NET | ❌ | ||||
| Java | ❌ | ||||
| Python | ❌ | ||||
| Scala | ❌ | ||||
| Ruby | ❌ | ||||
| Rust | ❌ | ||||
| PHP | ✅ | 0.9.0 | ❌ | ✅ | |
| C++ | ❌ | ||||
| Unity | ❌ | ||||
| Lua | ❌ | ||||
| Google Tag Manager | ✅ | v4 | ✅ | ✅ |
Toggle anonymous tracking
As well as setting it at tracker initialization, you can enable or disable anonymous tracking during a session. Use this to start with anonymous tracking until a user accepts a cookie banner, or to enable full tracking when a user logs in.
Here's some example code for toggling anonymization at runtime on web or mobile:
- JavaScript
- iOS
- Android
snowplow('enableAnonymousTracking');
snowplow('disableAnonymousTracking');
These methods also accept an optional configuration object to specify which levels of anonymization to enable.
tracker.userAnonymisation = true
tracker.sessionContext = true
tracker.emitter?.serverAnonymisation = true
tracker.userAnonymisation = true
tracker.sessionContext = true
tracker.emitter.serverAnonymisation = true
On web, enabling anonymous tracking removes user identifiers from outgoing events but doesn't delete existing cookies. On mobile, toggling anonymization starts a new session.
Clear user data
When enabling anonymous tracking, you may want to clear any existing user identifiers stored in cookies or local storage.
Use the clearUserData() method in the JavaScript trackers to delete all data stored in the _sp_id and _sp_ses cookies. It takes an optional configuration object to specify which identifiers to clear. To delete the network_userid in the Collector sp cookie, set server-side anonymization.
There's no equivalent API for deleting stored data on mobile.
Anonymizable event properties
Use anonymous tracking to avoid collecting the following identifiers in your events. The table shows how you can anonymize each identifier using client-side anonymization, server-side anonymization, or enrichments.
Snowplow events have two properties with similar names: the user_id atomic event property and the userId property in the session entity.
The former is a business user identifier you set via the tracker API, while the latter is a device ID generated by the tracker. Both can be anonymized using client-side anonymization.
| Property | Location in event | Identifier type | Description | Client-side anon | Server-side anon | Enrichment |
|---|---|---|---|---|---|---|
domain_userid | Atomic | User | UUID stored in a first-party cookie | ✅ | ✅ PII | |
domain_sessionid | Atomic | Session | UUID for the current session | ✅ | ✅ PII | |
domain_sessionidx | Atomic | Session | Count of sessions for this user | ✅ | ||
network_userid | Atomic | Network | UUID set by the Collector in a server-side cookie | ✅ | ✅ PII | |
user_ipaddress | Atomic | Network | IP address captured by the Collector | ✅ | ✅ PII, IP anonymization | |
user_id in atomic fields | Atomic | User | Business user identifier set via setUserId or similar API | ✅ | ✅ PII | |
userId in session entity | Entity | User | Device ID in the client session entity | ✅ | ||
sessionId | Entity | Session | UUID for the session | ✅ | ||
appleIdfa | Entity | User | Advertising identifier (IDFA) on iOS | ✅ | ||
appleIdfv | Entity | User | Vendor identifier (IDFV) on iOS | ✅ | ||
androidIdfa | Entity | User | Advertising identifier on Android | ✅ | ||
tabId | Entity | User | UUID for the browser tab | ✅ |
The PII pseudonymization enrichment supports an anonymousOnly mode, available since Enrich version 5.3.0, that only pseudonymizes fields when the SP-Anonymous header is present. This lets you keep full identifiers for consented users while anonymizing non-consented users.
It can also pseudonymize fields for structured and legacy ecommerce events, as well as these fields that are populated during enrichment:
| Property | Location in event | Identifier type | Description |
|---|---|---|---|
refr_domain_userid | Atomic | User | From cross-domain tracking |
ip_organization | Atomic | User | Added by IP enrichment |
ip_domain | Atomic | User | Added by IP enrichment |
mkt_term | Atomic | Marketing | Added by campaign attribution enrichment |
mkt_content | Atomic | Marketing | Added by campaign attribution enrichment |
mkt_clickid | Atomic | Marketing | Added by campaign attribution enrichment |