Customer identification and tracking
The Bloomreach Web SDK inherits its tracking functionality from the Engagement JavaScript SDK. This means all standard tracking methods — customer identification, event tracking, and link tracking — work the same way. This page documents those methods in full and covers the additional functionality unique to the Web SDK: deferred events, metadata, and the backwards compatibility alias.
For the full list of events you need to implement, see Required events.
Customer identification
The SDK tracks all visitors as anonymous customers by default, assigning each one a unique cookie-based ID. When a visitor logs in or registers, use identify() to link their anonymous events to a named customer profile. All events tracked before identification are automatically transferred to the identified profile — no data is lost.
identify()
Use identify() to associate the current visitor with a known customer identity, such as their email address or an internal user ID.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
customerIds | String / Number / Object | Yes | The customer's unique identifier. |
customerProperties | Object | No | Customer attributes to set at the time of identification. |
successCallback | Function | No | Called after the event is successfully sent to the API. |
errorCallback | Function | No | Called when an error occurs. |
immediate | Boolean | No | Defaults to false. When true, the SDK sends the request immediately rather than batching it. |
Example
If your hard ID is registered (the SDK default), pass the email directly:
brweb.identify('[email protected]');
If your hard ID has a different name, pass it as an object:
brweb.identify({ your_hard_id: '[email protected]' });
To identify a customer and set attributes at the same time:
brweb.identify(
{
registered: '[email protected]',
user_id: 'user_id_123'
},
{
email: '[email protected]',
first_name: 'Gordon',
last_name: 'Freeman'
},
function() { /* successCallback */ },
function() { /* errorCallback */ },
false
);
Best practices
Email: Always pass a lowercased and trimmed email address.
var email = customerEmailFromWebsite.toLowerCase().trim();
Custom IDs: When using a custom identifier such as an internal user_id, make sure the attribute exists in your Bloomreach Engagement project under Administration > Projects > Your project > Identifiers. Calls using unrecognized identifiers are discarded.
Re-identification: If you want to add a second identifier to a customer already identified by email, pass both identifiers in the same identify() call. Passing only the new identifier creates a separate customer profile.
// correct: pass both identifiers together
brweb.identify({
registered: '[email protected]',
user_id: 'user_id_123'
});
Cookies: Do not set a cookie field value in customerIds — it is ignored.
Note
If you use server-side caching on your website, make sure the
identify()call is not included in cached content.
update()
Use update() to set or update customer attributes at any point — not just at the time of identification. If an attribute doesn't exist, it's created automatically.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
customerAttributes | Object | Yes | The attributes to set or update. Maximum 255 attributes per customer (128 Kbit per attribute), or 1,024 attributes (2 KiB per attribute), depending on your contract. |
Special attributes
The following attribute names have specific roles in Bloomreach:
| Attribute | Used for |
|---|---|
first_name, last_name, company_name | Displayed in the customer profile view |
photo | Profile photo URL, displayed in the customer profile view |
email | Email campaigns |
phone | SMS campaigns. Use full international format: +421905123456 |
language | Multi-language projects. Must match the format defined in project settings. |
domain | Multi-domain tracking under a single account |
Example
brweb.update({
email: '[email protected]',
first_name: 'Gordon',
last_name: 'Freeman',
company: 'Blackmesa'
});
anonymize()
Use anonymize() to reset the current visitor's cookie and start tracking them as a new anonymous customer. This is useful when multiple people share the same device — for example, after a logout. All events and attributes tracked under the original cookie remain stored in the original customer profile.
brweb.anonymize();
Push notification implications
By default, anonymize() does not remove the browser push notification token from the original profile. To move the push token to the new profile, unsubscribe before anonymizing:
brweb.notifications.unsubscribe(status => {
if (status === 'unsubscribed') {
brweb.anonymize();
brweb.notifications.subscribe();
}
});
Weblayer implications
By default, anonymize() does not hide or re-trigger currently displayed weblayers. To re-trigger weblayers for the new anonymous profile, call reloadWebLayers() after anonymizing:
brweb.anonymize();
brweb.reloadWebLayers();
Note
anonymize()does not reset Google Analytics IDs. If you use Google Analytics retargeting, the new anonymous profile may merge back into the original customer profile immediately.
Event tracking
Use the following methods to track customer actions on your website. You can track up to 255 event types, each with up to 255 attributes (up to 128 Kbit per attribute).
Note
Only use ASCII characters for event and attribute names.
track()
Use track() to record any customer action as a named event with optional properties.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
eventName | String | Yes | The name of the event. |
eventProperties | Object | No | Properties to attach to the event. Maximum 255 entries. |
successCallback | Function | No | Called after the event is successfully tracked. |
errorCallback | Function | No | Called when an error occurs. |
Default properties
The SDK automatically appends the following properties to every tracked event:
| Property | Description | Example |
|---|---|---|
os | Visitor's operating system | iOS |
browser | Visitor's browser | Chrome |
device | Visitor's device type | iPhone |
location | Current page URL | https://www.example.com/contact |
Example
brweb.track('purchase', {
purchase_status: 'created',
product_list: [
{ product_id: 'abc123', quantity: 2 },
{ product_id: 'abc456', quantity: 1 }
],
total_price: 99.98,
payment_type: 'credit_card'
});
Note
Event tracking is asynchronous. If you need to track an event before navigating to a new page — for example, a consent event — use the
successCallbackparameter to wait for confirmation before redirecting.
trackLink()
Use trackLink() to track clicks on any element on your page using a CSS selector. If the selector matches multiple elements, the event fires on all of them.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
selector | String / Element | Yes | CSS selector of the element or elements to track. |
eventName | String | Yes | The name of the event. |
eventProperties | Object | No | Properties to attach to the event. |
Example
brweb.trackLink('#external-link', 'external_link_click', {
destination: 'partner-site'
});
trackEnhancedEcommerce()
Use trackEnhancedEcommerce() to push existing Google Analytics Enhanced Ecommerce data into Bloomreach Engagement. The SDK tracks the event with the provided properties, the default event properties, and a tracked_via: 'ecommerce' attribute.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
ecommerceObject | Object | Yes | A Google Analytics Enhanced Ecommerce object. See the GA Enhanced Ecommerce documentation. |
kind | String | No | The GA Enhanced Ecommerce event type. Defaults to 'all'. Accepted values: click, detail, add, remove, promoView, promoClick, checkout, checkout_option, purchase, refund, all. |
Example
brweb.trackEnhancedEcommerce(
{
// pass the same attributes as your GA Enhanced Ecommerce tracking
},
'detail'
);
Additional functionalities
The Web SDK extends the Engagement JavaScript SDK with three capabilities that aren't available in the Engagement SDK: deferred events, metadata, and a switch for Real-time segments.
Deferred events
Deferred events are interaction events that Discovery attaches to the next page view rather than processing immediately. This lets Discovery correlate the user's intent — such as a search query or suggestion click — with the resulting page view.
The SDK defers the following events automatically:
suggest_clicksearch_submit
| Deferred event | Discovery parameters |
|---|---|
suggest_click | df_etype=click, df_group=suggest, df_type=event |
suggest_submit | df_etype=submit, df_group=suggest, df_type=event |
These events are attached as a deferred_event object on the next page view event. Properties from the deferred event are appended to the page view event with a df_ prefix. For example, the q property from a deferred search_submit event becomes df_q on the following view_search_results event.
The following page view events accept a deferred event:
view_homepageview_categoryview_itemview_search_resultsview_contentview_thematicview_other
Deferred property mapping
The table below shows how deferred suggest_click properties map to Discovery parameters on the following page view.
| Deferred event property | Discovery parameter |
|---|---|
q | df_q |
aq | df_aq |
catalogs | df_catalogs |
Metadata
The metadata object in the SDK configuration passes Discovery-specific properties with every tracked event. These properties tell Discovery which catalog and catalog view to use, and control whether events are processed in test or debug mode.
You configure metadata once in the initialization snippet — the SDK then appends it automatically to every event sent to the API. For configuration details and accepted values, see Bloomreach Web SDK — Metadata.
Real-time segments
Real-time segments (RTS) are disabled by default. When enabled, the SDK fetches the current customer's segment data from Engagement and passes it to Discovery via the _br_uid_2 cookie on every page load. This lets Discovery personalize results based on live segment membership.
To enable RTS, add the following to your configuration object:
cdp_segments: {
rts: true
}
The segment's value refreshes in the following situations:
- On every page load during tracker start.
- When the URL changes (SPA navigation).
- Five seconds after any event is tracked (post-track refresh).
- When the user's identity changes.
Note
Segment refreshes are asynchronous. Page view events do not wait for the latest segment values before being sent to Discovery.
Cookies
The Web SDK sets the same cookies as the Engagement JavaScript SDK, plus two additional cookies for Discovery.
Cookie reference
| Cookie | Description | Type | Default expiration |
|---|---|---|---|
__exponea_etc__ | Visitor's client-side tracking cookie | First-party, client-side | 7 days – 3 years (browser-dependent) |
xnpe_[stream-id] | Visitor's server-side tracking cookie. Holds the same value as __exponea_etc__ and helps maintain identity in browsers with aggressive client-side cookie expiration (for example, Safari). Works in combination with a custom tracking domain. | First-party (with CTD) or third-party, server-side | 3 years |
__exponea_time2__ | Timestamp offset between browser and server time | First-party, client-side | 60 minutes |
__exponea_ab_[ABTestName]__ | A/B test variant name. Populated when brweb.getAbTest() is called. Not used for Experiments or weblayers. | First-party, client-side | 7 days – 3 years (browser-dependent) |
_br_uid_2 | Bloomreach Discovery visitor cookie. Used by Discovery for personalization and analytics. See the Discovery cookie reference. | First-party, client-side | Set by Discovery |
_cdp_segments | Exposes the current visitor's real-time segment values on the customer domain. Set by the SDK when real-time segments are enabled. | First-party, client-side | Refreshed on each page load |
Cookie expiration
The default expiration of tracking cookies is reset on every page load. This means a visitor who returns regularly will never have their cookie expire in practice.
You can customize expiration in the configuration object passed to brweb.start(). There are two approaches: set a single value for all cookies, or configure each cookie category separately.
Set the same expiration for all cookies
brweb.start({
// ... your other config ...
cookies: {
expires: 182 * 24 * 3600 // 182 days, in seconds
}
});
Set different expirations per cookie category
brweb.start({
// ... your other config ...
cookies: {
expires: {
tracking: 365 * 24 * 3600, // 1 year
ab_test: 30 * 24 * 3600 // 30 days
}
}
});
Use a relative date
brweb.start({
// ... your other config ...
cookies: {
// Note: expires takes seconds, but Date takes milliseconds — hence * 1000
expires: new Date(Date.now() + 3600 * 24 * 1000) // always 1 day from now
}
});
Note: Always calculate expiration from the current date when using a
Dateobject. Never use an absolute date — when that date passes, the SDK reverts to the default expiration values.
Recommendations
The tracking cookie (__exponea_etc__) links anonymous sessions together and powers personalization and analytics. Set the expiration too short and the SDK can't stitch a returning visitor's sessions into a single profile. We recommend keeping the tracking cookie expiration at one year or longer.
The time cookie (__exponea_time2__) only synchronizes browser and server time. A 60-minute expiration is appropriate.
Note
The SDK cannot modify Google Analytics IDs. If you use Google Analytics retargeting, changing the cookie expiration has limited effect on customer profile merging.
Storage
Local storage
The SDK uses local storage to track experiment and weblayer display history, push notification state, and session timing. This data has no expiration.
| Key | Description |
|---|---|
__exponea_experiment_event[EXPERIMENT_ID]_last_show__ | Timestamp of the last time a specific experiment was shown to the visitor. Used by the frequency matcher. |
__exponea_experiment_event[EXPERIMENT_ID]_last_interaction__ | Timestamp of the visitor's last interaction with a specific experiment. Used by the frequency matcher. |
__exponea_safari_push_subscribed__ | Boolean indicating whether a push token has been stored for Safari web push notifications. |
__exponea_last_session_ping_timestamp__ | Timestamp of the visitor's last session ping. |
__exponea_last_session_start_timestamp__ | Timestamp of the visitor's last session start. |
__exponea_banner_event__[BANNER_ID]_last_show | Timestamp of the last time a specific weblayer was shown to the visitor. |
__exponea_banner_event__[BANNER_ID]_last_interaction | Timestamp of the visitor's last interaction with a specific weblayer. |
__exponea__sync_modifications__ | Present when you use the synchronous solution for Experiments. |
Session storage
The SDK caches tracking configuration in session storage for the duration of the browser tab session. This data expires when the tab or browser is closed.
| Key | Description |
|---|---|
__exponea_tracking_definition__ | Visitor-specific tracking definitions from Data Manager > Automatic web tracking. |
The SDK also uses session storage to track when the visitor's last session occurred, to determine whether a new page view continues the current session or starts a new one.
Note
Browser push notification actions may use IndexedDB as an additional data store. This data has no expiration and may contain personally identifiable information (PII) from push notification message content.
Updated 13 days ago
