Frontend IntegrationWeb ObjectGTM integration

GTM integration

How to load @usesophi/sophi-web-object (the storefront event-tracking SDK) through Google Tag Manager, including recommended split and all-in-GTM configurations.

Use this page when you load @usesophi/sophi-web-object (the browser data-layer / analytics SDK) through Google Tag Manager. It is not the chat widget: for @usesophi/sophi-web-sdk (SophiWidget), see SDK GTM integration.

Prerequisites

  • Google Tag Manager is installed on your site.
  • Tags that load Sophi fire only when your privacy / consent rules allow (for example Google Consent Mode analytics_storage granted, or an equivalent you use).
  • window.sophi_object.config.apiKey is available before sophi.min.js runs, unless you use the all-in-GTM variant below.

For most modern storefronts, keep data and API keys in your application and use GTM only to inject the script:

ResponsibilityWhere
window.sophi_objectconfig (and optionally userId, debug, …), page, product, basket, listing, transaction, userYour site / SPA, updated when consent allows
Loading sophi.min.js from jsDelivrGTM (Custom HTML tag, consent-gated)

This avoids duplicating commerce payloads in GTM, supports multi-brand API keys in code, and matches the pattern described in our integration patterns.

GTM variable (easy upgrades)

Create a Constant variable in GTM, for example:

Variable nameTypeValue
Sophi Web Object script URLConstanthttps://cdn.jsdelivr.net/npm/@usesophi/sophi-web-object@x.y.z/dist/sophi.min.js

Replace x.y.z with a pinned semver for production. When you upgrade the SDK, change this one variable and publish the container—no need to edit multiple tags.

Avoid `@latest` in production

@latest is convenient for development. In production, pin a version so a new npm release cannot change behaviour until you deliberately update the Constant.

Two triggers, one tag

Visitors may already have granted analytics consent when the page loads, or they may accept cookies during the session. Attach the same “load Sophi script” tag to both cases:

  1. Consent on first paint — For example a Consent Initialization trigger (or your CMP’s equivalent) that fires when analytics consent is already granted for this page view.
  2. Consent granted mid-session — For example a Custom Event trigger when your banner pushes a consent update to dataLayer, with analytics === true (names depend on your implementation).

Both triggers should run the identical Custom HTML (below) so sophi.min.js loads exactly once when consent becomes true, whether that was before or after load.

If you mirror Google Consent Mode and push cookie_consent_updated when the user saves preferences:

  • Variable: Data Layer Variable reading cookie_consent.analytics (or your field name).
  • Trigger A: Consent Initialization — All Pages, with condition analytics_storage granted (or your CMP’s mapping).
  • Trigger B: Custom Event cookie_consent_updated, with condition DLV equals true.

Adapt names and conditions to your CMP; the important part is covering both initial and delayed consent.

Custom HTML tag (script only)

When your application already sets window.sophi_object.config (and other keys) before or when the tag fires:

<script src="{{Sophi Web Object script URL}}" async></script>

Use the exact variable name you defined in GTM (the {{...}} placeholder must match).

If the script might fire more than once during navigation tests, you can guard with a small check (optional):

<script>
  if (!window.__sophiWebObjectLoaded) {
    window.__sophiWebObjectLoaded = true;
    var s = document.createElement('script');
    s.src = '{{Sophi Web Object script URL}}';
    s.async = true;
    document.head.appendChild(s);
  }
</script>

The SDK itself waits for DOMContentLoaded before bootstrapping; async on the script tag is supported.

All-in-GTM variant (simple sites)

For static sites you can set minimal config in the same tag that loads the bundle. Prefer Option A (separate script src); Option B inlines the bundle and increases container size.

Option A — load from jsDelivr

  1. Create a Custom HTML tag.
  2. Ensure window.sophi_object exists with at least config.apiKey, then load the script:
<script>
  window.sophi_object = window.sophi_object || {};
  window.sophi_object.config = Object.assign({}, window.sophi_object.config, {
    apiKey: 'YOUR_API_KEY'
  });
</script>
<script src="https://cdn.jsdelivr.net/npm/@usesophi/sophi-web-object@x.y.z/dist/sophi.min.js" async></script>
  1. Fire the tag only when analytics consent is granted (same consent principles as above). Pin x.y.z in production.

Option B — inline sophi.min.js

  1. Paste the full contents of sophi.min.js from the published package after the small window.sophi_object config block.
  2. Use the same triggers as Option A.

Inlining removes one CDN round-trip at the cost of a large GTM payload.

If window.sophi_object is defined in an earlier tag, define it there and keep this tag’s HTML to only the script src line (recommended pattern in Recommended split).


For consent-sensitive fields (UserObject, PII), see Configuration and Types reference.

QA checklist

  1. With consent denied, confirm no Sophi tracking requests (or script load, depending on your triggers).
  2. After consent granted, confirm sophi.min.js loads from your pinned URL.
  3. Confirm window.sophi_object.config has a valid apiKey before or when the script runs (unless you rely on the SDK’s post-start updates—see SophiTracker).
  4. Navigate the site and verify events align with default mappings (for example pagepage_view, productproduct_view).

On this page