Skip to content

GTM destination: add "Load GTM" option to skip script injection - #1362

Merged
absorbb merged 1 commit into
newjitsufrom
feat/newjitsu/gtm-self-load
Jun 19, 2026
Merged

GTM destination: add "Load GTM" option to skip script injection#1362
absorbb merged 1 commit into
newjitsufrom
feat/newjitsu/gtm-self-load

Conversation

@absorbb

@absorbb absorbb commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a loadGtm option to the Google Tag Manager device destination so customers can take over loading GTM themselves while still using the official destination.

The GTM destination currently injects the GTM script lazily — only on the first event sent to it. For events fired right before a navigation (e.g. link clicks), this loses a race: the script hasn't loaded its tags/pixels by the time the browser navigates away, so the pixel never fires.

With this change, customers can load GTM on page load themselves (so tags are ready early) and set Load GTM = off. Jitsu then skips injecting the GTM script but still pushes page_view / track / identify events to the data layer, which the client-loaded container processes. This avoids having to reimplement the GTM destination as a generic Tag destination.

Changes

  • libs/jitsu-js/src/destination-plugins/gtm.ts — add loadGtm?: boolean to GtmDestinationCredentials. In initGtmIfNeeded, when loadGtm === false, ensure the data layer exists and return early (skip script injection). Event-pushing logic is unchanged.
  • webapps/console/lib/schema/destinations.tsx — expose a "Load GTM" toggle in the GTM destination config (z.boolean().default(true)).

Compatibility

default(true) keeps this fully backward-compatible — existing destinations behave exactly as before. Only customers who load GTM themselves flip it off.

Context

Requested by a customer in Slack (private channel C08UVQMET16). Tracked in the Notion task.

Testing notes

  • Not yet run: typecheck/tests (authored in a fresh worktree without workspace deps installed). Change is small and matches existing schema/indexing idioms. CI should cover it.

Follow-ups

  • Update the jitsu.com GTM destination docs (external docs repo).
  • Reply to the customer once shipped.

🤖 Generated with Claude Code

The GTM device destination injects the GTM script lazily, only on the first
event sent to it. For events fired right before a navigation (e.g. link
clicks) this loses a race: the script hasn't loaded its tags/pixels yet by the
time the browser navigates away.

Add a `loadGtm` credential (default true, backward-compatible). When set to
false, the client loads GTM itself (e.g. on page load) and Jitsu skips
injecting the GTM script — it only ensures the data layer exists and pushes
events to it, which the client-loaded container then processes. This keeps the
official GTM destination usable without reimplementing it as a generic Tag
destination.

Requested by customer in Slack (C08UVQMET16).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@jitsu-code-review jitsu-code-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the GTM device-destination changes in:

  • libs/jitsu-js/src/destination-plugins/gtm.ts
  • webapps/console/lib/schema/destinations.tsx

I focused on runtime behavior around loadGtm, data layer initialization, and schema/default compatibility. I did not find actionable correctness or security issues in this range.

@absorbb
absorbb merged commit dc6edf6 into newjitsu Jun 19, 2026
5 checks passed
@absorbb
absorbb deleted the feat/newjitsu/gtm-self-load branch June 19, 2026 08:58
absorbb added a commit that referenced this pull request Jun 19, 2026
When `loadGtm` is enabled (default), Jitsu owns the data layer and keeps
resetting the whole GTM data model between events via `this.reset()`.

When `loadGtm === false` the client loads GTM itself and may keep its own
persistent data-layer values that `reset()` would clobber. In that case,
instead of resetting the entire model, push back only the keys Jitsu set this
event with `null` values. This still prevents Jitsu event data from
accumulating across events, but leaves data set outside Jitsu untouched.

`event` is excluded from the clear (already consumed by the trigger), keeping
the clearing push data-only so it doesn't fire event-based triggers.

Builds on #1362 (the loadGtm option).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
absorbb added a commit that referenced this pull request Jun 19, 2026
When `loadGtm` is enabled (default), Jitsu owns the data layer and keeps
resetting the whole GTM data model between events via `this.reset()`.

When `loadGtm === false` the client loads GTM itself and may keep its own
persistent data-layer values that `reset()` would clobber. In that case,
instead of resetting the entire model, push back only the keys Jitsu set this
event with `null` values. This still prevents Jitsu event data from
accumulating across events, but leaves data set outside Jitsu untouched.

`event` is excluded from the clear (already consumed by the trigger), keeping
the clearing push data-only so it doesn't fire event-based triggers.

Builds on #1362 (the loadGtm option).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant