Skip to main content

Tracking specific client-side properties

An event describes a single, transient activity. The context in which that event occurs - the relatively persistent environment - is also incredibly valuable data. As discussed on the previous page, the most powerful way to track such data is to use custom self-describing JSON entities. These are sent as JSON in the raw event payload. Depending on your data warehouse, event context entities are loaded into their own tables, or remain as JSON in the loaded event.

The Java tracker provides an additional "canonical" method to track a small subset of contextual data, using the Subject class. As with the "canonical" Event types, e.g. PageView, Subject properties directly populate the "atomic" fields of the raw event payload. These data will always end up in individual columns of the main event table in the data warehouse.

The fields tracked using Subject tend to be most relevant in client-side tracking. Some are set automatically in all events during enrichment, even when no Subject is added. These properties are marked with * below, and discussed below. Timezone, marked with **, is set when a Subject is tracked with the event.

Add these fields to an event using Subject:

PropertyField in raw eventColumn(s) in enriched event
viewportvpbr_viewheight, br_viewwidth
screenResolutionresdvce_screenheight, dvce_screenwidth

Note: the ability to set domainSessionId was added in version 0.11.

These properties are especially useful for client-side tracking, or for linking client-side and server-side tracking. We highly recommend tracking in both client-side and server-side, if it's relevant to your application. Read more about this in these blog posts.

If you are also using the Javascript tracker, it will set cookies in the browser. The Subject properties domainUserId, and domainSessionId are intended to be used for extracted cookie values passed to the Java tracker. If you want to track other identification tokens, we recommend creating schemas and using context entities.

As always, be aware of privacy when tracking personal identifiable information such as email addresses or IP addresses.

Overriding autogenerated event properties

All enriched Snowplow events contain values for user_ipaddress, useragent, and network_userid.

The user_ipaddress is automatically added to all enriched events. To manually override this, use a Subject and set a ipAddress string; use an empty string to prevent IP address tracking. Alternatively, use the IP anonymization enrichment.

The useragent is also automatically added during enrichment. Snowplow pipelines provide multiple useragent-parsing enrichments. To manually override the detected useragent, use a Subject and set a useragent string. For the default Tracker configuration with OkHttp, the default useragent will be "okhttp/4.2.2".

The network_userid is the cookie value for the event collector’s third-party cookie. It is the server-side user identifier. The cookie is named sp (or micro for Snowplow Micro pipelines). The default behaviour is for the collector to provide a new cookie/network_userid for each event it receives. To override the collector cookie’s value with your own generated ID, use a Subject object and set networkUserId. Alternatively, configure a CookieJar to persist the sp cookie, and the network_userid, across requests (see here).

A further property, timezone, is generated automatically during Subject initialization, based on Calendar.getInstance().getTimeZone(). Therefore, this will be added to all events with a Subject attached. The default will be overriden if timezone is provided explicitly.

Adding Subject properties to events

There are two ways to track the Subject "atomic" properties in your events: on an event-by-event basis; or globally, to affect all events. A combination of both methods is also possible.

A simple Subject initialisation looks like this:

SubjectConfiguration subjectConfig = new SubjectConfiguration()
Subject subject = new Subject(subjectConfig);

In this case only the userId (and timezone) were set. There are no required properties for the SubjectConfiguration.

A Subject can be added to any event using the subject() Event.Builder method:

// This example shows an SelfDescribing event, but all events can have a Subject
SelfDescribing selfDescribing = SelfDescribing.builder()

To set Subject properties in all subsequent events, add a Subject to your Tracker object:

// A Subject can be provided at Tracker initialisation
// Indirectly, using the Snowplow interface and a SubjectConfiguration object
SubjectConfiguration subjectConfig = new SubjectConfiguration().useragent("useragent");
Tracker tracker = Snowplow.createTracker(
new TrackerConfiguration("trackerNamespace", "appId"),
new NetworkConfiguration("http://collector-url"),

// Creating a Tracker directly using Subject and Emitter objects
Subject subject = new Subject();
BatchEmitter emitter = new BatchEmitter(new NetworkConfiguration("http://endpoint"));
Tracker tracker = new Tracker(new TrackerConfiguration("trackerNamespace", "appId"), emitter, subject);

// Alternatively, a Subject can be set later
Tracker tracker = Snowplow.createTracker("trackerNamespace", "appId", "http://collectorEndpoint");
Subject subject = new Subject();

Subject properties can be updated or added to after initialization, using setter methods. See the API docs for full details.

It's possible to use both Event-specific and Tracker-associated Subject objects simultaneously. Fields from both Subject objects are added to the payload, with the Event-specific Subject having priority.

// Adding a global, Tracker-associated Subject
SubjectConfiguration trackerSubjectConfig = new SubjectConfiguration()

Tracker tracker = Snowplow.createTracker(
new TrackerConfiguration("trackerNamespace", "appId"),
new NetworkConfiguration("http://collector-url"),

// Adding an Event-specific Subject
SubjectConfiguration eventSubjectConfig = new SubjectConfiguration()

SelfDescribing selfDescribing = SelfDescribing.builder()
.subject(new Subject(eventSubjectConfig))

// Tracking the event

The resulting enriched event would have these Subject atomic columns populated:

Column in enriched eventValue / example valueSource
os_timezonee.g. "Europe/London"eventSubject
network_useride.g. "8383057f-2769-4321-ad72-58fa1b22e4b3"pipeline