New Search setup
This guide walks you through a new Bloomreach Web SDK implementation for Search. Follow these steps if you're starting from scratch with no existing Bloomreach tracking on your website and only need Search at this stage.
If you're setting up both Marketing and Search together, see Set up Marketing and Search.
Prerequisites
Before you start, make sure the following have been provisioned and you have access to:
- A Data hub workspace
- A Search account and organization
- DNS records configured for your custom tracking domain (CTD)
Add the tracking snippet
Add the snippet below to every page on your website. Place it in the <head> before the closing </head> tag. This placement is required for non-flickering experiments to work correctly.
ImportantDon't add the tracking snippet to payment gateways or pages that handle credit card data. Tracking scripts on payment pages can be exploited to intercept sensitive financial information.
You can also add it via Google Tag Manager if you manage scripts through a tag management system.
NoteGoogle Tag Manager only supports ES5 and throws a compilation error with the ES6-based JavaScript snippet. To avoid this:
- Add the snippet using a
<script type="text/gtmscript">tag instead of a standard<script>tag. This bypasses GTM's compilation step and allows the SDK to load correctly.- Remove the
new_experimentsconfiguration or explicitly setnew_experiments: false. GTM doesn't supportnew_experiments.
Replace the placeholder values with your actual credentials. See Find your credentials for instructions.
<style>.xnpe_async_hide{opacity:0 !important}</style>
<script>
!function(e,t,n,i,o,r){
const s=4e3,c="xnpe_async_hide";
function a(e){
if("number"!=typeof e)return e;
const t=new Date;
return new Date(t.getTime()+1e3*e)
}
function p(e){
return e.reduce((function(e,t){
return e[t]=function(){e._.push([t.toString(),arguments])},e
}),{_:[]})
}
function m(e,t,n){
const i=n.createElement(t);
i.src=e;
const o=n.getElementsByTagName(t)[0];
return o.parentNode.insertBefore(i,o),i
}
function l(e){
return"[object Date]"===Object.prototype.toString.call(e)
}
r.target=r.target||"//api.exponea.com",
r.file_path=r.file_path||r.target+"/js/brweb.min.js",
o[t]=p(["anonymize","initialize","identify","getSegments","update",
"track","trackLink","trackEnhancedEcommerce","getHtml","showHtml",
"showBanner","showWebLayer","ping","getAbTest","loadDependency",
"getRecommendation","reloadWebLayers","_preInitialize",
"_initializeConfig","metadata"]),
o[t].notifications=p(["isAvailable","isSubscribed","subscribe","unsubscribe"]),
o[t].segments=p(["subscribe"]),
o[t]["snippetVersion"]="v3.1.1",
function(e,t,n,i){
e[i]={sdk:e[n],sdkObjectName:n,skipExperiments:!!t.new_experiments,
path:t.target,streamId:t.stream_id}
}(o,r,t,i),
function(e,t,n){m(e.file_path,t,n)}(r,n,e),
function(e,t,n,i,o,r,p,u){
if(!e.new_experiments)return;
!0===e.new_experiments&&(e.new_experiments={});
const _=e.new_experiments.hide_class||c,
f=e.new_experiments.timeout||s,
d=encodeURIComponent(r.location.href);
let g;
e.cookies&&e.cookies.expires&&(
"number"==typeof e.cookies.expires||l(e.cookies.expires)
?g=a(e.cookies.expires)
:e.cookies.expires.tracking&&(
"number"==typeof e.cookies.expires.tracking||
l(e.cookies.expires.tracking)
)&&(g=a(e.cookies.expires.tracking)));
g&&g<new Date&&(g=void 0);
const b=
e.target+"/webxp/streams/"+e.stream_id+"/"+t+"/"+
(u.exec(p.cookie)||[0,"new"])[1]+
"/modifications.min.js?http-referer="+d+
"&timeout="+f+"ms"+
(g?"&cookie-expires="+Math.floor(g.getTime()/1e3):"");
"sync"===e.new_experiments.mode&&
r.localStorage.getItem("__exponea__sync_modifications__")
?function(e,t,n,i,o){
n[o][t]="<"+t+' src="'+e+'"></'+t+">";
i.writeln(n[o][t]);
i.writeln("<"+t+">!"+o+".init && document.writeln("+o+"."+t+
'.replace("/'+t+'/","/'+t+'-async/")'+
'.replace("><"," async><")</'+t+">)")
}(b,t,r,p,n)
:function(e,t,n,i,o,r,s,c){
r.documentElement.classList.add(e);
const a=m(n,i,r);
function p(){
o[c].init||m(n.replace("/"+i+"/","/"+i+"-async/"),i,r)
}
function l(){r.documentElement.classList.remove(e)}
a.onload=p,a.onerror=p,o.setTimeout(l,t),o[s]._revealPage=l
}(_,f,b,t,r,p,o,n)
}(r,n,i,0,t,o,e,RegExp("__exponea_etc__"+"=([\\w-]+)")),
function(e,t,n){
var i;
e[t]._initializeConfig(n);
(null===(i=n.experimental)||void 0===i
?void 0:i.non_personalized_weblayers)&&e[t]._preInitialize(n);
e[t].start=function(i){
i&&Object.keys(i).forEach((e=>n[e]=i[e]));
e[t].initialize(n)
}
}(o,t,r)
}(document,"brweb","script","webxpClient",window,{
target: "https://api.XXXXXXX.dev",
// Your Bloomreach API base URL
stream_id: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
// Your event stream ID
experimental: {
non_personalized_weblayers: true
},
new_experiments: {
mode: "sync"
},
customer: {
email_id: "[email protected]"
// Identified visitor's email address — optional for Search-only setups
},
track: {
default_properties: {
customer_tier: "gold-member"
// Custom properties added to all events, used for Search segment personalization
},
metadata: {
domain_key: "Pacific",
// Provided by your Search consultant
view_id: "en_US",
// Provided by your Search consultant
test_data: true,
// Ignores events in Search on production
debug: true
// Enables real-time integration mode in Search
}
},
});
brweb.start();
</script>
NoteSome privacy regulations require you to call
brweb.start()only after the visitor has granted cookie consent.
Snippet configuration reference
The table below covers the configuration parameters relevant to a Search setup. For the full configuration reference, see JS SDK configuration.
| Parameter | Type | Description |
|---|---|---|
target | String | Your Bloomreach API base URL. Find it in Data hub > Workspace settings > Access management > API > API Credentials. |
stream_id | String | Your event stream ID. Find it in Data hub > Event streams > select your stream > Access security. |
customer.email_id | String | Optional for Search-only setups. The identified visitor's email address. Include this if you plan to add Marketing later. |
track.default_properties | Object | Custom properties appended to every tracked event automatically. Use this for attributes like customer_tier that power Search relevance-by-segment search personalization. |
track.metadata.domain_key | String | Your Search domain key. |
track.metadata.view_id | String | Your Search catalog's view_id. For example, a locale or region. Provided by your Search consultant. |
track.metadata.test_data | Boolean | When true, Search ignores events sent from production. Use during testing and QA. |
track.metadata.debug | Boolean | When true, enables real-time integration mode in Search and ignores events on production. Use during development. |
Update metadata after initialization
In most implementations, metadata is set once in the snippet and doesn't need to change. If your website supports multiple locales or regions, you may need to update view_id or other metadata values after brweb.start() has been called — for example, when a visitor switches language. Use the brweb.metadata() method to do this.
To update all metadata properties at once:
brweb.metadata({
domain_key: "Pacific",
view_id: "es_MX",
test_data: true,
debug: true
});To update a single property:
brweb.metadata({
view_id: "es_MX"
});For the full metadata reference, see Bloomreach Web SDK: Metadata.
Identify visitors
Visitor identification is optional for Search but enables personalization use cases such as personalized ranking and relevance-by-segment.
Search supports an optional user_id property for this purpose. Consult your Search implementation partner before adding this to confirm it's relevant to your setup.
NoteDon't use personally identifiable information as the
user_idvalue. Always use an obfuscated identifier, for example, a hashed internal ID.
To include user_id in every tracked event by default, add it to the metadata object in your snippet configuration:
track: {
metadata: {
user_id: "be3e149d34ed43d4128252f2"
}
}To update user_id at runtime, for example, after a visitor logs in, use the brweb.metadata() method:
brweb.metadata({
user_id: "be3e149d34ed43d4128252f2"
});Track required events
Search uses tracked events to learn visitor behavior, personalize search results, power recommendations, and measure conversions. The table below lists all required events and the Search parameter each maps to.
For the full reference, including tracking calls, property descriptions, and API request examples, see Required events. Your Bloomreach consultant or implementation partner will confirm which events and properties are required for your specific use cases.
Page view events
Track these events when a page loads, refreshes, or when content changes in a single-page application.
| Event | Search mapping |
|---|---|
view_homepage | ptype=homepage |
view_category | ptype=category |
view_item | ptype=product |
view_search_results | ptype=search |
view_content | ptype=content |
view_thematic | ptype=thematic |
view_other | ptype=other |
view_quickview | etype=quickview |
Interaction events
Track these events on specific user actions.
| Event | Search mapping |
|---|---|
suggest_click | etype=click, group=suggest |
search_submit | etype=submit, group=suggest |
cart_update (add) | etype=click-add, group=cart |
cart_update (widget add) | etype=cart |
widget_view | etype=widget-view |
widget_click | etype=widget-click |
purchase | ptype=conversion |
Verify your implementation
Use the Bloomreach Tracking Console extension to validate your tracking setup in the browser. It lets you inspect events as they fire, verify that metadata properties are passing correctly, and confirm that Search is receiving the expected data.
NoteThe Tracking Console extension doesn't include the pixel validation capabilities available in the Bloomreach Pixel Validator Chrome extension.
What's next?
- Required events: Full reference for all events, properties, and API request examples
- Web tracking: Customer identification, event tracking methods, cookies, and storage
- Integrate on single-page applications: SPA-specific tracking considerations
- Set up Marketing and Search: Add Marketing to your setup when you're ready
Updated 2 days ago

