Ecosystem ↗

Tag-manager configuration

Configure browser/server event routing, shared stores, consent and protected administration.

↗ View Markdown

Prerequisites and setup#

Install @zeruxjs/tags and @zeruxjs/analytics, configure an analytics database connection, and enable analytics before tags. A standalone manager requires actual analytics/request-ID services; runtime bootstrap supplies them when available. A missing analytics service degrades the configured tags integration rather than inventing a reporting backend.

zerux.config.js
/** @type {import('zeruxjs').ZeruxConfig} */
export default {
  analytics: { enabled: true, analytics: 'reporting' },
  tags: {
    enabled: true,
    prefix: '/_tags',
    site: 'storefront',
    publicOrigin: 'https://tags.example.com',
    allowedOrigins: ['https://app.example.com'],
    defaultConsent: 'denied',
    requireBrowserConsent: true,
    debug: false,
  },
};

This is collector setup; it deliberately does not create anonymous admin access. Define the reporting connection in db. The application must proxy the public tagging origin to the actual runtime if it uses a separate subdomain. An origin setting does not configure DNS, TLS or routing infrastructure.

The default prefix is /_tags; the browser client is served beneath that prefix. site partitions the intended analytics context, while siteByOrigin can map explicitly allowed browser origins to sites. Do not trust a client-supplied site ID as proof of tenant authorization. allowedOrigins is a browser collection policy, not administrator authentication.

The package default consent is granted unless configured otherwise; this example explicitly chooses denied. The host's consent interaction must update the client consent state before optional browser event collection. requireBrowserConsent controls whether consent is required for relevant browser events. Do not place GA4 secrets, webhook authorization headers or administrator tokens in browser data-layer payloads.

Destinations and protected administration#

GA4 credentials and preapproved webhook destinations belong to the server-side credentials and destinations maps. Tags refer to those entries by identifier; the browser container must not receive their secret values. Destination validation does not replace a network egress policy or a review of the data sent to a third party.

To enable administration, implement authorizeAdmin(request) against a validated host session and role policy. authorizePublish can restrict publishing separately from draft editing. dashboardHost restricts the host serving administration; it is not authentication. Missing authorization means no public editing route should be assumed. Container writes use version checks: treat stale revisions as conflicts rather than retrying with unreviewed changes.

TypeScript setup#

ts
import type { ZeruxConfig } from 'zeruxjs';
type TagSetup = NonNullable<ZeruxConfig['tags']>;
const tags = {
  enabled: true, prefix: '/_tags', site: 'storefront',
  defaultConsent: 'denied', requireBrowserConsent: true,
} satisfies TagSetup;
export default { tags } satisfies ZeruxConfig;

For a standalone factory infer its input with Parameters<typeof createTagManager>[0], which includes dependencies supplied automatically by the runtime. Do not cast a partial runtime setup into the standalone factory input. The complete TagsStartupConfig table below shows the callback/store contracts.

Persistence and lifecycle#

Bootstrap attempts to use analytics-backed container and request-ID stores. Supply shared stores explicitly when the backing analytics implementation cannot provide them. Memory fallback is suitable for single-process development and does not coordinate revisions or duplicate reservations across hosts. Never describe a memory reservation map as durable event deduplication.

Verify a browser event, a server event, a denied origin, denied consent, and an unauthorized administration request. Check that published container JSON excludes credentials. Restart and test publication persistence with two processes before relying on the store for production tag governance.

Exact option shapes#

The fields below come from the current source declarations. Optional is not a default value. A callback is application code, not a string naming a role.

TagsStartupConfig#

Option Accepted TypeScript value Required Meaning
enabled boolean No Passed using this declared shape; omission is allowed only when marked optional.
prefix string No Passed using this declared shape; omission is allowed only when marked optional.
site string No Passed using this declared shape; omission is allowed only when marked optional.
publicOrigin string No Passed using this declared shape; omission is allowed only when marked optional.
allowedOrigins string[] No Passed using this declared shape; omission is allowed only when marked optional.
serverToken string No Passed using this declared shape; omission is allowed only when marked optional.
requestIds {reserve(day:string,id:string):Promise<boolean>} No Passed using this declared shape; omission is allowed only when marked optional.
store {load():Promise<unknown>;save(container:unknown,expectedVersion:number):Promise<boolean>} No Passed using this declared shape; omission is allowed only when marked optional.
container unknown No Passed using this declared shape; omission is allowed only when marked optional.
credentials Record<string,{secret:string}> No Passed using this declared shape; omission is allowed only when marked optional.
destinations Record<string,{url:string;headers?:Record<string,string>}> No Passed using this declared shape; omission is allowed only when marked optional.
authorizeAdmin (request:Request)=>boolean|Promise<boolean> No Application-supplied callback or adapter; see the setup and lifecycle discussion.
authorizePublish (request:Request)=>boolean|Promise<boolean> No Application-supplied callback or adapter; see the setup and lifecycle discussion.
requireBrowserConsent boolean No Passed using this declared shape; omission is allowed only when marked optional.
siteByOrigin Record<string,string> No Passed using this declared shape; omission is allowed only when marked optional.
botPolicy 'allow'|'drop-known' No Passed using this declared shape; omission is allowed only when marked optional.
onWarning (message:string)=>void No Application-supplied callback or adapter; see the setup and lifecycle discussion.
dashboardHost string No Passed using this declared shape; omission is allowed only when marked optional.
debug boolean No Passed using this declared shape; omission is allowed only when marked optional.
defaultConsent 'granted'|'denied' No Passed using this declared shape; omission is allowed only when marked optional.
onDebug (data:unknown)=>void No Application-supplied callback or adapter; see the setup and lifecycle discussion.
maxBodyBytes number No Passed using this declared shape; omission is allowed only when marked optional.
maxEventsPerMinute number No Passed using this declared shape; omission is allowed only when marked optional.
Implementation sources

Implementation files for the APIs described on this page.

ZeruxJS · Open source · MIT OR Apache-2.0

Make yourself at home.

Every shortcut has a visible control too. Reading and navigation work without JavaScript.

Ctrl / ⌘ K
Search all documentation
/
Search, outside editable fields
?
This help, outside editable fields
↑ / ↓
Move through search results
Esc
Close a dialog or version menu
Progress, privacy, offline reading and controls →

Reset this learning record?

This removes course answers, exercise confirmations, bookmarks and recent pages for this docs version in this browser. Export a copy first if you want to keep it.

Search documentation

Type at least two characters.