Integration guide
How to deliver @usesophi/sophi-web-object to your storefront — choose between GTM, npm/bundler, or CDN script tag depending on your stack.
Choose how you deliver @usesophi/sophi-web-object. For Google Tag Manager, the detailed walkthrough is on a dedicated page so it is easy to find: GTM integration.
To load the Sophi assistant widget (SophiWidget, @usesophi/sophi-web-sdk) from GTM, use SDK GTM integration, not this package.
Choose an integration method
| Method | Best when | Upgrade story |
|---|---|---|
| GTM | Marketing owns tag publishing; consent-gated load; you want one place to bump the script URL | Pin SDK version in a GTM Constant variable; change it + publish container |
| Script tag | Full control in your HTML templates; no GTM | Change the src URL (or your CMS snippet) and deploy |
| npm / ESM | Bundled app; type-aware codebase; tree-shaking not required for this global SDK | Bump dependency in package.json and release your app |
All methods expose window.sophi_object and window.SophiTracker (see SophiTracker API).
Script tag
The inline snippet must come before the async SDK script tag and must contain both the config object and the official pre-load stub:
<script>
window.sophi_object = {
config: {
apiKey: 'YOUR_API_KEY'
},
page: {
type: 'Home',
url: window.location.href
}
};
window.SophiTracker = window.SophiTracker || (function () {
var _q = [];
var _fwd = null;
function push() {
if (_fwd) { return _fwd.apply(null, arguments); }
_q.push(Array.prototype.slice.call(arguments));
}
push._sophiQ = _q;
push._sophiSetFwd = function (fn) { _fwd = fn; };
return { push: push };
}());
</script>
<script
src="https://cdn.jsdelivr.net/npm/@usesophi/sophi-web-object@1.3.x/dist/sophi.min.js"
async
></script>The URL above uses @1.3.x, which automatically selects the latest compatible patch within the 1.3 minor line — you get bug fixes without risking a breaking minor upgrade. Never use @latest in production. Check Installation for the full CDN table.
Why the stub is required
The SDK script loads asynchronously. Between the moment the inline snippet runs and the moment the SDK bundle executes, window.SophiTracker does not exist yet. Without the stub, any push() call in that window is silently lost.
The stub:
- Creates
window.SophiTrackerimmediately if it does not already exist. - Buffers every
push()call into an internal queue (_sophiQ). - Installs a forwarding hook (
_sophiSetFwd) that the SDK uses on startup to replay the queue.
The SDK adopts the stub queue and drains all buffered calls in FIFO order after session initialization and initial preload data collection complete.
Call lifecycle
Inline snippet runs
→ window.sophi_object set (config + optional page/product/… data)
→ window.SophiTracker stub installed
push() calls before SDK bundle loads
→ buffered in stub._sophiQ
SDK bundle executes
→ Stub queue migrated to internal pending queue
→ window.SophiTracker replaced with real tracker
→ push() calls between bundle execution and bootstrap → buffered
DOMContentLoaded / bootstrap
→ Session established
→ sophi_object preload data collected (collectAll)
→ Buffered push() calls drained in FIFO order
→ Tracker enters READY state
Later push() calls → processed immediatelyInitial-page events
Declare initial page state through window.sophi_object:
window.sophi_object = {
config: { apiKey: 'YOUR_API_KEY' },
page: {
type: 'Product',
url: 'https://store.com/products/blue-dress',
title: 'Blue Dress | Store'
},
product: {
id: '1627421',
// …
}
};The SDK processes this snapshot at bootstrap. page produces a page_view event; product produces a product_view event. Both are guaranteed to fire before any buffered push() calls are drained.
Later SPA events
After the initial page load, use SophiTracker.push() for route changes and interaction events:
SophiTracker.push({
page: { type: 'Category', url: 'https://store.com/dresses' },
listing: { /* … */ }
});The stub and SDK automatically buffer calls made before readiness. You do not need to check window.SophiTracker before calling push().
Important warnings
window.sophi_object is a config and state object, not an event queue.
- Do not assign it as an array:
window.sophi_object = window.sophi_object || [] - Assigning the same property twice before bootstrap keeps only the latest value — earlier values are silently overwritten.
- Do not replace or reassign
window.sophi_objectafter the SDK Proxy has been installed.
If you set page through sophi_object preload and also call SophiTracker.push({ page: … }) for the same event, two page_view events will be sent. Use only one mechanism per event.
Browser back/forward route changes must still trigger an explicit SophiTracker.push() call from your router. The SDK does not automatically detect history changes.
If config.storageConsent: false is set at startup, calls buffered in the pre-load queue are discarded when the SDK initialises — not held for later replay. Events begin flowing only after SophiTracker.setConsent(true) is called, at which point the SDK re-collects the current sophi_object snapshot.
npm / ESM
npm install @usesophi/sophi-web-objectES module import is hoisted, so assign window.sophi_object first, then load the SDK with dynamic import (or a small separate entry file that runs before your main bundle):
window.sophi_object = {
config: { apiKey: 'YOUR_API_KEY' },
};
await import('@usesophi/sophi-web-object/dist/sophi.esm.js');
// After bootstrap: window.SophiTracker is readyAlternatively, set window.sophi_object in an inline <script> before your bundled app, or use the script tag / GTM approaches.
Best practices
- Pin versions in production — Use an exact semver in URLs or
package.json, not@latest, so releases do not change behaviour unexpectedly. - Consent — Load the tracker and populate PII only when your policy allows (see Configuration and Types for
UserObject). - SPAs — After route or context changes, update via
SophiTracker.push()or assignments; see SophiTracker API and Integration patterns. - Config and apiKey — The SDK strips
apiKeyfrom the public object after startup; avoid rewriting it on every render.
Events cheat sheet
When you assign to watched keys without overriding event_type, defaults are:
| Key | Default event_type |
|---|---|
page | page_view |
user | identify |
product | product_view |
basket | basket_view |
listing | listing_view |
transaction | purchase |
For add_to_cart, remove_from_cart, and checkout_started, set event_type explicitly (usually via SophiTracker.push). Details: Event types.
Next steps
- GTM integration
- Installation — CDN table and artifacts
- Window object layer
- Integration patterns — cart, checkout, login examples
Sophi Web Object (@usesophi/sophi-web-object)
The Sophi Web Object package is a framework-agnostic browser SDK that tracks e-commerce behaviour via window.sophi_object and sends structured events to the Sophi event API.
Installation
The npm package is @usesophi/sophi-web-object. Artifacts live under dist/ in the package.