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

ParameterTypeRequiredDescription
customerIdsString / Number / ObjectYesThe customer's unique identifier.
customerPropertiesObjectNoCustomer attributes to set at the time of identification.
successCallbackFunctionNoCalled after the event is successfully sent to the API.
errorCallbackFunctionNoCalled when an error occurs.
immediateBooleanNoDefaults 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

ParameterTypeRequiredDescription
customerAttributesObjectYesThe 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:

AttributeUsed for
first_name, last_name, company_nameDisplayed in the customer profile view
photoProfile photo URL, displayed in the customer profile view
emailEmail campaigns
phoneSMS campaigns. Use full international format: +421905123456
languageMulti-language projects. Must match the format defined in project settings.
domainMulti-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

ParameterTypeRequiredDescription
eventNameStringYesThe name of the event.
eventPropertiesObjectNoProperties to attach to the event. Maximum 255 entries.
successCallbackFunctionNoCalled after the event is successfully tracked.
errorCallbackFunctionNoCalled when an error occurs.

Default properties

The SDK automatically appends the following properties to every tracked event:

PropertyDescriptionExample
osVisitor's operating systemiOS
browserVisitor's browserChrome
deviceVisitor's device typeiPhone
locationCurrent page URLhttps://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 successCallback parameter 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

ParameterTypeRequiredDescription
selectorString / ElementYesCSS selector of the element or elements to track.
eventNameStringYesThe name of the event.
eventPropertiesObjectNoProperties 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

ParameterTypeRequiredDescription
ecommerceObjectObjectYesA Google Analytics Enhanced Ecommerce object. See the GA Enhanced Ecommerce documentation.
kindStringNoThe 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_click
  • search_submit
Deferred eventDiscovery parameters
suggest_clickdf_etype=click, df_group=suggest, df_type=event
suggest_submitdf_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_homepage
  • view_category
  • view_item
  • view_search_results
  • view_content
  • view_thematic
  • view_other

Deferred property mapping

The table below shows how deferred suggest_click properties map to Discovery parameters on the following page view.

Deferred event propertyDiscovery parameter
qdf_q
aqdf_aq
catalogsdf_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

CookieDescriptionTypeDefault expiration
__exponea_etc__Visitor's client-side tracking cookieFirst-party, client-side7 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-side3 years
__exponea_time2__Timestamp offset between browser and server timeFirst-party, client-side60 minutes
__exponea_ab_[ABTestName]__A/B test variant name. Populated when brweb.getAbTest() is called. Not used for Experiments or weblayers.First-party, client-side7 days – 3 years (browser-dependent)
_br_uid_2Bloomreach Discovery visitor cookie. Used by Discovery for personalization and analytics. See the Discovery cookie reference.First-party, client-sideSet by Discovery
_cdp_segmentsExposes 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-sideRefreshed 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 Date object. 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.

KeyDescription
__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_showTimestamp of the last time a specific weblayer was shown to the visitor.
__exponea_banner_event__[BANNER_ID]_last_interactionTimestamp 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.

KeyDescription
__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.