Enable anonymous tracking with the Flutter tracker
Anonymous tracking is a feature that enables anonymization of various user and session identifiers, to support user privacy when consent for tracking the identifiers isn't given.
This table shows the user and session identifiers that can be anonymized on web and mobile:
| Identifier | Location in event | Tracked on web | Tracked on mobile |
|---|---|---|---|
user_id | Atomic | ✅ | ✅ |
domain_userid | Atomic | ✅ Non-configurable | ✅ |
domain_sessionid | Atomic | ✅ Non-configurable | ❌ |
domain_sessionidx | Atomic | ✅ Non-configurable | ❌ |
userId | Session entity | ✅ Non-configurable, same as domain_userid | ✅ Non-configurable |
sessionId | Session entity | ✅ Non-configurable | ✅ Non-configurable |
previousSessionId | Session entity | ✅ Non-configurable | ✅ Non-configurable |
appleIdfa | Mobile (platform) entity | ❌ | ✅ |
appleIdfv | Mobile (platform) entity | ❌ | ✅ |
androidIdfa | Mobile (platform) entity | ❌ | ✅ |
network_userid | Atomic | ✅ Non-configurable | ✅ |
user_ipaddress | Atomic | ✅ Non-configurable | ✅ |
You can set some of these properties at tracker initialization.
The Collector captures the IP address from the request HTTP headers, and updates the user_ipaddress event property. However, if you set the user_ipaddress property at initialization, that value has priority.
Similarly, if you set the network_userid property, that value is used instead of the Collector cookie value.
Read more about anonymous tracking in the overview page.
As well as setting these flags at initialization, from version 0.10.0 you can change them at runtime on an existing tracker, without recreating it. See Changing anonymisation at runtime below.
There are several levels to the anonymization depending on which of the categories are affected.
1. Full client-side anonymization
In this case, we want to anonymize both the client-side user identifiers as well as the client-side session identifiers. Here the Session entity is not configured: no session information will be tracked at all.
const TrackerConfiguration()
.userAnonymisation(true)
.sessionContext(false)
.platformContext(true) // only relevant for mobile
On web, setting userAnonymisation stops any user identifiers or session information being stored in cookies or localStorage. This means that domain_userid, domain_sessionid, and domain_sessionidx will be anonymized. These properties are already not present in any mobile events.
On mobile, setting userAnonymisation affects properties in the Session and Platform entities. In this example, the Platform entity is enabled. The appleIdfv Platform property would be anonymized, as well as appleIdfa/androidIdfa if your app is configured to track those.
- Web
- Mobile
| Identifier | Location in event | Included in event? |
|---|---|---|
user_id | Atomic | ❌ |
domain_userid | Atomic | ❌ |
domain_sessionid | Atomic | ❌ |
domain_sessionidx | Atomic | ❌ |
userId | Session entity | ❌ no session entity |
sessionId | Session entity | ❌ no session entity |
previousSessionId | Session entity | ❌ no session entity |
appleIdfa | Mobile (platform) entity | N/A |
appleIdfv | Mobile (platform) entity | N/A |
androidIdfa | Mobile (platform) entity | N/A |
network_userid | Atomic | ✅ |
user_ipaddress | Atomic | ✅ |
| Identifier | Location in event | Included in event? |
|---|---|---|
user_id | Atomic | ❌ |
domain_userid | Atomic | ❌ |
domain_sessionid | Atomic | N/A |
domain_sessionidx | Atomic | N/A |
userId | Session entity | ❌ no session entity |
sessionId | Session entity | ❌ no session entity |
previousSessionId | Session entity | ❌ no session entity |
appleIdfa | Mobile (platform) entity | ❌ |
appleIdfv | Mobile (platform) entity | ❌ |
androidIdfa | Mobile (platform) entity | ❌ |
network_userid | Atomic | ✅/❌ removed if you set this |
user_ipaddress | Atomic | ✅/❌ removed if you set this |
2. Client-side anonymization with session tracking
This setting disables client-side user identifiers but tracks session information.
const TrackerConfiguration()
.userAnonymisation(true)
.sessionContext(true)
.platformContext(true) // only relevant for mobile
Enabling both userAnonymisation and sessionContext means that events will have the Session entity, but the userId property will be anonymised to a null UUID (00000000-0000-0000-0000-000000000000). The sessionId and sessionIndex are still present, as are domain_sessionid and domain_sessionidx for web events. As above, if the Platform entity is enabled, the IDFA identifiers will not be present.
- Web
- Mobile
| Identifier | Location in event | Included in event? |
|---|---|---|
user_id | Atomic | ❌ |
domain_userid | Atomic | ❌ |
domain_sessionid | Atomic | ✅ |
domain_sessionidx | Atomic | ✅ |
userId | Session entity | ❌ null UUID |
sessionId | Session entity | ✅ |
previousSessionId | Session entity | ❌ |
appleIdfa | Mobile (platform) entity | N/A |
appleIdfv | Mobile (platform) entity | N/A |
androidIdfa | Mobile (platform) entity | N/A |
network_userid | Atomic | ✅ |
user_ipaddress | Atomic | ✅ |
| Identifier | Location in event | Included in event? |
|---|---|---|
user_id | Atomic | ❌ |
domain_userid | Atomic | ❌ |
domain_sessionid | Atomic | N/A |
domain_sessionidx | Atomic | N/A |
userId | Session entity | ❌ null UUID |
sessionId | Session entity | ✅ |
previousSessionId | Session entity | ❌ |
appleIdfa | Mobile (platform) entity | ❌ |
appleIdfv | Mobile (platform) entity | ❌ |
androidIdfa | Mobile (platform) entity | ❌ |
network_userid | Atomic | ✅/❌ removed if you set this |
user_ipaddress | Atomic | ✅/❌ removed if you set this |
3. Server-side anonymization
Server-side anonymization affects user identifiers set server-side. In particular, these are the network_userid property set in server-side cookie and the user IP address (user_ipaddress). You can anonymize the properties using the serverAnonymisation flag in EmitterConfiguration:
const EmitterConfiguration()
.serverAnonymisation(true)
Setting this will add a SP-Anonymous HTTP header to requests sent to the Snowplow collector. The Snowplow pipeline will anonymize the identifiers.
On mobile, serverAnonymisation and userAnonymisation are separate. This means you can anonymize only the server-side identifiers without also anonymizing the client-side identifiers.
On web, setting serverAnonymisation provides full anonymization. It's effectively a subset of userAnonymisation. If serverAnonymisation is enabled, this will also set userAnonymisation to true (even if set to false in your TrackerConfiguration).
- Web
- Mobile
| Identifier | Location in event | Included in event? |
|---|---|---|
user_id | Atomic | ❌ |
domain_userid | Atomic | ❌ |
domain_sessionid | Atomic | ❌ |
domain_sessionidx | Atomic | ❌ |
userId | Session entity | ❌ no session entity |
sessionId | Session entity | ❌ no session entity |
previousSessionId | Session entity | ❌ no session entity |
appleIdfa | Mobile (platform) entity | N/A |
appleIdfv | Mobile (platform) entity | N/A |
androidIdfa | Mobile (platform) entity | N/A |
network_userid | Atomic | ❌ |
user_ipaddress | Atomic | ❌ |
| Identifier | Location in event | Included in event? |
|---|---|---|
user_id | Atomic | ✅ |
domain_userid | Atomic | ✅ |
domain_sessionid | Atomic | N/A |
domain_sessionidx | Atomic | N/A |
userId | Session entity | ✅ |
sessionId | Session entity | ✅ |
previousSessionId | Session entity | ✅ |
appleIdfa | Mobile (platform) entity | ✅ |
appleIdfv | Mobile (platform) entity | ✅ |
androidIdfa | Mobile (platform) entity | ✅ |
network_userid | Atomic | ❌/✅ still present if you set this |
user_ipaddress | Atomic | ❌/✅ still present if you set this |
4. Full anonymization for mobile
For full anonymization on mobile, set both client-side and server-side anonymization.
const TrackerConfiguration()
.userAnonymisation(true)
.sessionContext(false)
.platformContext(true) // only relevant for mobile
const EmitterConfiguration()
.serverAnonymisation(true)
| Identifier | Location in event | Included in event? |
|---|---|---|
user_id | Atomic | ❌ |
domain_userid | Atomic | ❌ |
domain_sessionid | Atomic | N/A |
domain_sessionidx | Atomic | N/A |
userId | Session entity | ❌ no session entity |
sessionId | Session entity | ❌ no session entity |
previousSessionId | Session entity | ❌ no session entity |
appleIdfa | Mobile (platform) entity | ❌ |
appleIdfv | Mobile (platform) entity | ❌ |
androidIdfa | Mobile (platform) entity | ❌ |
network_userid | Atomic | ❌ |
user_ipaddress | Atomic | ❌ |
Changing anonymisation at runtime
This feature is only available on mobile (Android and iOS).
The userAnonymisation and serverAnonymisation flags described above are normally set at tracker initialization. You can also change them at runtime on an existing tracker, for example when a user updates their tracking consent, without recreating the tracker:
// On the tracker instance:
await tracker.setUserAnonymisation(true);
await tracker.setServerAnonymisation(true);
// Or via the static API, using the tracker namespace:
await Snowplow.setUserAnonymisation(true, tracker: 'ns1');
await Snowplow.setServerAnonymisation(true, tracker: 'ns1');
This avoids recreating the tracker (and therefore resetting identifiers) just to change the anonymisation level. The new setting applies to all events tracked afterwards, with the same effect as setting the flag at initialization.
Changing userAnonymisation starts a new session. The tracker instance and the user identifier are preserved, but the sessionId changes. setServerAnonymisation does not affect the session.
These methods are only available on mobile (Android and iOS). On Web they throw an Unimplemented PlatformException.