Product UpdatesExplainerAdvanced

Signed configuration: why the tag manager is a supply-chain component and how Ed25519 keeps it honest

A tag manager ships code to every visitor of your site. Track treats that as a supply chain: declarative templates instead of custom scripts, Ed25519-signed configuration bundles, a manifest with digest and key id, client-side verification and a version history you can roll back.

By
Track editorial team
Published
Last reviewed
Reading time
3 min read

Key takeaways

  • A tag manager ships code to every visitor, so Track treats configuration delivery as a supply chain with three threats: harmful changes by insiders, tampered delivery and untracked drift.
  • Declarative templates with typed parameters replace custom HTML and JavaScript; a bundle is data, validated on server and client, with no eval and no arbitrary script loading.
  • Published bundles are Ed25519-signed with a key that never leaves the publishing service; the SDK verifies digest and signature with Web Crypto and discards anything that fails.
  • A freshly fetched manifest carries version, digest, key id and the kill switch flag, and every publish is an immutable, approved, attributable version that can be rolled back.

The threat model

Three things can go wrong with configuration delivered to browsers:

  1. Someone with legitimate access ships something harmful — a custom HTML tag that exfiltrates form data, a "temporary" script that stays for years.
  2. The delivery path is tampered with — a compromised CDN edge, a misconfigured proxy, a man-in-the-middle on a hostile network.
  3. Nobody can tell what changed — the live configuration drifts from what was reviewed.

Declarative templates close the first door

Track has no custom HTML or custom JavaScript tag type. Every browser-side action is a template from a fixed set (Meta pixel, Google tag, TikTok pixel, UET, Insight Tag, and so on) with typed parameters: ids, event mappings, consent purposes. A template cannot contain code; it selects a loader the SDK already ships and fills in identifiers. The configuration bundle is data, validated against a schema on the server and again on the client. There is no eval, no new Function, and nothing in a bundle can make the SDK fetch a script from a URL the template does not already know.

That is a deliberate loss of flexibility. The migration guide lists what has no equivalent; the answer is always "put that logic in the site's own code, where it is reviewed like code".

Signing closes the second

When a version is published, the server serialises the bundle canonically, computes its SHA-256 digest and signs the bytes with an Ed25519 private key that exists only on the publishing service. The published artefact is { payload, digest, keyId, algorithm, signature }.

The SDK ships with the public keys for the site's key ids. Before applying a bundle it recomputes the digest, checks it against the signed one, and verifies the signature with Web Crypto (SubtleCrypto.verify with Ed25519). A bundle that fails verification is discarded and the SDK keeps its last verified bundle from session cache — or runs with no destinations at all rather than an unverified configuration.

Signing does not replace TLS; it protects against everything TLS does not, including a compromised edge that serves valid-looking JSON over a valid certificate.

The manifest

The loader first fetches a small manifest: tracking id, environment, version, bundle URL, digest, key id, published-at timestamp and the kill switch flag. The manifest is fetched fresh; the bundle is cached in session storage by version and digest. This is what lets a kill switch or a rollback take effect on the next page view without cache-busting the bundle itself.

Versioning closes the third

Every publish creates an immutable version with a diff against its predecessor, the actor, the approval that authorised it and the request id. The version history shows exactly what visitors receive, and rollback republishes an earlier version as a new one — signed again, audited again. Drafts and published versions never share storage, so "what is live" is a single fact, not a state of several toggles.

Key management

  • Signing keys are generated per environment and never leave the publishing service; the private key is never stored in the database.
  • Key ids allow rotation: a new key is added, new versions are signed with it, the old public key remains valid for verification until every site has republished, then it is retired.
  • The key_id on every manifest tells you which key signed the live configuration.

What this means for your security review

You can describe the tag manager to a security team in one paragraph: it delivers signed, schema-validated data to a fixed SDK; it cannot execute site-authored code; every change is versioned, approved and attributable; and a compromise of the delivery path cannot alter behaviour without the signing key. The security page links the current key ids and the SDK's verification source.

Primary sources

Documentation and standards this article is based on.

  1. RFC 8032 — Edwards-Curve Digital Signature Algorithm (EdDSA)rfc-editor.org
  2. MDN — SubtleCrypto.verify()developer.mozilla.org

Was this article helpful?

Responsible editor

Track editorial team

Product & engineering

The people building Track: engineers and analysts who work on server-side tracking, consent tooling and connector integrations every day.