@jwiedeman/gtm-kit 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts","../src/constants.ts","../src/consent.ts","../src/consent/presets.ts","../src/data-layer.ts","../src/logger.ts","../src/url-utils.ts","../src/script-manager.ts","../src/client.ts","../src/events/push.ts","../src/noscript.ts","../src/auto-queue.ts"],"names":["_a","_b","noop"],"mappings":"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","sourcesContent":["/**\n * Branded type for GTM Container IDs.\n * Prevents accidental mix-ups with other string types.\n *\n * @example\n * ```ts\n * const containerId = 'GTM-XXXXXX' as ContainerId;\n * ```\n */\nexport type ContainerId = string & { readonly __brand: 'ContainerId' };\n\n/**\n * Type guard to check if a string is a valid GTM container ID format.\n * Valid formats: GTM-XXXXXX (6+ alphanumeric characters)\n */\nexport const isValidContainerId = (value: string): value is ContainerId => {\n return /^GTM-[A-Z0-9]{6,}$/i.test(value);\n};\n\n/**\n * Safely cast a string to ContainerId after validation.\n * Throws if the format is invalid.\n */\nexport const toContainerId = (value: string): ContainerId => {\n if (!isValidContainerId(value)) {\n throw new Error(\n `Invalid GTM container ID format: \"${value}\". ` +\n 'Container IDs must start with \"GTM-\" followed by 6 or more alphanumeric characters. ' +\n 'Example: \"GTM-ABC123\" or \"GTM-WXYZ7890\"'\n );\n }\n return value;\n};\n\n/**\n * Branded type for DataLayer names.\n * Prevents accidental use of invalid JavaScript identifiers.\n */\nexport type DataLayerName = string & { readonly __brand: 'DataLayerName' };\n\n/**\n * JavaScript reserved words that cannot be used as variable names.\n */\nconst JS_RESERVED_WORDS = new Set([\n 'break',\n 'case',\n 'catch',\n 'class',\n 'const',\n 'continue',\n 'debugger',\n 'default',\n 'delete',\n 'do',\n 'else',\n 'enum',\n 'export',\n 'extends',\n 'false',\n 'finally',\n 'for',\n 'function',\n 'if',\n 'import',\n 'in',\n 'instanceof',\n 'let',\n 'new',\n 'null',\n 'return',\n 'static',\n 'super',\n 'switch',\n 'this',\n 'throw',\n 'true',\n 'try',\n 'typeof',\n 'var',\n 'void',\n 'while',\n 'with',\n 'yield',\n 'await',\n 'implements',\n 'interface',\n 'package',\n 'private',\n 'protected',\n 'public',\n 'arguments',\n 'eval'\n]);\n\n/**\n * Type guard to check if a string is a valid dataLayer name.\n * Valid names must be valid JavaScript identifiers and not reserved words.\n *\n * Security: Prevents injection attacks via malicious dataLayer names like:\n * - \"dataLayer'];alert('XSS');//\"\n * - \"dataLayer<script>\"\n *\n * @example\n * ```ts\n * isValidDataLayerName('dataLayer'); // true\n * isValidDataLayerName('myCustomLayer'); // true\n * isValidDataLayerName('data_layer_1'); // true\n * isValidDataLayerName(\"dataLayer'];alert('XSS')\"); // false\n * isValidDataLayerName('class'); // false (reserved word)\n * ```\n */\nexport const isValidDataLayerName = (value: string): value is DataLayerName => {\n // Must be a non-empty string\n if (typeof value !== 'string' || value.length === 0) {\n return false;\n }\n\n // Must be a valid JavaScript identifier\n // Starts with letter, underscore, or dollar sign\n // Contains only letters, numbers, underscores, or dollar signs\n if (!/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(value)) {\n return false;\n }\n\n // Must not be a reserved word\n if (JS_RESERVED_WORDS.has(value)) {\n return false;\n }\n\n return true;\n};\n\n/**\n * Safely cast a string to DataLayerName after validation.\n * Throws if the name is not a valid JavaScript identifier.\n *\n * @example\n * ```ts\n * const name = toDataLayerName('dataLayer'); // OK\n * const custom = toDataLayerName('myCustomLayer'); // OK\n * toDataLayerName(\"dataLayer'];alert('XSS')\"); // throws Error\n * ```\n */\nexport const toDataLayerName = (value: string): DataLayerName => {\n if (!isValidDataLayerName(value)) {\n throw new Error(\n `Invalid dataLayer name: \"${value}\". ` +\n 'DataLayer names must be valid JavaScript identifiers (letters, numbers, underscores, dollar signs) ' +\n 'and cannot be reserved words. Example: \"dataLayer\", \"myCustomLayer\", \"gtm_data\"'\n );\n }\n return value;\n};\n\n/**\n * Values that can be pushed to the GTM dataLayer.\n *\n * The dataLayer accepts three types of values:\n *\n * ## 1. Objects (most common)\n * Plain objects containing event data and variables. Property values can be:\n * - **Primitives**: `string`, `number`, `boolean`, `null`, `undefined`\n * - **Arrays**: For ecommerce items, user lists, etc.\n * - **Nested objects**: For complex structured data\n *\n * ```ts\n * // Event with properties\n * push({ event: 'page_view', page_title: 'Home' });\n *\n * // Setting variables\n * push({ user_id: '12345', user_type: 'premium' });\n *\n * // Ecommerce data\n * push({\n * event: 'purchase',\n * ecommerce: {\n * transaction_id: 'T-123',\n * value: 99.99,\n * items: [{ item_id: 'SKU-1', price: 99.99 }]\n * }\n * });\n * ```\n *\n * ## 2. Functions (GTM callbacks)\n * Functions pushed to dataLayer are executed by GTM with a callback parameter.\n * Useful for reading GTM state or triggering container-specific behavior.\n *\n * ```ts\n * // Read container ID\n * push(function(this: { id: string }) {\n * console.log('Container:', this.id);\n * });\n *\n * // Async operation with GTM\n * push(function() {\n * return new Promise(resolve => {\n * setTimeout(() => resolve(), 1000);\n * });\n * });\n * ```\n *\n * ## 3. Arrays (consent commands, legacy format)\n * Array format primarily used for Google Consent Mode commands.\n * The first element is the command, followed by parameters.\n *\n * ```ts\n * // Consent default command\n * push(['consent', 'default', { analytics_storage: 'denied' }]);\n *\n * // Consent update command\n * push(['consent', 'update', { analytics_storage: 'granted' }]);\n * ```\n *\n * @see https://developers.google.com/tag-manager/devguide#datalayer\n * @see https://developers.google.com/tag-platform/gtagjs/reference#consent\n */\nexport type DataLayerValue = Record<string, unknown> | ((...args: unknown[]) => unknown) | unknown[];\n\n/**\n * Type-safe globalThis extension for accessing dataLayer.\n * Use this interface to extend globalThis in your application.\n *\n * @example\n * ```ts\n * declare global {\n * interface Window extends GtmGlobalExtension {}\n * }\n *\n * // Then access safely\n * const dataLayer = window.dataLayer;\n * ```\n */\nexport interface GtmGlobalExtension {\n dataLayer?: DataLayerValue[];\n google_tag_manager?: Record<string, unknown>;\n}\n\n/**\n * Type-safe access to the dataLayer from globalThis/window.\n * Returns undefined if running in a non-browser environment or if dataLayer doesn't exist.\n */\nexport const getGlobalDataLayer = (name = 'dataLayer'): DataLayerValue[] | undefined => {\n if (typeof globalThis === 'undefined') {\n return undefined;\n }\n const global = globalThis as typeof globalThis & Record<string, unknown>;\n const layer = global[name];\n return Array.isArray(layer) ? (layer as DataLayerValue[]) : undefined;\n};\n\n/**\n * Type-safe access to google_tag_manager from globalThis/window.\n * Returns undefined if running in a non-browser environment or if GTM isn't loaded.\n */\nexport const getGoogleTagManager = (): Record<string, unknown> | undefined => {\n if (typeof globalThis === 'undefined') {\n return undefined;\n }\n const global = globalThis as typeof globalThis & GtmGlobalExtension;\n return global.google_tag_manager;\n};\n\nexport interface DataLayerState {\n name: string;\n dataLayer: DataLayerValue[];\n created: boolean;\n restore(): void;\n}\n\nexport interface Logger {\n debug(message: string, details?: Record<string, unknown>): void;\n info(message: string, details?: Record<string, unknown>): void;\n warn(message: string, details?: Record<string, unknown>): void;\n error(message: string, details?: Record<string, unknown>): void;\n}\n\nexport type PartialLogger = Partial<Logger>;\n\nexport type ScriptAttributeValue = string | boolean | null | undefined;\n\nexport interface ScriptAttributes {\n async?: boolean;\n defer?: boolean;\n nonce?: string;\n [attribute: string]: ScriptAttributeValue;\n}\n\n/**\n * Script load status:\n * - 'loaded': Script loaded and GTM initialized successfully\n * - 'failed': Script failed to load (network error, blocked, etc.)\n * - 'skipped': Script was skipped (already present, or no document available)\n * - 'partial': Script loaded but GTM failed to initialize (malformed container, etc.)\n */\nexport type ScriptLoadStatus = 'loaded' | 'failed' | 'skipped' | 'partial';\n\nexport interface ScriptLoadState {\n containerId: string;\n src?: string;\n status: ScriptLoadStatus;\n fromCache?: boolean;\n error?: string;\n /**\n * Time taken to load the script in milliseconds.\n * Only present for scripts that were actually loaded (not cached/skipped).\n */\n loadTimeMs?: number;\n}\n\nexport interface ContainerDescriptor {\n id: string;\n queryParams?: Record<string, string | number | boolean>;\n}\n\nexport type ContainerConfigInput = string | ContainerDescriptor;\n\n/**\n * Options for script retry behavior on load failures.\n */\nexport interface ScriptRetryOptions {\n /**\n * Number of retry attempts after initial failure.\n * Set to 0 to disable retries (default behavior).\n * @default 0\n */\n attempts?: number;\n\n /**\n * Initial delay in milliseconds before first retry.\n * Subsequent retries use exponential backoff (delay * 2^attempt).\n * @default 1000\n */\n delay?: number;\n\n /**\n * Maximum delay between retries in milliseconds.\n * Prevents exponential backoff from growing too large.\n * @default 30000\n */\n maxDelay?: number;\n}\n\nexport interface CreateGtmClientOptions {\n containers: ContainerConfigInput[] | ContainerConfigInput;\n dataLayerName?: string;\n host?: string;\n defaultQueryParams?: Record<string, string | number | boolean>;\n scriptAttributes?: ScriptAttributes;\n logger?: PartialLogger;\n\n /**\n * Enable debug mode with verbose console logging.\n * When true, all GTM operations are logged to the console with timestamps\n * and colored prefixes for easy debugging.\n *\n * Note: This overrides any custom logger if set to true.\n * For production, either set to false or use a custom logger.\n * @default false\n */\n debug?: boolean;\n\n /**\n * Script retry configuration for failed loads.\n * Enables automatic retry with exponential backoff.\n */\n retry?: ScriptRetryOptions;\n\n /**\n * Timeout in milliseconds for script load.\n * If a script doesn't load within this time, it's considered failed.\n * Set to 0 to disable timeout (not recommended).\n * @default 30000\n */\n scriptTimeout?: number;\n\n /**\n * Callback invoked when a script fails to load (after all retries exhausted).\n * Use this to handle errors gracefully in your application.\n */\n onScriptError?: (state: ScriptLoadState) => void;\n\n /**\n * Callback invoked when a script load times out.\n * Called before retry attempts if retries are configured.\n */\n onScriptTimeout?: (containerId: string) => void;\n\n /**\n * Maximum number of entries allowed in the dataLayer array.\n * When the limit is reached, oldest non-critical entries are removed to make room.\n * Critical entries (gtm.js start event, consent commands) are preserved.\n * Set to 0 to disable the limit (not recommended for long-running SPAs).\n * @default 500\n */\n maxDataLayerSize?: number;\n\n /**\n * Callback invoked when dataLayer entries are trimmed due to size limit.\n * Use this to monitor memory management or log analytics.\n */\n onDataLayerTrim?: (trimmedCount: number, currentSize: number) => void;\n\n /**\n * Whether to verify GTM initialization after script loads.\n * When enabled, checks for the gtm.js event in the dataLayer after script load.\n * If verification fails, the script status is set to 'partial'.\n * @default false\n */\n verifyInitialization?: boolean;\n\n /**\n * Timeout in milliseconds to wait for GTM initialization verification.\n * Only used when verifyInitialization is true.\n * @default 5000\n */\n initializationTimeout?: number;\n\n /**\n * Callback invoked when a script loads but GTM fails to initialize.\n * This indicates a partial load failure (script loaded but GTM didn't work).\n */\n onPartialLoad?: (state: ScriptLoadState) => void;\n}\n\n/**\n * Diagnostic information about the GTM client state.\n * Useful for debugging integration issues.\n */\nexport interface GtmDiagnostics {\n /** Whether the client has been initialized */\n initialized: boolean;\n /** Whether all scripts have finished loading */\n ready: boolean;\n /** Name of the dataLayer being used */\n dataLayerName: string;\n /** Current size of the dataLayer array */\n dataLayerSize: number;\n /** Number of items in the pre-init queue */\n queueSize: number;\n /** Number of consent commands delivered */\n consentCommandsDelivered: number;\n /** Container IDs configured */\n containers: string[];\n /** Script load states for each container */\n scriptStates: ScriptLoadState[];\n /** Time since client was created (ms) */\n uptimeMs: number;\n /** Whether debug mode is enabled */\n debugMode: boolean;\n}\n\nexport interface GtmClient {\n readonly dataLayerName: string;\n init(): void;\n push(value: DataLayerValue): void;\n setConsentDefaults(state: import('./consent').ConsentState, options?: import('./consent').ConsentRegionOptions): void;\n updateConsent(state: import('./consent').ConsentState, options?: import('./consent').ConsentRegionOptions): void;\n teardown(): void;\n isInitialized(): boolean;\n /**\n * Synchronously check if all GTM scripts have finished loading.\n * Returns true if all scripts have loaded (successfully or failed), false if still loading.\n */\n isReady(): boolean;\n whenReady(): Promise<ScriptLoadState[]>;\n onReady(callback: (state: ScriptLoadState[]) => void): () => void;\n /**\n * Get diagnostic information about the GTM client state.\n * Useful for debugging integration issues.\n */\n getDiagnostics(): GtmDiagnostics;\n}\n","export const DEFAULT_GTM_HOST = 'https://www.googletagmanager.com';\nexport const DEFAULT_DATA_LAYER_NAME = 'dataLayer';\nexport const DEFAULT_MAX_DATA_LAYER_SIZE = 500;\n\n/**\n * Maximum reasonable wait time for consent waitForUpdate (30 minutes).\n * Values exceeding this will trigger a warning.\n */\nexport const MAX_CONSENT_WAIT_MS = 30 * 60 * 1000; // 30 minutes\n\n/**\n * Default timeout for script loading (30 seconds).\n */\nexport const DEFAULT_SCRIPT_TIMEOUT_MS = 30000;\n\n/**\n * Default timeout for GTM initialization check (5 seconds).\n */\nexport const DEFAULT_INIT_TIMEOUT_MS = 5000;\n\n/**\n * Default delay between retry attempts (1 second).\n */\nexport const DEFAULT_RETRY_DELAY_MS = 1000;\n\n/**\n * Maximum delay between retry attempts (30 seconds).\n */\nexport const MAX_RETRY_DELAY_MS = 30000;\n","import type { DataLayerValue } from './types';\n\nconst CONSENT_COMMAND = 'consent' as const;\nconst CONSENT_DEFAULT = 'default' as const;\nconst CONSENT_UPDATE = 'update' as const;\n\n/**\n * The four consent categories tracked by Google Consent Mode v2.\n */\nconst CONSENT_KEYS = ['ad_storage', 'analytics_storage', 'ad_user_data', 'ad_personalization'] as const;\n\n/**\n * A consent category key: 'ad_storage' | 'analytics_storage' | 'ad_user_data' | 'ad_personalization'\n */\nexport type ConsentKey = (typeof CONSENT_KEYS)[number];\n\n/**\n * A consent decision: 'granted' or 'denied'\n */\nexport type ConsentDecision = 'granted' | 'denied';\n\n/**\n * Consent state object for one or more categories.\n *\n * This is a **partial** record - you only need to specify the categories you want to set.\n * Unspecified categories retain their previous state when using `updateConsent()`.\n *\n * @example\n * ```ts\n * // All four categories\n * const fullState: ConsentState = {\n * ad_storage: 'granted',\n * analytics_storage: 'granted',\n * ad_user_data: 'granted',\n * ad_personalization: 'granted'\n * };\n *\n * // Single category (partial update)\n * const partialState: ConsentState = {\n * analytics_storage: 'granted'\n * };\n *\n * // Multiple specific categories\n * const mixedState: ConsentState = {\n * analytics_storage: 'granted',\n * ad_storage: 'denied'\n * };\n * ```\n */\nexport type ConsentState = Partial<Record<ConsentKey, ConsentDecision>>;\n\nexport interface ConsentRegionOptions {\n /**\n * ISO 3166-2 region codes (e.g., `US-CA`, `EEA`) that the consent command applies to.\n */\n region?: readonly string[];\n /**\n * Milliseconds to wait for an explicit update before firing tags when using the default command.\n */\n waitForUpdate?: number;\n}\n\nexport type ConsentCommand = typeof CONSENT_DEFAULT | typeof CONSENT_UPDATE;\n\nexport interface ConsentCommandInput {\n command: ConsentCommand;\n state: ConsentState;\n options?: ConsentRegionOptions;\n}\n\nexport type ConsentCommandValue =\n | [typeof CONSENT_COMMAND, ConsentCommand, ConsentState]\n | [typeof CONSENT_COMMAND, ConsentCommand, ConsentState, Record<string, unknown>];\n\nconst isConsentKey = (value: string): value is ConsentKey => (CONSENT_KEYS as readonly string[]).includes(value);\n\nconst isConsentDecision = (value: unknown): value is ConsentDecision => value === 'granted' || value === 'denied';\n\nconst assertValidRegions = (regions: readonly string[]) => {\n if (!Array.isArray(regions)) {\n throw new Error(\n 'Consent region list must be an array of ISO 3166-2 region codes. ' +\n `Received: ${typeof regions}. ` +\n 'Example: { region: [\"US-CA\", \"EEA\"] }'\n );\n }\n\n for (const region of regions) {\n if (typeof region !== 'string' || region.trim().length === 0) {\n throw new Error(\n 'Consent region codes must be non-empty ISO 3166-2 strings. ' +\n `Received: ${region === null ? 'null' : typeof region}. ` +\n 'Example: \"US-CA\", \"EEA\", \"US\"'\n );\n }\n }\n};\n\nconst assertValidWaitForUpdate = (waitForUpdate: number) => {\n if (!Number.isFinite(waitForUpdate) || waitForUpdate < 0) {\n throw new Error(\n `Invalid waitForUpdate value: ${waitForUpdate}. ` +\n 'waitForUpdate must be a non-negative finite number representing milliseconds to wait for consent update. ' +\n 'Example: { waitForUpdate: 500 }'\n );\n }\n};\n\nexport const normalizeConsentState = (state: ConsentState): ConsentState => {\n const normalizedEntries = Object.entries(state ?? {}).map(([key, value]) => {\n if (!isConsentKey(key)) {\n throw new Error(\n `Invalid consent key: \"${key}\". ` +\n 'Valid keys are: ad_storage, analytics_storage, ad_user_data, ad_personalization. ' +\n 'Example: { ad_storage: \"granted\", analytics_storage: \"denied\" }'\n );\n }\n\n if (!isConsentDecision(value)) {\n throw new Error(\n `Invalid consent value for key \"${key}\": ${value === null ? 'null' : typeof value === 'string' ? `\"${value}\"` : value}. ` +\n 'Consent values must be \"granted\" or \"denied\". ' +\n 'Example: { ad_storage: \"granted\" }'\n );\n }\n\n return [key, value] as const;\n });\n\n if (!normalizedEntries.length) {\n throw new Error(\n 'At least one consent key/value pair is required. ' +\n 'Example: { ad_storage: \"granted\", analytics_storage: \"granted\" }'\n );\n }\n\n const normalizedState = {} as ConsentState;\n for (const [key, value] of normalizedEntries) {\n normalizedState[key as ConsentKey] = value;\n }\n\n return Object.freeze(normalizedState);\n};\n\nconst normalizeOptions = (options?: ConsentRegionOptions): Record<string, unknown> | undefined => {\n if (!options) {\n return undefined;\n }\n\n const payload: Record<string, unknown> = {};\n\n if (options.region) {\n assertValidRegions(options.region);\n if (options.region.length) {\n payload.region = [...options.region];\n }\n }\n\n if (typeof options.waitForUpdate === 'number') {\n assertValidWaitForUpdate(options.waitForUpdate);\n payload.wait_for_update = options.waitForUpdate;\n }\n\n return Object.keys(payload).length ? payload : undefined;\n};\n\nexport const buildConsentCommand = ({ command, state, options }: ConsentCommandInput): ConsentCommandValue => {\n if (command !== CONSENT_DEFAULT && command !== CONSENT_UPDATE) {\n throw new Error(\n `Unsupported consent command: \"${command}\". ` +\n 'Valid commands are \"default\" (for initial consent state) or \"update\" (for user consent changes). ' +\n 'Example: buildConsentCommand({ command: \"default\", state: { analytics_storage: \"denied\" } })'\n );\n }\n\n const normalizedState = normalizeConsentState(state);\n const normalizedOptions = normalizeOptions(options);\n\n if (normalizedOptions) {\n return [CONSENT_COMMAND, command, normalizedState, normalizedOptions];\n }\n\n return [CONSENT_COMMAND, command, normalizedState];\n};\n\nexport const createConsentCommandValue = (input: ConsentCommandInput): DataLayerValue => {\n // Spread the tuple to convert it to a plain array for DataLayerValue compatibility\n return [...buildConsentCommand(input)];\n};\n\nexport const createConsentDefaultsCommand = (state: ConsentState, options?: ConsentRegionOptions): DataLayerValue =>\n createConsentCommandValue({ command: CONSENT_DEFAULT, state, options });\n\nexport const createConsentUpdateCommand = (state: ConsentState, options?: ConsentRegionOptions): DataLayerValue =>\n createConsentCommandValue({ command: CONSENT_UPDATE, state, options });\n\nexport const consent = {\n buildConsentCommand,\n createConsentDefaultsCommand,\n createConsentUpdateCommand,\n normalizeConsentState\n};\n","import type { ConsentState } from '../consent';\n\n/**\n * Pre-configured consent state presets for common scenarios.\n *\n * These presets cover the most common consent patterns:\n * - `eeaDefault`: All denied (GDPR compliant default)\n * - `allGranted`: All granted (user accepts everything)\n * - `analyticsOnly`: Mixed state (analytics only, no ads)\n *\n * For custom combinations, pass a partial `ConsentState` object to `updateConsent()`.\n * You only need to specify the categories you want to update.\n *\n * @example\n * ```ts\n * // Use a preset\n * client.updateConsent(consentPresets.allGranted);\n *\n * // Or create a custom state\n * client.updateConsent({\n * analytics_storage: 'granted',\n * ad_storage: 'denied'\n * });\n *\n * // Partial updates (only update specific categories)\n * client.updateConsent({ analytics_storage: 'granted' });\n * ```\n */\nexport const consentPresets = {\n /**\n * All categories denied - GDPR/EEA compliant default.\n *\n * Use as the initial state for regions requiring explicit opt-in consent.\n * Tags will be blocked until the user grants specific permissions.\n *\n * | Category | State |\n * |----------|-------|\n * | ad_storage | denied |\n * | analytics_storage | denied |\n * | ad_user_data | denied |\n * | ad_personalization | denied |\n */\n eeaDefault: Object.freeze({\n ad_storage: 'denied',\n analytics_storage: 'denied',\n ad_user_data: 'denied',\n ad_personalization: 'denied'\n } satisfies ConsentState),\n\n /**\n * All categories granted - user accepts all tracking.\n *\n * Use when the user clicks \"Accept All\" or in regions where consent is implied.\n *\n * | Category | State |\n * |----------|-------|\n * | ad_storage | granted |\n * | analytics_storage | granted |\n * | ad_user_data | granted |\n * | ad_personalization | granted |\n */\n allGranted: Object.freeze({\n ad_storage: 'granted',\n analytics_storage: 'granted',\n ad_user_data: 'granted',\n ad_personalization: 'granted'\n } satisfies ConsentState),\n\n /**\n * Analytics allowed, advertising denied - mixed consent state.\n *\n * Use when the user accepts analytics/statistics but rejects advertising cookies.\n * This is a common \"essential + analytics\" consent pattern.\n *\n * | Category | State |\n * |----------|-------|\n * | ad_storage | denied |\n * | analytics_storage | granted |\n * | ad_user_data | denied |\n * | ad_personalization | denied |\n */\n analyticsOnly: Object.freeze({\n ad_storage: 'denied',\n analytics_storage: 'granted',\n ad_user_data: 'denied',\n ad_personalization: 'denied'\n } satisfies ConsentState)\n} as const;\n\nexport type ConsentPresetName = keyof typeof consentPresets;\n\nexport const getConsentPreset = (name: ConsentPresetName): ConsentState => ({\n ...consentPresets[name]\n});\n\n/**\n * Convenience export for the EEA default consent state.\n * All categories denied - GDPR/EEA compliant default.\n */\nexport const eeaDefault = consentPresets.eeaDefault;\n\n/**\n * Convenience export for the all-granted consent state.\n * All categories granted - user accepts all tracking.\n */\nexport const allGranted = consentPresets.allGranted;\n\n/**\n * Convenience export for the analytics-only consent state.\n * Analytics allowed, advertising denied.\n */\nexport const analyticsOnly = consentPresets.analyticsOnly;\n","import type { DataLayerState, DataLayerValue, Logger } from './types';\n\ninterface EnsureDataLayerResult extends DataLayerState {\n snapshot: DataLayerValue[] | undefined;\n}\n\nexport interface MutationTraceOptions {\n logger: Logger;\n dataLayerName: string;\n}\n\nconst isArray = (value: unknown): value is DataLayerValue[] => Array.isArray(value);\n\nexport const ensureDataLayer = (name: string): EnsureDataLayerResult => {\n const globalScope = globalThis as Record<string, unknown>;\n const existing = globalScope[name];\n const snapshot = isArray(existing) ? [...existing] : undefined;\n\n if (!isArray(existing)) {\n globalScope[name] = [] as DataLayerValue[];\n }\n\n return {\n name,\n dataLayer: globalScope[name] as DataLayerValue[],\n created: !isArray(existing),\n restore() {\n if (!isArray(existing)) {\n delete globalScope[name];\n return;\n }\n\n const clone = snapshot ? [...snapshot] : [];\n globalScope[name] = clone;\n },\n snapshot\n };\n};\n\nexport const pushToDataLayer = (state: DataLayerState, value: DataLayerValue) => {\n state.dataLayer.push(value);\n};\n\n/**\n * Creates a Proxy wrapper around a dataLayer array that logs all mutations.\n * Used in debug mode to help developers trace dataLayer changes.\n */\nexport const createTracedDataLayer = (dataLayer: DataLayerValue[], options: MutationTraceOptions): DataLayerValue[] => {\n const { logger, dataLayerName } = options;\n\n const formatValue = (value: unknown): string => {\n if (value === null) return 'null';\n if (value === undefined) return 'undefined';\n if (typeof value === 'function') return '[Function]';\n if (typeof value === 'object') {\n try {\n const str = JSON.stringify(value);\n return str.length > 100 ? str.slice(0, 100) + '...' : str;\n } catch {\n return '[Object with circular reference]';\n }\n }\n return String(value);\n };\n\n return new Proxy(dataLayer, {\n set(target, property, value) {\n const index = Number(property);\n const isIndex = !Number.isNaN(index) && Number.isInteger(index) && index >= 0;\n\n if (isIndex) {\n const isReplacement = index < target.length;\n if (isReplacement) {\n logger.debug(`[${dataLayerName}] Replaced value at index ${index}`, {\n previousValue: formatValue(target[index]),\n newValue: formatValue(value)\n });\n } else {\n logger.debug(`[${dataLayerName}] Added value at index ${index}`, {\n value: formatValue(value)\n });\n }\n }\n\n Reflect.set(target, property, value);\n return true;\n },\n\n deleteProperty(target, property) {\n const index = Number(property);\n const isIndex = !Number.isNaN(index) && Number.isInteger(index) && index >= 0;\n\n if (isIndex && index < target.length) {\n logger.debug(`[${dataLayerName}] Deleted value at index ${index}`, {\n deletedValue: formatValue(target[index])\n });\n }\n\n Reflect.deleteProperty(target, property);\n return true;\n },\n\n get(target, property) {\n const value = target[property as keyof typeof target];\n\n // Wrap mutating array methods to log their operations\n if (typeof value === 'function') {\n if (property === 'push') {\n return function (...args: DataLayerValue[]) {\n logger.debug(`[${dataLayerName}] push() called with ${args.length} item(s)`, {\n items: args.map((arg) => formatValue(arg)),\n previousLength: target.length\n });\n return Array.prototype.push.apply(target, args);\n };\n }\n\n if (property === 'pop') {\n return function () {\n const poppedValue = target[target.length - 1];\n logger.debug(`[${dataLayerName}] pop() called`, {\n poppedValue: formatValue(poppedValue),\n previousLength: target.length\n });\n return Array.prototype.pop.call(target);\n };\n }\n\n if (property === 'shift') {\n return function () {\n const shiftedValue = target[0];\n logger.debug(`[${dataLayerName}] shift() called`, {\n shiftedValue: formatValue(shiftedValue),\n previousLength: target.length\n });\n return Array.prototype.shift.call(target);\n };\n }\n\n if (property === 'unshift') {\n return function (...args: DataLayerValue[]) {\n logger.debug(`[${dataLayerName}] unshift() called with ${args.length} item(s)`, {\n items: args.map((arg) => formatValue(arg)),\n previousLength: target.length\n });\n return Array.prototype.unshift.apply(target, args);\n };\n }\n\n if (property === 'splice') {\n return function (start: number, deleteCount?: number, ...items: DataLayerValue[]) {\n const deletedItems = target.slice(start, start + (deleteCount ?? target.length - start));\n logger.debug(`[${dataLayerName}] splice() called`, {\n start,\n deleteCount: deleteCount ?? 'rest',\n deletedItems: deletedItems.map((item) => formatValue(item)),\n insertedItems: items.map((item) => formatValue(item)),\n previousLength: target.length\n });\n return Array.prototype.splice.apply(target, [start, deleteCount ?? target.length - start, ...items]);\n };\n }\n }\n\n return value;\n }\n });\n};\n","import type { Logger, PartialLogger } from './types';\n\ntype LogLevel = keyof Logger;\n\nconst levels: LogLevel[] = ['debug', 'info', 'warn', 'error'];\n\nconst noop = () => {\n /* intentionally empty */\n};\n\n/**\n * Color codes for different log levels in console output.\n * Uses ANSI-like browser console styling.\n */\nconst levelColors: Record<LogLevel, string> = {\n debug: 'color: #6b7280', // gray\n info: 'color: #3b82f6', // blue\n warn: 'color: #f59e0b', // amber\n error: 'color: #ef4444' // red\n};\n\nconst levelPrefixes: Record<LogLevel, string> = {\n debug: '[GTM-Kit DEBUG]',\n info: '[GTM-Kit INFO]',\n warn: '[GTM-Kit WARN]',\n error: '[GTM-Kit ERROR]'\n};\n\n/**\n * Creates a debug logger that outputs formatted messages to the console.\n * This is the built-in logger used when `debug: true` is set.\n */\nexport const createDebugLogger = (): Logger => {\n const createLogFn =\n (level: LogLevel) =>\n (message: string, details?: Record<string, unknown>): void => {\n const timestamp = new Date().toISOString().split('T')[1].slice(0, -1);\n const prefix = levelPrefixes[level];\n const style = levelColors[level];\n\n /* eslint-disable no-console -- Logger's purpose is to output to console */\n const consoleFn =\n level === 'error'\n ? console.error\n : level === 'warn'\n ? console.warn\n : level === 'info'\n ? console.info\n : console.log;\n /* eslint-enable no-console */\n\n if (details && Object.keys(details).length > 0) {\n consoleFn(`%c${timestamp} ${prefix}%c ${message}`, style, 'color: inherit', details);\n } else {\n consoleFn(`%c${timestamp} ${prefix}%c ${message}`, style, 'color: inherit');\n }\n };\n\n return {\n debug: createLogFn('debug'),\n info: createLogFn('info'),\n warn: createLogFn('warn'),\n error: createLogFn('error')\n };\n};\n\nexport const createLogger = (logger?: PartialLogger): Logger => {\n const safeLogger: Partial<Record<LogLevel, (message: string, details?: Record<string, unknown>) => void>> = {};\n\n for (const level of levels) {\n const provided = logger?.[level];\n if (typeof provided === 'function') {\n safeLogger[level] = provided.bind(logger);\n continue;\n }\n safeLogger[level] = noop;\n }\n\n return safeLogger as Logger;\n};\n\nexport type LoggerFacade = ReturnType<typeof createLogger>;\n","import { DEFAULT_DATA_LAYER_NAME, DEFAULT_GTM_HOST } from './constants';\nimport type { ContainerConfigInput, ContainerDescriptor } from './types';\n\n/**\n * Type guard to check if a value is a string.\n * @internal Primarily for internal use. API may change.\n */\nexport const isString = (value: unknown): value is string => typeof value === 'string';\n\n/**\n * Normalize a container input to a ContainerDescriptor.\n * @internal Primarily for internal use. API may change.\n */\nexport const normalizeContainer = (input: ContainerConfigInput): ContainerDescriptor => {\n if (isString(input)) {\n return { id: input };\n }\n return input;\n};\n\n/**\n * Normalize container inputs to an array of ContainerDescriptors.\n * @internal Primarily for internal use. API may change.\n */\nexport const normalizeContainers = (\n containers: ContainerConfigInput | ContainerConfigInput[]\n): ContainerDescriptor[] => {\n if (Array.isArray(containers)) {\n return containers.map(normalizeContainer);\n }\n return [normalizeContainer(containers)];\n};\n\n/**\n * Convert query params to a Record<string, string>.\n * @internal Primarily for internal use. API may change.\n */\nexport const toRecord = (params?: Record<string, string | number | boolean>): Record<string, string> => {\n if (!params) {\n return {};\n }\n return Object.entries(params).reduce<Record<string, string>>((acc, [key, value]) => {\n acc[key] = String(value);\n return acc;\n }, {});\n};\n\n/**\n * Normalize a host URL by removing trailing slashes.\n * @internal Primarily for internal use. API may change.\n */\nexport const normalizeHost = (host: string): string => (host.endsWith('/') ? host.slice(0, -1) : host);\n\ntype UrlKind = 'gtm' | 'ns';\n\nconst buildUrl = (\n kind: UrlKind,\n host: string,\n containerId: string,\n queryParams?: Record<string, string | number | boolean>,\n dataLayerName: string = DEFAULT_DATA_LAYER_NAME\n): string => {\n const normalizedHost = normalizeHost(host);\n const searchParams = new URLSearchParams({ id: containerId });\n\n const params = toRecord(queryParams);\n\n // Add dataLayer name parameter if using custom name\n if (dataLayerName !== DEFAULT_DATA_LAYER_NAME && params.l === undefined) {\n params.l = dataLayerName;\n }\n\n for (const [key, value] of Object.entries(params)) {\n if (key === 'id') {\n continue;\n }\n searchParams.set(key, value);\n }\n\n const suffix = kind === 'gtm' ? 'gtm.js' : 'ns.html';\n return `${normalizedHost}/${suffix}?${searchParams.toString()}`;\n};\n\n/**\n * Build a GTM script URL.\n */\nexport const buildGtmScriptUrl = (\n host: string,\n containerId: string,\n queryParams?: Record<string, string | number | boolean>,\n dataLayerName: string = DEFAULT_DATA_LAYER_NAME\n): string => buildUrl('gtm', host, containerId, queryParams, dataLayerName);\n\n/**\n * Build a GTM noscript iframe URL.\n */\nexport const buildGtmNoscriptUrl = (\n host: string,\n containerId: string,\n queryParams?: Record<string, string | number | boolean>,\n dataLayerName: string = DEFAULT_DATA_LAYER_NAME\n): string => buildUrl('ns', host, containerId, queryParams, dataLayerName);\n\n/**\n * Escape a string for use in HTML attributes.\n * @internal Primarily for internal use. API may change.\n */\nexport const escapeAttributeValue = (value: string): string =>\n value.replace(/&/g, '&amp;').replace(/\"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n\n// Re-export default host for convenience\nexport { DEFAULT_GTM_HOST };\n","import { DEFAULT_DATA_LAYER_NAME, DEFAULT_GTM_HOST } from './constants';\nimport { createLogger } from './logger';\nimport type {\n ContainerDescriptor,\n CreateGtmClientOptions,\n ScriptAttributes,\n ScriptLoadState,\n ScriptLoadStatus,\n ScriptRetryOptions\n} from './types';\nimport { getGoogleTagManager } from './types';\nimport { buildGtmScriptUrl } from './url-utils';\n\nconst CONTAINER_ATTR = 'data-gtm-container-id';\nconst INSTANCE_ATTR = 'data-gtm-kit-instance';\n\n// Default values for retry and timeout\nconst DEFAULT_RETRY_ATTEMPTS = 0;\nconst DEFAULT_RETRY_DELAY = 1000;\nconst DEFAULT_RETRY_MAX_DELAY = 30000;\nconst DEFAULT_SCRIPT_TIMEOUT = 30000;\nconst DEFAULT_INITIALIZATION_TIMEOUT = 5000;\n\ninterface Deferred<T> {\n promise: Promise<T>;\n resolve: (value: T) => void;\n settled: boolean;\n}\n\nconst createDeferred = <T>(): Deferred<T> => {\n let resolved = false;\n let resolver: (value: T) => void;\n\n const promise = new Promise<T>((resolve) => {\n resolver = resolve;\n });\n\n return {\n get settled() {\n return resolved;\n },\n promise,\n resolve: (value: T) => {\n if (resolved) {\n return;\n }\n\n resolved = true;\n resolver(value);\n }\n } as Deferred<T>;\n};\n\nexport interface NormalizedContainer extends ContainerDescriptor {\n queryParams?: Record<string, string | number | boolean>;\n}\n\nexport interface ScriptManagerOptions {\n instanceId: string;\n host?: string;\n dataLayerName?: string;\n scriptAttributes?: ScriptAttributes;\n defaultQueryParams?: Record<string, string | number | boolean>;\n logger?: CreateGtmClientOptions['logger'];\n retry?: ScriptRetryOptions;\n scriptTimeout?: number;\n onScriptError?: (state: ScriptLoadState) => void;\n onScriptTimeout?: (containerId: string) => void;\n verifyInitialization?: boolean;\n initializationTimeout?: number;\n onPartialLoad?: (state: ScriptLoadState) => void;\n}\n\nexport interface EnsureResult {\n inserted: HTMLScriptElement[];\n}\n\nconst findExistingScript = (containerId: string): HTMLScriptElement | null => {\n if (typeof document === 'undefined') {\n return null;\n }\n\n const attrSelector = `script[${CONTAINER_ATTR}=\"${containerId}\"]`;\n const existingWithAttr = document.querySelector(attrSelector);\n if (existingWithAttr) {\n return existingWithAttr as HTMLScriptElement;\n }\n\n const scripts = Array.from(document.getElementsByTagName('script'));\n return scripts.find((script) => script.src.includes(`id=${encodeURIComponent(containerId)}`)) || null;\n};\n\nconst formatErrorMessage = (event: Event): string => {\n if (event instanceof ErrorEvent) {\n if (event.error) {\n return String(event.error);\n }\n\n if (event.message) {\n return event.message;\n }\n }\n\n return 'Failed to load GTM script.';\n};\n\nexport class ScriptManager {\n private readonly logger = createLogger(this.options.logger);\n private readonly host = this.options.host ?? DEFAULT_GTM_HOST;\n private readonly dataLayerName = this.options.dataLayerName ?? DEFAULT_DATA_LAYER_NAME;\n private readonly defaultQueryParams = this.options.defaultQueryParams;\n private readonly scriptAttributes = this.options.scriptAttributes;\n private readonly insertedScripts = new Set<HTMLScriptElement>();\n private readonly readyCallbacks = new Set<(state: ScriptLoadState[]) => void>();\n private readiness = createDeferred<ScriptLoadState[]>();\n private readonly loadStates = new Map<string, ScriptLoadState>();\n private readonly pendingContainers = new Set<string>();\n\n // Retry configuration\n private readonly retryAttempts: number;\n private readonly retryDelay: number;\n private readonly retryMaxDelay: number;\n private readonly scriptTimeout: number;\n private readonly onScriptError?: (state: ScriptLoadState) => void;\n private readonly onScriptTimeout?: (containerId: string) => void;\n\n // Initialization verification\n private readonly verifyInitialization: boolean;\n private readonly initializationTimeout: number;\n private readonly onPartialLoad?: (state: ScriptLoadState) => void;\n\n // Retry tracking\n private readonly retryCounters = new Map<string, number>();\n private readonly activeTimeouts = new Map<string, ReturnType<typeof setTimeout>>();\n private readonly verificationTimeouts = new Map<string, ReturnType<typeof setTimeout>>();\n\n // Page unload handling\n private unloadHandler: (() => void) | null = null;\n private isUnloading = false;\n\n constructor(private readonly options: ScriptManagerOptions) {\n // Initialize retry configuration\n this.retryAttempts = options.retry?.attempts ?? DEFAULT_RETRY_ATTEMPTS;\n this.retryDelay = options.retry?.delay ?? DEFAULT_RETRY_DELAY;\n this.retryMaxDelay = options.retry?.maxDelay ?? DEFAULT_RETRY_MAX_DELAY;\n this.scriptTimeout = options.scriptTimeout ?? DEFAULT_SCRIPT_TIMEOUT;\n this.onScriptError = options.onScriptError;\n this.onScriptTimeout = options.onScriptTimeout;\n\n // Initialize verification configuration\n this.verifyInitialization = options.verifyInitialization ?? false;\n this.initializationTimeout = options.initializationTimeout ?? DEFAULT_INITIALIZATION_TIMEOUT;\n this.onPartialLoad = options.onPartialLoad;\n }\n\n whenReady(): Promise<ScriptLoadState[]> {\n return this.readiness.promise;\n }\n\n isReady(): boolean {\n return this.readiness.settled;\n }\n\n getScriptStates(): ScriptLoadState[] {\n return Array.from(this.loadStates.values());\n }\n\n onReady(callback: (state: ScriptLoadState[]) => void): () => void {\n this.readyCallbacks.add(callback);\n\n if (this.readiness.settled) {\n callback(Array.from(this.loadStates.values()));\n }\n\n return () => {\n this.readyCallbacks.delete(callback);\n };\n }\n\n private notifyReady(): void {\n const snapshot = Array.from(this.loadStates.values());\n\n if (!this.readiness.settled) {\n this.readiness.resolve(snapshot);\n }\n\n for (const callback of this.readyCallbacks) {\n callback(snapshot);\n }\n }\n\n private maybeNotifyReady(): void {\n if (this.pendingContainers.size === 0) {\n this.notifyReady();\n }\n }\n\n private recordState(state: ScriptLoadState): void {\n this.loadStates.set(state.containerId, state);\n }\n\n private resetReadiness(): void {\n this.pendingContainers.clear();\n this.loadStates.clear();\n this.readiness = createDeferred<ScriptLoadState[]>();\n }\n\n /**\n * Calculate delay for retry attempt using exponential backoff.\n * delay = min(initialDelay * 2^attempt, maxDelay)\n */\n private calculateRetryDelay(attempt: number): number {\n const delay = this.retryDelay * Math.pow(2, attempt);\n return Math.min(delay, this.retryMaxDelay);\n }\n\n /**\n * Get current retry count for a container.\n */\n private getRetryCount(containerId: string): number {\n return this.retryCounters.get(containerId) ?? 0;\n }\n\n /**\n * Check if retry is available for a container.\n */\n private canRetry(containerId: string): boolean {\n return this.getRetryCount(containerId) < this.retryAttempts;\n }\n\n /**\n * Clear timeout for a container.\n */\n private clearContainerTimeout(containerId: string): void {\n const timeout = this.activeTimeouts.get(containerId);\n if (timeout) {\n clearTimeout(timeout);\n this.activeTimeouts.delete(containerId);\n }\n }\n\n /**\n * Schedule a retry for a failed container.\n */\n private scheduleRetry(container: NormalizedContainer, targetParent: HTMLElement): void {\n const containerId = container.id;\n const currentAttempt = this.getRetryCount(containerId);\n const delay = this.calculateRetryDelay(currentAttempt);\n\n this.logger.info('Scheduling retry for GTM container.', {\n containerId,\n attempt: currentAttempt + 1,\n maxAttempts: this.retryAttempts,\n delay\n });\n\n this.retryCounters.set(containerId, currentAttempt + 1);\n\n setTimeout(() => {\n this.loadScript(container, targetParent);\n }, delay);\n }\n\n /**\n * Handle final failure after all retries exhausted.\n */\n private handleFinalFailure(containerId: string, url: string, error: string, isTimeout: boolean): void {\n const state: ScriptLoadState = {\n containerId,\n src: url,\n status: 'failed',\n error: isTimeout ? `Script load timeout (${this.scriptTimeout}ms)` : error,\n fromCache: false\n };\n\n this.recordState(state);\n this.pendingContainers.delete(containerId);\n\n // Call error callback\n if (this.onScriptError) {\n try {\n this.onScriptError(state);\n } catch (callbackError) {\n this.logger.error('Error in onScriptError callback.', { error: callbackError });\n }\n }\n\n this.maybeNotifyReady();\n }\n\n /**\n * Load a single container script with retry and timeout support.\n * Returns the created script element.\n */\n private loadScript(container: NormalizedContainer, targetParent: HTMLElement): HTMLScriptElement {\n const containerId = container.id;\n const params = {\n ...this.defaultQueryParams,\n ...container.queryParams\n };\n\n const script = document.createElement('script');\n const url = buildGtmScriptUrl(this.host, containerId, params, this.dataLayerName);\n script.src = url;\n script.setAttribute(CONTAINER_ATTR, containerId);\n script.setAttribute(INSTANCE_ATTR, this.options.instanceId);\n\n const attributes = this.scriptAttributes ?? {};\n if (attributes.async !== undefined) {\n script.async = attributes.async;\n } else {\n script.async = true;\n }\n if (attributes.defer !== undefined) {\n script.defer = attributes.defer;\n }\n\n for (const [key, value] of Object.entries(attributes)) {\n if (key === 'async' || key === 'defer') {\n continue;\n }\n\n if (value === undefined || value === null) {\n continue;\n }\n\n const stringValue = String(value);\n\n if (key === 'nonce') {\n script.nonce = stringValue;\n }\n\n script.setAttribute(key, stringValue);\n }\n\n let settled = false;\n const loadStartTime = performance.now();\n\n const settle = (status: ScriptLoadStatus, event?: Event): void => {\n if (settled) {\n return;\n }\n settled = true;\n\n // Calculate load time\n const loadTimeMs = Math.round(performance.now() - loadStartTime);\n\n // Clear the timeout\n this.clearContainerTimeout(containerId);\n\n if (status === 'loaded') {\n // Script loaded - check if we need to verify GTM initialization\n if (this.verifyInitialization) {\n this.startInitializationVerification(containerId, url, loadTimeMs);\n } else {\n // No verification, mark as success immediately\n const state: ScriptLoadState = {\n containerId,\n src: url,\n status: 'loaded',\n fromCache: false,\n loadTimeMs\n };\n this.recordState(state);\n this.pendingContainers.delete(containerId);\n this.logger.info('GTM container script loaded successfully.', { containerId, src: url, loadTimeMs });\n this.maybeNotifyReady();\n }\n return;\n }\n\n // Failure - check if we can retry\n const errorMessage = event ? formatErrorMessage(event) : 'Script load failed';\n const canRetry = this.canRetry(containerId);\n\n if (canRetry) {\n this.logger.warn('GTM script load failed, will retry.', {\n containerId,\n src: url,\n error: errorMessage,\n retriesRemaining: this.retryAttempts - this.getRetryCount(containerId)\n });\n // Remove the failed script\n if (script.parentNode) {\n script.parentNode.removeChild(script);\n }\n this.insertedScripts.delete(script);\n this.scheduleRetry(container, targetParent);\n } else {\n this.logger.error('GTM script load failed, no retries remaining.', {\n containerId,\n src: url,\n error: errorMessage\n });\n this.handleFinalFailure(containerId, url, errorMessage, false);\n }\n };\n\n script.addEventListener('load', () => settle('loaded'));\n script.addEventListener('error', (event) => settle('failed', event));\n\n // Set up timeout if configured\n if (this.scriptTimeout > 0) {\n const timeoutId = setTimeout(() => {\n if (!settled) {\n this.logger.warn('GTM script load timeout.', {\n containerId,\n src: url,\n timeout: this.scriptTimeout\n });\n\n // Call timeout callback\n if (this.onScriptTimeout) {\n try {\n this.onScriptTimeout(containerId);\n } catch (callbackError) {\n this.logger.error('Error in onScriptTimeout callback.', { error: callbackError });\n }\n }\n\n // Treat timeout as failure for retry logic\n const canRetry = this.canRetry(containerId);\n if (canRetry) {\n settled = true;\n // Remove the timed-out script\n if (script.parentNode) {\n script.parentNode.removeChild(script);\n }\n this.insertedScripts.delete(script);\n this.scheduleRetry(container, targetParent);\n } else {\n settle('failed');\n // Override with timeout-specific error\n const state = this.loadStates.get(containerId);\n if (state) {\n state.error = `Script load timeout (${this.scriptTimeout}ms)`;\n }\n }\n }\n }, this.scriptTimeout);\n\n this.activeTimeouts.set(containerId, timeoutId);\n }\n\n targetParent.appendChild(script);\n this.insertedScripts.add(script);\n this.logger.debug('Injecting GTM container script.', { containerId, src: url });\n\n return script;\n }\n\n ensure(containers: NormalizedContainer[]): EnsureResult {\n if (typeof document === 'undefined') {\n this.logger.warn('No document available – skipping script injection.');\n\n for (const container of containers) {\n if (!container.id) {\n continue;\n }\n\n this.recordState({\n containerId: container.id,\n status: 'skipped',\n error: 'Document unavailable for script injection.'\n });\n }\n\n this.maybeNotifyReady();\n return { inserted: [] };\n }\n\n const inserted: HTMLScriptElement[] = [];\n const targetParent = document.head || document.body;\n if (!targetParent) {\n this.logger.error('Unable to find document.head or document.body for script injection.');\n\n for (const container of containers) {\n if (!container.id) {\n continue;\n }\n\n this.recordState({\n containerId: container.id,\n status: 'skipped',\n error: 'Missing document.head and document.body for GTM script injection.'\n });\n }\n\n this.maybeNotifyReady();\n return { inserted: [] };\n }\n\n // Set up page unload handler to gracefully handle navigation during script load\n this.setupUnloadHandler();\n\n for (const container of containers) {\n if (!container.id || !container.id.trim()) {\n this.logger.warn('Skipping container with empty or invalid id.', { container });\n continue;\n }\n\n const existing = findExistingScript(container.id);\n if (existing) {\n this.logger.debug('Container script already present, skipping injection.', {\n containerId: container.id\n });\n\n this.recordState({\n containerId: container.id,\n src: existing.src,\n status: 'loaded',\n fromCache: true\n });\n continue;\n }\n\n // Initialize retry counter for this container\n this.retryCounters.set(container.id, 0);\n this.pendingContainers.add(container.id);\n\n // Load script with retry and timeout support\n const script = this.loadScript(container, targetParent);\n inserted.push(script);\n }\n\n this.maybeNotifyReady();\n return { inserted };\n }\n\n /**\n * Set up handler for page unload to gracefully resolve pending scripts.\n * Uses 'pagehide' event which is more reliable than 'beforeunload' for cleanup.\n */\n private setupUnloadHandler(): void {\n if (typeof window === 'undefined' || this.unloadHandler) {\n return;\n }\n\n this.unloadHandler = () => {\n this.handlePageUnload();\n };\n\n // Use 'pagehide' as it's more reliable for cleanup (fires even on bfcache navigation)\n window.addEventListener('pagehide', this.unloadHandler);\n }\n\n /**\n * Handle page unload by marking pending scripts as skipped and resolving promises.\n * This prevents hanging promises and ensures clean state during navigation.\n */\n private handlePageUnload(): void {\n if (this.isUnloading) {\n return;\n }\n\n this.isUnloading = true;\n\n // Mark all pending containers as skipped\n for (const containerId of this.pendingContainers) {\n this.recordState({\n containerId,\n status: 'skipped',\n error: 'Page navigation interrupted script load.'\n });\n }\n\n // Clear all pending containers\n this.pendingContainers.clear();\n\n // Clear all timeouts to prevent callbacks from firing after unload\n for (const timeout of this.activeTimeouts.values()) {\n clearTimeout(timeout);\n }\n this.activeTimeouts.clear();\n\n for (const timeout of this.verificationTimeouts.values()) {\n clearTimeout(timeout);\n }\n this.verificationTimeouts.clear();\n\n // Resolve the readiness promise immediately to prevent hanging\n this.notifyReady();\n }\n\n /**\n * Remove page unload handler.\n */\n private removeUnloadHandler(): void {\n if (typeof window === 'undefined' || !this.unloadHandler) {\n return;\n }\n\n window.removeEventListener('pagehide', this.unloadHandler);\n this.unloadHandler = null;\n }\n\n /**\n * Start initialization verification after script loads.\n * Checks for GTM initialization by looking for google_tag_manager global.\n */\n private startInitializationVerification(containerId: string, url: string, loadTimeMs?: number): void {\n const startTime = Date.now();\n const pollInterval = 100; // Check every 100ms\n\n const checkInitialization = (): boolean => {\n // Check for google_tag_manager global with this container\n const gtm = getGoogleTagManager();\n return gtm !== undefined && typeof gtm[containerId] !== 'undefined';\n };\n\n const poll = (): void => {\n if (checkInitialization()) {\n // GTM initialized successfully\n this.clearVerificationTimeout(containerId);\n const state: ScriptLoadState = {\n containerId,\n src: url,\n status: 'loaded',\n fromCache: false,\n loadTimeMs\n };\n this.recordState(state);\n this.pendingContainers.delete(containerId);\n this.logger.info('GTM container initialized successfully.', { containerId, src: url, loadTimeMs });\n this.maybeNotifyReady();\n return;\n }\n\n const elapsed = Date.now() - startTime;\n if (elapsed >= this.initializationTimeout) {\n // Timeout - mark as partial load failure\n this.clearVerificationTimeout(containerId);\n const state: ScriptLoadState = {\n containerId,\n src: url,\n status: 'partial',\n fromCache: false,\n error: `GTM failed to initialize within ${this.initializationTimeout}ms`,\n loadTimeMs\n };\n this.recordState(state);\n this.pendingContainers.delete(containerId);\n this.logger.warn('GTM container loaded but failed to initialize.', {\n containerId,\n src: url,\n timeout: this.initializationTimeout,\n loadTimeMs\n });\n\n // Call partial load callback\n if (this.onPartialLoad) {\n try {\n this.onPartialLoad(state);\n } catch (callbackError) {\n this.logger.error('Error in onPartialLoad callback.', { error: callbackError });\n }\n }\n\n this.maybeNotifyReady();\n return;\n }\n\n // Schedule next poll\n const timeoutId = setTimeout(poll, pollInterval);\n this.verificationTimeouts.set(containerId, timeoutId);\n };\n\n // Start polling\n poll();\n }\n\n /**\n * Clear verification timeout for a container.\n */\n private clearVerificationTimeout(containerId: string): void {\n const timeout = this.verificationTimeouts.get(containerId);\n if (timeout) {\n clearTimeout(timeout);\n this.verificationTimeouts.delete(containerId);\n }\n }\n\n teardown() {\n if (typeof document === 'undefined') {\n return;\n }\n\n // Remove page unload handler\n this.removeUnloadHandler();\n this.isUnloading = false;\n\n // Clear any active timeouts\n for (const timeout of this.activeTimeouts.values()) {\n clearTimeout(timeout);\n }\n this.activeTimeouts.clear();\n\n // Clear verification timeouts\n for (const timeout of this.verificationTimeouts.values()) {\n clearTimeout(timeout);\n }\n this.verificationTimeouts.clear();\n\n // Clear retry counters\n this.retryCounters.clear();\n\n for (const script of this.insertedScripts) {\n if (script.parentNode) {\n script.parentNode.removeChild(script);\n }\n }\n\n this.insertedScripts.clear();\n this.resetReadiness();\n }\n}\n","import { DEFAULT_DATA_LAYER_NAME, DEFAULT_MAX_DATA_LAYER_SIZE, MAX_CONSENT_WAIT_MS } from './constants';\nimport { ensureDataLayer, pushToDataLayer, createTracedDataLayer } from './data-layer';\nimport { createConsentCommandValue } from './consent';\nimport type { ConsentRegionOptions, ConsentState } from './consent';\nimport { createLogger, createDebugLogger } from './logger';\nimport { ScriptManager } from './script-manager';\nimport { normalizeContainer } from './url-utils';\nimport { isValidDataLayerName } from './types';\nimport type { CreateGtmClientOptions, DataLayerValue, GtmClient, GtmDiagnostics, ScriptLoadState } from './types';\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n};\n\n/**\n * WeakMap cache for serialization results.\n * Uses WeakMap to automatically clean up when objects are garbage collected,\n * preventing memory leaks while avoiding redundant serialization of the same objects.\n */\nconst serializationCache = new WeakMap<object, string | null>();\n\n/**\n * Serialize a value with circular reference detection.\n * @param value - The value to serialize\n * @param seen - Set of objects currently being serialized (for cycle detection)\n */\nconst serializeUnknown = (value: unknown, seen: Set<object> = new Set()): string | null => {\n // Check cache for object values (arrays and plain objects)\n if (typeof value === 'object' && value !== null) {\n if (serializationCache.has(value)) {\n return serializationCache.get(value) ?? null;\n }\n // Detect circular reference - if we've seen this object in the current path\n if (seen.has(value)) {\n // Circular reference detected, return null (cannot serialize)\n return null;\n }\n }\n\n if (value === null || typeof value === 'boolean' || typeof value === 'number') {\n return JSON.stringify(value);\n }\n\n if (typeof value === 'string') {\n return JSON.stringify(value);\n }\n\n if (Array.isArray(value)) {\n // Add to seen set before recursing\n seen.add(value);\n const parts: string[] = [];\n for (const entry of value) {\n const serialized = serializeUnknown(entry, seen);\n if (serialized === null) {\n seen.delete(value);\n serializationCache.set(value, null);\n return null;\n }\n parts.push(serialized);\n }\n seen.delete(value);\n const result = `[${parts.join(',')}]`;\n serializationCache.set(value, result);\n return result;\n }\n\n if (isPlainObject(value)) {\n // Add to seen set before recursing\n seen.add(value);\n const keys = Object.keys(value).sort();\n const parts: string[] = [];\n for (const key of keys) {\n const serialized = serializeUnknown(value[key], seen);\n if (serialized === null) {\n seen.delete(value);\n serializationCache.set(value, null);\n return null;\n }\n parts.push(`${JSON.stringify(key)}:${serialized}`);\n }\n seen.delete(value);\n const result = `{${parts.join(',')}}`;\n serializationCache.set(value, result);\n return result;\n }\n\n return null;\n};\n\nconst serializeDataLayerValue = (value: DataLayerValue): string | null => {\n if (Array.isArray(value)) {\n return serializeUnknown(value);\n }\n\n if (isPlainObject(value)) {\n return serializeUnknown(value);\n }\n\n return null;\n};\n\nconst isConsentCommandValue = (value: DataLayerValue): value is unknown[] =>\n Array.isArray(value) &&\n value.length >= 3 &&\n value[0] === 'consent' &&\n (value[1] === 'default' || value[1] === 'update');\n\nconst isStartEvent = (value: DataLayerValue): boolean => {\n if (!isPlainObject(value)) {\n return false;\n }\n\n return value.event === 'gtm.js';\n};\n\ninterface QueuedEntry {\n value: DataLayerValue;\n signature: string | null;\n}\n\nlet instanceCounter = 0;\n\n// Track active client instances per dataLayer name to warn about potential conflicts\nconst activeClientsPerDataLayer = new Map<string, Set<string>>();\n\n/**\n * Internal implementation of the GTM client.\n * Use {@link createGtmClient} to create instances.\n * @internal\n */\nexport class GtmClientImpl implements GtmClient {\n private readonly logger = this.options.debug ? createDebugLogger() : createLogger(this.options.logger);\n private readonly resolvedDataLayerName = this.options.dataLayerName ?? DEFAULT_DATA_LAYER_NAME;\n private readonly maxDataLayerSize = this.options.maxDataLayerSize ?? DEFAULT_MAX_DATA_LAYER_SIZE;\n private readonly containers = Array.isArray(this.options.containers)\n ? this.options.containers.map(normalizeContainer)\n : [normalizeContainer(this.options.containers)];\n private readonly queue: QueuedEntry[] = [];\n private readonly queuedConsentSignatures = new Set<string>();\n private readonly deliveredConsentSignatures = new Set<string>();\n private snapshotSignatures: Set<string> | null = null;\n private readonly scriptManager = new ScriptManager({\n instanceId: this.instanceId,\n host: this.options.host,\n dataLayerName: this.resolvedDataLayerName,\n defaultQueryParams: this.options.defaultQueryParams,\n scriptAttributes: this.options.scriptAttributes,\n logger: this.options.logger,\n retry: this.options.retry,\n scriptTimeout: this.options.scriptTimeout,\n onScriptError: this.options.onScriptError,\n onScriptTimeout: this.options.onScriptTimeout,\n verifyInitialization: this.options.verifyInitialization,\n initializationTimeout: this.options.initializationTimeout,\n onPartialLoad: this.options.onPartialLoad\n });\n private dataLayerState: ReturnType<typeof ensureDataLayer> | null = null;\n private initialized = false;\n private readonly startTimestamp = Date.now();\n\n constructor(\n private readonly options: CreateGtmClientOptions,\n private readonly instanceId: string\n ) {\n if (!this.containers.length) {\n throw new Error(\n 'At least one GTM container ID is required to initialize the client. ' +\n 'Example: createGtmClient({ containers: \"GTM-XXXXXX\" })'\n );\n }\n\n // Validate container IDs - filter out empty/whitespace-only IDs\n const invalidContainers = this.containers.filter((c) => !c.id || !c.id.trim());\n if (invalidContainers.length > 0) {\n if (invalidContainers.length === this.containers.length) {\n // All containers are invalid - throw\n throw new Error(\n 'All container IDs are empty or invalid. At least one valid GTM container ID is required. ' +\n 'Container IDs should be in the format \"GTM-XXXXXX\". ' +\n 'Example: createGtmClient({ containers: \"GTM-ABC123\" })'\n );\n } else {\n // Some containers are invalid - warn and continue with valid ones\n this.logger.warn(\n `${invalidContainers.length} container ID(s) are empty or invalid and will be skipped. ` +\n 'Valid container IDs should be in the format \"GTM-XXXXXX\".'\n );\n }\n }\n\n // Validate dataLayer name if provided\n if (this.options.dataLayerName !== undefined && !isValidDataLayerName(this.options.dataLayerName)) {\n throw new Error(\n `Invalid dataLayer name: \"${this.options.dataLayerName}\". ` +\n 'DataLayer names must be valid JavaScript identifiers (letters, numbers, underscores, dollar signs) ' +\n 'and cannot be reserved words. Example: \"dataLayer\", \"myCustomLayer\", \"gtm_data\"'\n );\n }\n }\n\n /**\n * Initializes the GTM client, setting up the dataLayer and loading GTM scripts.\n *\n * **Important**: Call `setConsentDefaults()` BEFORE `init()` if you need consent mode.\n * Events pushed before `init()` are queued and delivered after initialization.\n *\n * This method is idempotent - calling it multiple times has no effect after\n * the first call.\n *\n * @example\n * ```ts\n * const client = createGtmClient({ containers: 'GTM-XXXXXX' });\n *\n * // Set consent BEFORE init\n * client.setConsentDefaults({ analytics_storage: 'denied' });\n *\n * // Initialize GTM\n * client.init();\n *\n * // Now safe to push events\n * client.push({ event: 'page_view' });\n * ```\n */\n init(): void {\n if (this.initialized) {\n this.logger.debug('GTM client already initialized; skipping.');\n return;\n }\n\n this.logger.info('Initializing GTM client.', {\n containers: this.containers.map((container) => container.id),\n dataLayerName: this.resolvedDataLayerName\n });\n\n // Track this client instance for the dataLayer name\n if (!activeClientsPerDataLayer.has(this.resolvedDataLayerName)) {\n activeClientsPerDataLayer.set(this.resolvedDataLayerName, new Set());\n }\n const activeClients = activeClientsPerDataLayer.get(this.resolvedDataLayerName)!;\n\n // Warn if another client is already using this dataLayer\n if (activeClients.size > 0) {\n this.logger.warn(\n `Multiple GTM client instances are sharing the same dataLayer \"${this.resolvedDataLayerName}\". ` +\n 'This may cause unexpected behavior if one instance tears down while others are active. ' +\n 'Consider using different dataLayerName values for separate clients.',\n { activeInstances: activeClients.size + 1, dataLayerName: this.resolvedDataLayerName }\n );\n }\n activeClients.add(this.instanceId);\n\n // Warn if using custom dataLayerName but default 'dataLayer' already exists\n // This is a common misconfiguration - the existing dataLayer will be ignored\n const existingDataLayer = (globalThis as Record<string, unknown>)['dataLayer'];\n if (this.resolvedDataLayerName !== 'dataLayer' && typeof existingDataLayer !== 'undefined') {\n this.logger.warn(\n `Using custom dataLayerName \"${this.resolvedDataLayerName}\" but global \"dataLayer\" already exists. ` +\n 'The existing dataLayer will NOT be used. If you have existing GTM code using \"dataLayer\", ' +\n 'either remove the custom dataLayerName option or update your existing code to use the new name.',\n {\n customName: this.resolvedDataLayerName,\n existingDataLayerLength: Array.isArray(existingDataLayer) ? existingDataLayer.length : undefined\n }\n );\n }\n\n this.dataLayerState = ensureDataLayer(this.resolvedDataLayerName);\n\n // Wrap dataLayer with tracing proxy in debug mode\n if (this.options.debug) {\n const tracedDataLayer = createTracedDataLayer(this.dataLayerState.dataLayer, {\n logger: this.logger,\n dataLayerName: this.resolvedDataLayerName\n });\n // Update the global reference to use the traced version\n const globalScope = globalThis as Record<string, unknown>;\n globalScope[this.resolvedDataLayerName] = tracedDataLayer;\n // Also update our local reference\n this.dataLayerState.dataLayer = tracedDataLayer;\n this.logger.debug('DataLayer mutation tracing enabled.', {\n dataLayerName: this.resolvedDataLayerName\n });\n }\n\n this.captureSnapshotSignatures();\n this.pushStartEvent();\n this.flushQueue();\n this.scriptManager.ensure(this.containers);\n\n this.initialized = true;\n }\n\n /**\n * Pushes a value to the GTM dataLayer.\n *\n * **Queuing behavior:** If called before `init()`, values are silently queued\n * and delivered when `init()` is called. This allows you to push events early\n * (e.g., during app startup) without waiting for GTM initialization.\n *\n * **Error handling:** Push errors are caught and logged but do not throw.\n * This ensures analytics failures never crash your application.\n *\n * @param value - The value to push to the dataLayer. Can be:\n * - An event object: `{ event: 'page_view', page_title: 'Home' }`\n * - Data variables: `{ user_id: '123', user_type: 'premium' }`\n * - A callback function for timing: `() => console.log('Processed')`\n *\n * @example Pushing events\n * ```ts\n * // Page view event\n * client.push({ event: 'page_view', page_title: 'Home' });\n *\n * // Custom event with data\n * client.push({\n * event: 'button_click',\n * button_id: 'signup-cta',\n * button_text: 'Sign Up Now'\n * });\n * ```\n *\n * @example Pushing data (no event)\n * ```ts\n * // Set user properties (no event fired)\n * client.push({\n * user_id: 'usr_123',\n * user_type: 'premium',\n * account_age_days: 365\n * });\n * ```\n *\n * @example Pre-init queuing\n * ```ts\n * const client = createGtmClient({ containers: 'GTM-XXXXX' });\n *\n * // These are queued (init not called yet)\n * client.push({ event: 'early_event_1' });\n * client.push({ event: 'early_event_2' });\n *\n * // Later, when ready to initialize:\n * client.init(); // Queued events are now delivered to dataLayer\n * ```\n */\n push(value: DataLayerValue): void {\n if (value === undefined || value === null) {\n this.logger.warn('Skipped dataLayer push: value is null or undefined.', { value });\n return;\n }\n\n const immediate = this.deliverToDataLayer(value);\n\n if (immediate) {\n this.logger.debug('Pushed value to dataLayer.', { immediate: true });\n } else {\n this.logger.debug('Queued dataLayer value (pre-init).', { queueLength: this.queue.length });\n // Show queue visualization when items are queued\n this.logQueueVisualization('Current queue state');\n }\n }\n\n setConsentDefaults(state: ConsentState, options?: ConsentRegionOptions): void {\n // Warn if called after init - consent defaults should be set BEFORE GTM loads\n if (this.initialized) {\n this.logger.warn(\n 'setConsentDefaults() called after init(). ' +\n 'Consent defaults should be set BEFORE calling init() to ensure proper tag behavior. ' +\n 'The defaults will still be pushed, but GTM may have already fired tags with implied consent.',\n { state, options }\n );\n }\n\n // Validate waitForUpdate value\n if (options?.waitForUpdate !== undefined) {\n const waitValue = options.waitForUpdate;\n\n // Error on invalid values (negative, NaN, Infinity)\n if (typeof waitValue !== 'number' || !Number.isFinite(waitValue) || waitValue < 0) {\n throw new Error(\n `Invalid waitForUpdate value: ${waitValue}. ` +\n 'waitForUpdate must be a non-negative finite number representing milliseconds.'\n );\n }\n\n // Warn if waitForUpdate exceeds the maximum reasonable wait time\n if (waitValue > MAX_CONSENT_WAIT_MS) {\n this.logger.warn(\n `waitForUpdate value of ${waitValue}ms exceeds 30 minutes. ` +\n 'This may cause significant delays in tag firing. Consider using a smaller value.',\n { waitForUpdate: waitValue }\n );\n }\n }\n\n const value = createConsentCommandValue({ command: 'default', state, options });\n const immediate = this.deliverToDataLayer(value);\n\n this.logger.info('Applied consent defaults.', {\n immediate,\n state,\n options\n });\n }\n\n /**\n * Updates the consent state. Each unique consent state is pushed to the dataLayer.\n *\n * **Concurrent updates behavior (last-write-wins):**\n * - All unique consent updates are pushed to the dataLayer in the order they are called\n * - Duplicate consent updates (same state and options) are deduplicated via signature comparison\n * - GTM processes consent commands in order, so the last update for a given key wins\n * - This is intentional: it allows rapid UI changes to all be recorded while preventing duplicates\n *\n * @example\n * ```ts\n * // These concurrent updates are all pushed (all unique)\n * client.updateConsent({ ad_storage: 'granted' }); // Pushed\n * client.updateConsent({ analytics_storage: 'granted' }); // Pushed\n * client.updateConsent({ ad_storage: 'denied' }); // Pushed (different state)\n *\n * // This duplicate is deduplicated\n * client.updateConsent({ ad_storage: 'denied' }); // Skipped (duplicate)\n * ```\n */\n updateConsent(state: ConsentState, options?: ConsentRegionOptions): void {\n const value = createConsentCommandValue({ command: 'update', state, options });\n const immediate = this.deliverToDataLayer(value);\n\n this.logger.info('Updated consent state.', {\n immediate,\n state,\n options\n });\n }\n\n /**\n * Tears down the GTM client, restoring the dataLayer to its pre-init state.\n *\n * Use this for cleanup in React useEffect, Vue onUnmounted, etc.\n * After teardown, the client cannot be reused - create a new instance instead.\n *\n * **Warning**: If multiple clients share the same dataLayer name, teardown\n * will restore the dataLayer snapshot, which may affect other clients.\n *\n * @example React cleanup\n * ```tsx\n * useEffect(() => {\n * const client = createGtmClient({ containers: 'GTM-XXXXXX' });\n * client.init();\n *\n * return () => client.teardown();\n * }, []);\n * ```\n */\n teardown(): void {\n this.logger.info('Tearing down GTM client instance.', { dataLayerName: this.resolvedDataLayerName });\n\n // Remove this client from active tracking\n const activeClients = activeClientsPerDataLayer.get(this.resolvedDataLayerName);\n if (activeClients) {\n activeClients.delete(this.instanceId);\n\n // Warn if other clients are still using this dataLayer (restore may affect them)\n if (activeClients.size > 0 && this.dataLayerState) {\n this.logger.warn(\n `Tearing down GTM client while ${activeClients.size} other instance(s) are still using ` +\n `the same dataLayer \"${this.resolvedDataLayerName}\". ` +\n \"The dataLayer will be restored to this client's snapshot, which may affect other clients.\",\n { remainingInstances: activeClients.size, dataLayerName: this.resolvedDataLayerName }\n );\n }\n\n // Clean up the Map entry if no more clients\n if (activeClients.size === 0) {\n activeClientsPerDataLayer.delete(this.resolvedDataLayerName);\n }\n }\n\n this.scriptManager.teardown();\n if (this.dataLayerState) {\n this.dataLayerState.restore();\n }\n this.queue.length = 0;\n this.queuedConsentSignatures.clear();\n this.deliveredConsentSignatures.clear();\n this.snapshotSignatures = null;\n this.initialized = false;\n this.dataLayerState = null;\n }\n\n /**\n * Returns whether `init()` has been called.\n *\n * Note: This does NOT mean GTM scripts have loaded - use `isReady()` for that.\n *\n * @returns `true` if `init()` has been called, `false` otherwise\n */\n isInitialized(): boolean {\n return this.initialized;\n }\n\n /**\n * Returns whether all GTM scripts have finished loading (successfully or not).\n *\n * This is a synchronous check - use `whenReady()` if you need to wait.\n *\n * @returns `true` if all scripts have completed loading, `false` if still loading\n *\n * @example\n * ```ts\n * if (client.isReady()) {\n * // Scripts loaded, safe to check script states\n * } else {\n * // Scripts still loading\n * await client.whenReady();\n * }\n * ```\n */\n isReady(): boolean {\n return this.scriptManager.isReady();\n }\n\n /**\n * Returns a Promise that resolves when all GTM scripts have finished loading.\n *\n * The promise resolves with an array of script load states - check each state's\n * `status` to determine if scripts loaded successfully.\n *\n * @returns Promise resolving to array of script load states\n *\n * @example\n * ```ts\n * const states = await client.whenReady();\n *\n * const allSuccessful = states.every(s => s.status === 'loaded');\n * if (!allSuccessful) {\n * console.warn('Some GTM scripts failed to load');\n * }\n * ```\n */\n whenReady(): Promise<ScriptLoadState[]> {\n return this.scriptManager.whenReady();\n }\n\n /**\n * Registers a callback to be invoked when all GTM scripts have finished loading.\n *\n * If scripts are already loaded, the callback is invoked immediately.\n * Returns an unsubscribe function to cancel the callback.\n *\n * @param callback - Function to call with script load states\n * @returns Unsubscribe function\n *\n * @example\n * ```ts\n * const unsubscribe = client.onReady((states) => {\n * console.log('GTM loaded:', states);\n * });\n *\n * // Later, if needed:\n * unsubscribe();\n * ```\n */\n onReady(callback: (state: ScriptLoadState[]) => void): () => void {\n return this.scriptManager.onReady(callback);\n }\n\n /**\n * The resolved dataLayer name (defaults to 'dataLayer').\n */\n get dataLayerName(): string {\n return this.resolvedDataLayerName;\n }\n\n /**\n * Returns diagnostic information about the GTM client state.\n *\n * Useful for debugging and monitoring. Includes initialization status,\n * script states, queue size, and uptime.\n *\n * @returns Diagnostic information object\n *\n * @example\n * ```ts\n * const diagnostics = client.getDiagnostics();\n * console.log('GTM Status:', {\n * initialized: diagnostics.initialized,\n * ready: diagnostics.ready,\n * dataLayerSize: diagnostics.dataLayerSize,\n * uptime: `${diagnostics.uptimeMs}ms`\n * });\n * ```\n */\n getDiagnostics(): GtmDiagnostics {\n return {\n initialized: this.initialized,\n ready: this.scriptManager.isReady(),\n dataLayerName: this.resolvedDataLayerName,\n dataLayerSize: this.dataLayerState?.dataLayer.length ?? 0,\n queueSize: this.queue.length,\n consentCommandsDelivered: this.deliveredConsentSignatures.size,\n containers: this.containers.map((c) => c.id),\n scriptStates: this.scriptManager.getScriptStates(),\n uptimeMs: Date.now() - this.startTimestamp,\n debugMode: this.options.debug ?? false\n };\n }\n\n private flushQueue(): void {\n if (!this.dataLayerState) {\n return;\n }\n\n if (this.options.debug && this.queue.length > 0) {\n this.logQueueVisualization('Flushing queue');\n }\n\n while (this.queue.length) {\n const entry = this.queue.shift();\n if (!entry) {\n continue;\n }\n\n this.pushValueToDataLayer(entry.value, entry.signature);\n\n if (entry.signature) {\n this.queuedConsentSignatures.delete(entry.signature);\n }\n }\n\n if (this.options.debug) {\n this.logger.debug('Queue flushed successfully.', { queueLength: 0 });\n }\n }\n\n /**\n * Logs a visual representation of the event queue for debugging.\n * Shows event types, order, and basic structure.\n */\n private logQueueVisualization(action: string): void {\n if (!this.options.debug || this.queue.length === 0) {\n return;\n }\n\n const queueSummary = this.queue.map((entry, index) => {\n const value = entry.value;\n let eventType = 'unknown';\n let details = '';\n\n if (Array.isArray(value)) {\n // Consent command\n eventType = `consent:${value[1] ?? 'command'}`;\n details = JSON.stringify(value[2] ?? {}).slice(0, 50);\n } else if (typeof value === 'object' && value !== null) {\n const obj = value as Record<string, unknown>;\n if (obj.event) {\n eventType = String(obj.event);\n // Add ecommerce indicator if present\n if (obj.ecommerce) {\n details = '[ecommerce]';\n }\n } else {\n eventType = 'data';\n details = Object.keys(obj).slice(0, 3).join(', ');\n }\n } else if (typeof value === 'function') {\n eventType = 'callback';\n }\n\n return ` ${index + 1}. ${eventType}${details ? ` (${details})` : ''}`;\n });\n\n this.logger.debug(`[Queue Visualization] ${action}`, {\n queueLength: this.queue.length,\n entries: '\\n' + queueSummary.join('\\n')\n });\n }\n\n private deliverToDataLayer(value: DataLayerValue): boolean {\n if (this.initialized && this.dataLayerState) {\n this.pushValueToDataLayer(value);\n return true;\n }\n\n this.queueValue(value);\n return false;\n }\n\n private pushStartEvent(): void {\n if (!this.dataLayerState) {\n return;\n }\n\n if (this.hasExistingStartEvent()) {\n this.logger.debug('Detected existing gtm.js event; skipping duplicate start push.');\n return;\n }\n\n const startEvent = { 'gtm.start': this.startTimestamp, event: 'gtm.js' } as const;\n this.pushValueToDataLayer(startEvent);\n }\n\n private captureSnapshotSignatures(): void {\n if (!this.dataLayerState) {\n return;\n }\n\n const snapshot = this.dataLayerState.snapshot ?? [];\n this.snapshotSignatures = new Set<string>();\n\n for (const value of snapshot) {\n const signature = serializeDataLayerValue(value);\n if (signature) {\n this.snapshotSignatures.add(signature);\n if (isConsentCommandValue(value)) {\n this.deliveredConsentSignatures.add(signature);\n }\n }\n }\n }\n\n private queueValue(value: DataLayerValue): void {\n const signature = isConsentCommandValue(value) ? serializeDataLayerValue(value) : null;\n\n if (signature && this.queuedConsentSignatures.has(signature)) {\n this.logger.debug('Skipping duplicate queued dataLayer value.', { value });\n return;\n }\n\n const entry: QueuedEntry = { value, signature };\n\n if (isConsentCommandValue(value)) {\n const firstNonConsentIndex = this.queue.findIndex((queued) => !isConsentCommandValue(queued.value));\n\n if (firstNonConsentIndex === -1) {\n this.queue.push(entry);\n } else {\n this.queue.splice(firstNonConsentIndex, 0, entry);\n }\n } else {\n this.queue.push(entry);\n }\n\n if (signature) {\n this.queuedConsentSignatures.add(signature);\n }\n }\n\n private pushValueToDataLayer(value: DataLayerValue, existingSignature?: string | null): void {\n if (!this.dataLayerState) {\n return;\n }\n\n const signature = existingSignature ?? serializeDataLayerValue(value);\n const isConsentCommand = isConsentCommandValue(value);\n const seenInSnapshot = signature ? this.snapshotSignatures?.has(signature) : false;\n const alreadyDeliveredConsent =\n isConsentCommand && signature ? this.deliveredConsentSignatures.has(signature) : false;\n\n if (signature && seenInSnapshot) {\n this.logger.debug('Skipping duplicate dataLayer value detected during hydration.', { value });\n if (isConsentCommand) {\n this.deliveredConsentSignatures.add(signature);\n }\n return;\n }\n\n if (isConsentCommand && alreadyDeliveredConsent) {\n this.logger.debug('Skipping duplicate consent command.', { value });\n return;\n }\n\n // Enforce size limit before pushing to prevent unbounded growth\n this.enforceDataLayerSizeLimit();\n\n // Wrap dataLayer push in try/catch to prevent errors from crashing the app\n try {\n pushToDataLayer(this.dataLayerState, value);\n } catch (error) {\n this.logger.error('Failed to push value to dataLayer.', {\n error: error instanceof Error ? error.message : String(error),\n value\n });\n // Don't rethrow - let the app continue even if GTM tracking fails\n return;\n }\n\n if (isConsentCommand && signature) {\n this.deliveredConsentSignatures.add(signature);\n }\n }\n\n private hasExistingStartEvent(): boolean {\n if (!this.dataLayerState) {\n return false;\n }\n\n const snapshot = this.dataLayerState.snapshot ?? [];\n if (snapshot.some(isStartEvent)) {\n return true;\n }\n\n return this.dataLayerState.dataLayer.some(isStartEvent);\n }\n\n private enforceDataLayerSizeLimit(): void {\n if (this.maxDataLayerSize <= 0 || !this.dataLayerState) {\n return;\n }\n\n const dataLayer = this.dataLayerState.dataLayer;\n // Trim when at or above the limit to make room for the incoming push\n const excess = dataLayer.length - this.maxDataLayerSize;\n\n if (excess < 0) {\n return;\n }\n\n // Find indices of critical entries that should not be trimmed\n const criticalIndices = new Set<number>();\n for (let i = 0; i < dataLayer.length; i++) {\n const value = dataLayer[i];\n if (isStartEvent(value) || isConsentCommandValue(value)) {\n criticalIndices.add(i);\n }\n }\n\n // Remove at least 1 entry to make room for the incoming push\n const targetTrimCount = Math.max(1, excess + 1);\n let trimmedCount = 0;\n let index = 0;\n\n while (trimmedCount < targetTrimCount && index < dataLayer.length) {\n if (!criticalIndices.has(index)) {\n dataLayer.splice(index, 1);\n trimmedCount++;\n // Adjust critical indices for removed element\n const newCriticalIndices = new Set<number>();\n for (const criticalIndex of criticalIndices) {\n if (criticalIndex > index) {\n newCriticalIndices.add(criticalIndex - 1);\n } else {\n newCriticalIndices.add(criticalIndex);\n }\n }\n criticalIndices.clear();\n for (const ci of newCriticalIndices) {\n criticalIndices.add(ci);\n }\n } else {\n index++;\n }\n }\n\n if (trimmedCount > 0) {\n this.logger.warn('DataLayer size limit reached; trimmed oldest entries.', {\n trimmedCount,\n currentSize: dataLayer.length,\n maxSize: this.maxDataLayerSize\n });\n\n this.options.onDataLayerTrim?.(trimmedCount, dataLayer.length);\n }\n }\n}\n\n/**\n * Creates a new GTM client instance for managing Google Tag Manager interactions.\n *\n * The client handles:\n * - DataLayer initialization and management\n * - GTM script loading with retry support\n * - Consent mode commands (defaults and updates)\n * - Event queuing before initialization\n * - Hydration-aware deduplication for SSR apps\n *\n * @param options - Configuration options for the GTM client\n * @returns A GTM client instance\n *\n * @example Basic usage\n * ```ts\n * import { createGtmClient } from '@jwiedeman/gtm-kit';\n *\n * const client = createGtmClient({\n * containers: 'GTM-XXXXXX'\n * });\n *\n * client.init();\n * client.push({ event: 'page_view', page_title: 'Home' });\n * ```\n *\n * @example With consent mode\n * ```ts\n * const client = createGtmClient({\n * containers: 'GTM-XXXXXX',\n * debug: true\n * });\n *\n * // Set consent defaults BEFORE init\n * client.setConsentDefaults({\n * ad_storage: 'denied',\n * analytics_storage: 'denied'\n * });\n *\n * client.init();\n *\n * // Update consent after user interaction\n * client.updateConsent({ analytics_storage: 'granted' });\n * ```\n *\n * @example With error handling\n * ```ts\n * const client = createGtmClient({\n * containers: 'GTM-XXXXXX',\n * retry: { attempts: 3, delay: 1000 },\n * onScriptError: (state) => {\n * console.error('GTM failed to load:', state.error);\n * }\n * });\n * ```\n *\n * @see {@link CreateGtmClientOptions} for all configuration options\n */\nexport const createGtmClient = (options: CreateGtmClientOptions): GtmClient => {\n const instanceId = `gtm-kit-${++instanceCounter}`;\n return new GtmClientImpl(options, instanceId);\n};\n","import type { GtmClient } from '../types';\nimport type {\n EcommerceEvent,\n EcommerceEventName,\n EcommercePayload,\n EventForName,\n EventPayload,\n GtmEvent\n} from './types';\n\nconst isRecord = (value: unknown): value is Record<string, unknown> => typeof value === 'object' && value !== null;\n\nconst clonePayload = <TPayload extends EventPayload | undefined>(payload: TPayload): TPayload => {\n if (!payload) {\n return payload;\n }\n\n return { ...payload } as TPayload;\n};\n\nexport const pushEvent = <TName extends string, TPayload extends EventPayload = EventPayload>(\n client: Pick<GtmClient, 'push'>,\n name: TName,\n payload?: TPayload\n): EventForName<TName> => {\n if (!name) {\n throw new Error(\n 'An event name is required when pushing to the dataLayer. ' +\n 'Example: pushEvent(client, \"page_view\", { page_path: \"/home\" })'\n );\n }\n\n if (payload !== undefined && !isRecord(payload)) {\n throw new Error(\n 'Event payloads must be plain objects when pushing to the dataLayer. ' +\n `Received: ${typeof payload}. ` +\n 'Example: pushEvent(client, \"click\", { button_name: \"cta\" })'\n );\n }\n\n const event = {\n event: name,\n ...(clonePayload(payload) ?? {})\n } as GtmEvent<TName, TPayload>;\n\n client.push(event);\n return event as EventForName<TName>;\n};\n\nexport interface PushEcommerceOptions<TExtras extends EventPayload = EventPayload> {\n extras?: TExtras;\n}\n\nexport const pushEcommerce = <TName extends EcommerceEventName, TExtras extends EventPayload = EventPayload>(\n client: Pick<GtmClient, 'push'>,\n name: TName,\n ecommerce: EcommercePayload,\n options?: PushEcommerceOptions<TExtras>\n): EcommerceEvent<TName, TExtras> => {\n if (!isRecord(ecommerce)) {\n throw new Error(\n 'Ecommerce payload must be an object. ' +\n `Received: ${ecommerce === null ? 'null' : typeof ecommerce}. ` +\n 'Example: pushEcommerce(client, \"purchase\", { transaction_id: \"T123\", value: 99.99, items: [...] })'\n );\n }\n\n const extras = options?.extras ?? {};\n\n if (!isRecord(extras)) {\n throw new Error(\n 'Ecommerce extras must be an object when provided. ' +\n `Received: ${typeof extras}. ` +\n 'Example: pushEcommerce(client, \"purchase\", ecommerce, { extras: { user_id: \"123\" } })'\n );\n }\n\n const payload = { ...extras, ecommerce } as { ecommerce: EcommercePayload } & TExtras;\n return pushEvent(client, name, payload) as EcommerceEvent<TName, TExtras>;\n};\n","import type { ContainerConfigInput, ContainerDescriptor } from './types';\nimport { DEFAULT_GTM_HOST } from './constants';\nimport { normalizeContainer, buildGtmNoscriptUrl, escapeAttributeValue } from './url-utils';\n\nconst DEFAULT_IFRAME_ATTRIBUTES: Record<string, string> = {\n height: '0',\n width: '0',\n style: 'display:none;visibility:hidden',\n title: 'Google Tag Manager'\n};\n\nconst buildAttributeString = (attributes: Record<string, string | number | boolean> | undefined): string => {\n if (!attributes) {\n return '';\n }\n\n const entries = Object.entries(attributes);\n if (!entries.length) {\n return '';\n }\n\n return entries.map(([key, value]) => `${key}=\"${escapeAttributeValue(String(value))}\"`).join(' ');\n};\n\nexport interface NoscriptOptions {\n host?: string;\n defaultQueryParams?: Record<string, string | number | boolean>;\n iframeAttributes?: Record<string, string | number | boolean>;\n}\n\nconst buildNoscriptForContainer = (container: ContainerDescriptor, options: NoscriptOptions): string => {\n if (!container.id) {\n throw new Error(\n 'Container ID is required to build noscript markup. ' + 'Example: createNoscriptMarkup(\"GTM-XXXXXX\")'\n );\n }\n\n const host = options.host ?? DEFAULT_GTM_HOST;\n const params = {\n ...options.defaultQueryParams,\n ...container.queryParams\n };\n\n const src = buildGtmNoscriptUrl(host, container.id, params);\n const iframeAttributes = {\n ...DEFAULT_IFRAME_ATTRIBUTES,\n ...options.iframeAttributes\n };\n const attributeString = buildAttributeString(iframeAttributes);\n\n const attrs = attributeString ? ` ${attributeString}` : '';\n return `<noscript><iframe src=\"${escapeAttributeValue(src)}\"${attrs}></iframe></noscript>`;\n};\n\nexport const createNoscriptMarkup = (\n containers: ContainerConfigInput[] | ContainerConfigInput,\n options: NoscriptOptions = {}\n): string => {\n const normalizedContainers = Array.isArray(containers)\n ? containers.map(normalizeContainer)\n : [normalizeContainer(containers)];\n\n if (!normalizedContainers.length) {\n throw new Error(\n 'At least one container is required to build noscript markup. ' +\n 'Example: createNoscriptMarkup(\"GTM-XXXXXX\") or createNoscriptMarkup([\"GTM-ABC123\", \"GTM-XYZ789\"])'\n );\n }\n\n return normalizedContainers.map((container) => buildNoscriptForContainer(container, options)).join('');\n};\n\nexport const DEFAULT_NOSCRIPT_IFRAME_ATTRIBUTES = { ...DEFAULT_IFRAME_ATTRIBUTES };\n","/**\n * Auto-queue: Automatic dataLayer buffering for race condition elimination.\n *\n * This module provides automatic buffering of dataLayer pushes that occur before\n * GTM.js loads. Events are captured, stored in order, and replayed once GTM is ready.\n *\n * @example\n * ```ts\n * // Call as early as possible (ideally inline in <head>)\n * import { installAutoQueue } from '@jwiedeman/gtm-kit';\n *\n * installAutoQueue(); // Start buffering immediately\n *\n * // Later, events pushed before GTM loads are automatically queued\n * window.dataLayer.push({ event: 'early_event' }); // Buffered!\n *\n * // When GTM loads, all buffered events replay in order\n * ```\n *\n * @example\n * ```html\n * <!-- Inline script for earliest possible buffering -->\n * <script>\n * // Minimal inline version for <head>\n * (function(w,d,n){\n * w[n]=w[n]||[];var q=[],o=w[n].push.bind(w[n]);\n * w[n].push=function(){q.push(arguments);return o.apply(this,arguments)};\n * w.__gtmkit_buffer=q;\n * })(window,document,'dataLayer');\n * </script>\n * ```\n */\n\nimport { DEFAULT_DATA_LAYER_NAME } from './constants';\nimport type { DataLayerValue } from './types';\n\n/**\n * Escape a string for safe use in JavaScript string literals.\n * Prevents XSS when interpolating values into inline scripts.\n */\nconst escapeJsString = (value: string): string =>\n value\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/'/g, \"\\\\'\")\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')\n .replace(/</g, '\\\\x3c')\n .replace(/>/g, '\\\\x3e')\n .replace(/\\u2028/g, '\\\\u2028')\n .replace(/\\u2029/g, '\\\\u2029');\n\n/**\n * Checks if a dataLayer value is the GTM.js load event.\n * Used to detect when GTM has finished loading.\n */\nconst isGtmLoadEvent = (value: DataLayerValue): boolean =>\n value !== null &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n (value as Record<string, unknown>).event === 'gtm.js';\n\n/**\n * Cleans up the inline buffer global reference.\n * Call this in error handlers to prevent memory leaks if the full\n * GTM Kit fails to initialize after the inline script ran.\n *\n * @example\n * ```ts\n * try {\n * // Initialize GTM Kit\n * const client = createGtmClient({ containers: 'GTM-XXXXX' });\n * client.init();\n * } catch (error) {\n * // Clean up inline buffer on error\n * cleanupInlineBuffer();\n * console.error('GTM initialization failed:', error);\n * }\n * ```\n */\nexport function cleanupInlineBuffer(): void {\n if (typeof globalThis === 'undefined') {\n return;\n }\n\n const globalScope = globalThis as Record<string, unknown>;\n if (globalScope.__gtmkit_buffer !== undefined) {\n delete globalScope.__gtmkit_buffer;\n }\n}\n\n/** Options for configuring the auto-queue behavior */\nexport interface AutoQueueOptions {\n /**\n * Name of the dataLayer array. Defaults to 'dataLayer'.\n */\n dataLayerName?: string;\n\n /**\n * Interval in milliseconds to check if GTM has loaded.\n * Lower values = faster detection, higher CPU usage.\n * @default 50\n */\n pollInterval?: number;\n\n /**\n * Maximum time in milliseconds to wait for GTM before giving up.\n * Set to 0 for unlimited waiting.\n * @default 30000 (30 seconds)\n */\n timeout?: number;\n\n /**\n * Maximum number of events to buffer.\n * Prevents memory issues if GTM never loads.\n * @default 1000\n */\n maxBufferSize?: number;\n\n /**\n * Callback fired when the buffer is replayed.\n */\n onReplay?: (bufferedCount: number) => void;\n\n /**\n * Callback fired if timeout is reached before GTM loads.\n */\n onTimeout?: (bufferedCount: number) => void;\n}\n\n/** State of the auto-queue system */\nexport interface AutoQueueState {\n /** Whether the auto-queue is currently active */\n active: boolean;\n /** Number of events currently buffered */\n bufferedCount: number;\n /** Whether GTM has been detected as ready */\n gtmReady: boolean;\n /** Manually trigger replay (useful for testing) */\n replay: () => void;\n /** Uninstall the auto-queue and restore original push */\n uninstall: () => void;\n}\n\ninterface BufferedEntry {\n value: DataLayerValue;\n timestamp: number;\n}\n\n/**\n * Installs automatic dataLayer buffering that captures events before GTM loads.\n *\n * Call this as early as possible in your application lifecycle, ideally before\n * any other scripts that might push to the dataLayer.\n *\n * The auto-queue:\n * 1. Creates the dataLayer if it doesn't exist\n * 2. Intercepts all pushes to capture them in a buffer\n * 3. Detects when GTM.js loads by watching for the 'gtm.js' event\n * 4. Replays all buffered events in order once GTM is ready\n * 5. Removes itself, allowing normal dataLayer operation\n *\n * @param options - Configuration options\n * @returns State object with control methods\n *\n * @example\n * ```ts\n * const queue = installAutoQueue({\n * onReplay: (count) => console.log(`Replayed ${count} buffered events`),\n * onTimeout: (count) => console.warn(`GTM didn't load, ${count} events buffered`)\n * });\n *\n * // Check state\n * console.log(queue.bufferedCount); // Number of events waiting\n *\n * // Manual control (usually not needed)\n * queue.replay(); // Force replay now\n * queue.uninstall(); // Remove the interceptor\n * ```\n */\nexport function installAutoQueue(options: AutoQueueOptions = {}): AutoQueueState {\n const {\n dataLayerName = DEFAULT_DATA_LAYER_NAME,\n pollInterval = 50,\n timeout = 30000,\n maxBufferSize = 1000,\n onReplay,\n onTimeout\n } = options;\n\n // Skip in non-browser environments\n if (typeof globalThis === 'undefined' || typeof globalThis.document === 'undefined') {\n return createNoopState();\n }\n\n const globalScope = globalThis as Record<string, unknown>;\n\n // Create dataLayer if it doesn't exist\n if (!Array.isArray(globalScope[dataLayerName])) {\n globalScope[dataLayerName] = [];\n }\n\n const dataLayer = globalScope[dataLayerName] as DataLayerValue[];\n const buffer: BufferedEntry[] = [];\n const originalPush = dataLayer.push.bind(dataLayer);\n\n let active = true;\n let gtmReady = false;\n let pollTimer: ReturnType<typeof setInterval> | null = null;\n let timeoutTimer: ReturnType<typeof setTimeout> | null = null;\n let replayTimer: ReturnType<typeof setTimeout> | null = null;\n\n // Check if GTM.js event is present (indicating GTM has loaded)\n const isGtmLoaded = (): boolean => dataLayer.some(isGtmLoadEvent);\n\n // Replay all buffered events to the dataLayer\n const replay = (): void => {\n if (!active) return;\n\n active = false;\n gtmReady = true;\n\n // Clear all timers\n if (pollTimer) {\n clearInterval(pollTimer);\n pollTimer = null;\n }\n if (timeoutTimer) {\n clearTimeout(timeoutTimer);\n timeoutTimer = null;\n }\n if (replayTimer) {\n clearTimeout(replayTimer);\n replayTimer = null;\n }\n\n // Restore original push\n dataLayer.push = originalPush;\n\n // Replay buffered events in order\n const count = buffer.length;\n for (const entry of buffer) {\n originalPush(entry.value);\n }\n buffer.length = 0;\n\n onReplay?.(count);\n };\n\n // Uninstall without replaying\n const uninstall = (): void => {\n if (!active) return;\n\n active = false;\n\n // Clear all timers\n if (pollTimer) {\n clearInterval(pollTimer);\n pollTimer = null;\n }\n if (timeoutTimer) {\n clearTimeout(timeoutTimer);\n timeoutTimer = null;\n }\n if (replayTimer) {\n clearTimeout(replayTimer);\n replayTimer = null;\n }\n\n dataLayer.push = originalPush;\n buffer.length = 0;\n\n // Clean up any lingering global buffer reference\n cleanupInlineBuffer();\n };\n\n // Create intercepted push function\n const interceptedPush = function (this: DataLayerValue[], ...args: DataLayerValue[]): number {\n for (const value of args) {\n // Always push to actual dataLayer (GTM may already be listening)\n originalPush(value);\n\n // Buffer the value for potential replay\n if (active && buffer.length < maxBufferSize) {\n buffer.push({\n value,\n timestamp: Date.now()\n });\n }\n\n // Check if this push indicates GTM is ready\n if (active && !replayTimer && isGtmLoadEvent(value)) {\n // GTM just loaded! Trigger replay on next tick to ensure\n // this event is fully processed first\n replayTimer = setTimeout(replay, 0);\n }\n }\n\n return dataLayer.length;\n };\n\n // Install the interceptor\n dataLayer.push = interceptedPush;\n\n // Check if GTM was already loaded before we installed\n if (isGtmLoaded()) {\n // GTM already present, replay immediately\n replayTimer = setTimeout(replay, 0);\n } else {\n // Poll for GTM readiness as backup detection\n pollTimer = setInterval(() => {\n if (isGtmLoaded()) {\n replay();\n }\n }, pollInterval);\n\n // Set timeout if configured\n if (timeout > 0) {\n timeoutTimer = setTimeout(() => {\n if (active) {\n onTimeout?.(buffer.length);\n // Don't uninstall on timeout - keep buffering in case GTM loads late\n }\n }, timeout);\n }\n }\n\n // Return state object\n return {\n get active() {\n return active;\n },\n get bufferedCount() {\n return buffer.length;\n },\n get gtmReady() {\n return gtmReady;\n },\n replay,\n uninstall\n };\n}\n\n/**\n * Creates a minimal inline script for earliest possible buffering.\n *\n * This returns a script that can be embedded directly in the HTML `<head>`\n * before any other scripts. It's a minimal version of installAutoQueue()\n * that captures events until the full GTM Kit is loaded.\n *\n * @param dataLayerName - Name of the dataLayer array\n * @returns Inline script string to embed in HTML\n *\n * @example\n * ```ts\n * // In your SSR template\n * const inlineScript = createAutoQueueScript();\n * // Output: <script>{inlineScript}</script> in <head>\n * ```\n */\nexport function createAutoQueueScript(dataLayerName: string = DEFAULT_DATA_LAYER_NAME): string {\n // Minified inline script that:\n // 1. Creates dataLayer if missing\n // 2. Overrides push to capture events\n // 3. Stores buffer in __gtmkit_buffer for later retrieval\n // SECURITY: Escape the dataLayerName to prevent XSS via malicious input\n const safeName = escapeJsString(dataLayerName);\n return `(function(w,n){w[n]=w[n]||[];var q=[],o=w[n].push.bind(w[n]);w[n].push=function(){for(var i=0;i<arguments.length;i++){q.push({v:arguments[i],t:Date.now()});o(arguments[i])}return w[n].length};w.__gtmkit_buffer={q:q,o:o,n:n}})(window,'${safeName}');`;\n}\n\n/**\n * Attaches to an existing inline buffer created by createAutoQueueScript().\n *\n * If you used the inline script in your HTML head, call this when the full\n * GTM Kit loads to take over buffer management and enable replay.\n *\n * @param options - Configuration options\n * @returns State object, or null if no inline buffer exists\n *\n * @example\n * ```ts\n * // After GTM Kit bundle loads\n * const queue = attachToInlineBuffer({\n * onReplay: (count) => console.log(`Replayed ${count} events`)\n * });\n *\n * if (queue) {\n * console.log(`Taking over ${queue.bufferedCount} buffered events`);\n * }\n * ```\n */\nexport function attachToInlineBuffer(options: Omit<AutoQueueOptions, 'dataLayerName'> = {}): AutoQueueState | null {\n if (typeof globalThis === 'undefined') {\n return null;\n }\n\n const globalScope = globalThis as Record<string, unknown>;\n const inlineBuffer = globalScope.__gtmkit_buffer as\n | {\n q: { v: DataLayerValue; t: number }[];\n o: (...args: DataLayerValue[]) => number;\n n: string;\n }\n | undefined;\n\n if (!inlineBuffer) {\n return null;\n }\n\n const { n: dataLayerName } = inlineBuffer;\n\n // Clean up the global reference\n delete globalScope.__gtmkit_buffer;\n\n // Install full auto-queue with the same dataLayer name\n // The buffer from the inline script is already in the dataLayer,\n // so we just need to continue monitoring from here\n return installAutoQueue({\n ...options,\n dataLayerName\n });\n}\n\n/** Creates a no-op state for SSR environments */\nfunction createNoopState(): AutoQueueState {\n // No-op functions for SSR - these do nothing intentionally\n const noop = (): void => {\n /* no-op for SSR */\n };\n return {\n active: false,\n bufferedCount: 0,\n gtmReady: false,\n replay: noop,\n uninstall: noop\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/types.ts","../src/constants.ts","../src/consent.ts","../src/consent/presets.ts","../src/data-layer.ts","../src/logger.ts","../src/url-utils.ts","../src/script-manager.ts","../src/client.ts","../src/events/push.ts","../src/noscript.ts","../src/auto-queue.ts"],"names":["_a","_b","noop"],"mappings":"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","sourcesContent":["/**\n * Branded type for GTM Container IDs.\n * Prevents accidental mix-ups with other string types.\n *\n * @example\n * ```ts\n * const containerId = 'GTM-XXXXXX' as ContainerId;\n * ```\n */\nexport type ContainerId = string & { readonly __brand: 'ContainerId' };\n\n/**\n * Type guard to check if a string is a valid GTM container ID format.\n * Valid formats: GTM-XXXXXX (6+ alphanumeric characters)\n */\nexport const isValidContainerId = (value: string): value is ContainerId => {\n return /^GTM-[A-Z0-9]{6,}$/i.test(value);\n};\n\n/**\n * Safely cast a string to ContainerId after validation.\n * Throws if the format is invalid.\n */\nexport const toContainerId = (value: string): ContainerId => {\n if (!isValidContainerId(value)) {\n throw new Error(\n `Invalid GTM container ID format: \"${value}\". ` +\n 'Container IDs must start with \"GTM-\" followed by 6 or more alphanumeric characters. ' +\n 'Example: \"GTM-ABC123\" or \"GTM-WXYZ7890\"'\n );\n }\n return value;\n};\n\n/**\n * Branded type for DataLayer names.\n * Prevents accidental use of invalid JavaScript identifiers.\n */\nexport type DataLayerName = string & { readonly __brand: 'DataLayerName' };\n\n/**\n * JavaScript reserved words that cannot be used as variable names.\n */\nconst JS_RESERVED_WORDS = new Set([\n 'break',\n 'case',\n 'catch',\n 'class',\n 'const',\n 'continue',\n 'debugger',\n 'default',\n 'delete',\n 'do',\n 'else',\n 'enum',\n 'export',\n 'extends',\n 'false',\n 'finally',\n 'for',\n 'function',\n 'if',\n 'import',\n 'in',\n 'instanceof',\n 'let',\n 'new',\n 'null',\n 'return',\n 'static',\n 'super',\n 'switch',\n 'this',\n 'throw',\n 'true',\n 'try',\n 'typeof',\n 'var',\n 'void',\n 'while',\n 'with',\n 'yield',\n 'await',\n 'implements',\n 'interface',\n 'package',\n 'private',\n 'protected',\n 'public',\n 'arguments',\n 'eval'\n]);\n\n/**\n * Type guard to check if a string is a valid dataLayer name.\n * Valid names must be valid JavaScript identifiers and not reserved words.\n *\n * Security: Prevents injection attacks via malicious dataLayer names like:\n * - \"dataLayer'];alert('XSS');//\"\n * - \"dataLayer<script>\"\n *\n * @example\n * ```ts\n * isValidDataLayerName('dataLayer'); // true\n * isValidDataLayerName('myCustomLayer'); // true\n * isValidDataLayerName('data_layer_1'); // true\n * isValidDataLayerName(\"dataLayer'];alert('XSS')\"); // false\n * isValidDataLayerName('class'); // false (reserved word)\n * ```\n */\nexport const isValidDataLayerName = (value: string): value is DataLayerName => {\n // Must be a non-empty string\n if (typeof value !== 'string' || value.length === 0) {\n return false;\n }\n\n // Must be a valid JavaScript identifier\n // Starts with letter, underscore, or dollar sign\n // Contains only letters, numbers, underscores, or dollar signs\n if (!/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(value)) {\n return false;\n }\n\n // Must not be a reserved word\n if (JS_RESERVED_WORDS.has(value)) {\n return false;\n }\n\n return true;\n};\n\n/**\n * Safely cast a string to DataLayerName after validation.\n * Throws if the name is not a valid JavaScript identifier.\n *\n * @example\n * ```ts\n * const name = toDataLayerName('dataLayer'); // OK\n * const custom = toDataLayerName('myCustomLayer'); // OK\n * toDataLayerName(\"dataLayer'];alert('XSS')\"); // throws Error\n * ```\n */\nexport const toDataLayerName = (value: string): DataLayerName => {\n if (!isValidDataLayerName(value)) {\n throw new Error(\n `Invalid dataLayer name: \"${value}\". ` +\n 'DataLayer names must be valid JavaScript identifiers (letters, numbers, underscores, dollar signs) ' +\n 'and cannot be reserved words. Example: \"dataLayer\", \"myCustomLayer\", \"gtm_data\"'\n );\n }\n return value;\n};\n\n/**\n * Values that can be pushed to the GTM dataLayer.\n *\n * The dataLayer accepts three types of values:\n *\n * ## 1. Objects (most common)\n * Plain objects containing event data and variables. Property values can be:\n * - **Primitives**: `string`, `number`, `boolean`, `null`, `undefined`\n * - **Arrays**: For ecommerce items, user lists, etc.\n * - **Nested objects**: For complex structured data\n *\n * ```ts\n * // Event with properties\n * push({ event: 'page_view', page_title: 'Home' });\n *\n * // Setting variables\n * push({ user_id: '12345', user_type: 'premium' });\n *\n * // Ecommerce data\n * push({\n * event: 'purchase',\n * ecommerce: {\n * transaction_id: 'T-123',\n * value: 99.99,\n * items: [{ item_id: 'SKU-1', price: 99.99 }]\n * }\n * });\n * ```\n *\n * ## 2. Functions (GTM callbacks)\n * Functions pushed to dataLayer are executed by GTM with a callback parameter.\n * Useful for reading GTM state or triggering container-specific behavior.\n *\n * ```ts\n * // Read container ID\n * push(function(this: { id: string }) {\n * console.log('Container:', this.id);\n * });\n *\n * // Async operation with GTM\n * push(function() {\n * return new Promise(resolve => {\n * setTimeout(() => resolve(), 1000);\n * });\n * });\n * ```\n *\n * ## 3. Arrays (consent commands, legacy format)\n * Array format primarily used for Google Consent Mode commands.\n * The first element is the command, followed by parameters.\n *\n * ```ts\n * // Consent default command\n * push(['consent', 'default', { analytics_storage: 'denied' }]);\n *\n * // Consent update command\n * push(['consent', 'update', { analytics_storage: 'granted' }]);\n * ```\n *\n * @see https://developers.google.com/tag-manager/devguide#datalayer\n * @see https://developers.google.com/tag-platform/gtagjs/reference#consent\n */\nexport type DataLayerValue = Record<string, unknown> | ((...args: unknown[]) => unknown) | unknown[];\n\n/**\n * Type-safe globalThis extension for accessing dataLayer.\n * Use this interface to extend globalThis in your application.\n *\n * @example\n * ```ts\n * declare global {\n * interface Window extends GtmGlobalExtension {}\n * }\n *\n * // Then access safely\n * const dataLayer = window.dataLayer;\n * ```\n */\nexport interface GtmGlobalExtension {\n dataLayer?: DataLayerValue[];\n google_tag_manager?: Record<string, unknown>;\n}\n\n/**\n * Type-safe access to the dataLayer from globalThis/window.\n * Returns undefined if running in a non-browser environment or if dataLayer doesn't exist.\n */\nexport const getGlobalDataLayer = (name = 'dataLayer'): DataLayerValue[] | undefined => {\n if (typeof globalThis === 'undefined') {\n return undefined;\n }\n const global = globalThis as typeof globalThis & Record<string, unknown>;\n const layer = global[name];\n return Array.isArray(layer) ? (layer as DataLayerValue[]) : undefined;\n};\n\n/**\n * Type-safe access to google_tag_manager from globalThis/window.\n * Returns undefined if running in a non-browser environment or if GTM isn't loaded.\n */\nexport const getGoogleTagManager = (): Record<string, unknown> | undefined => {\n if (typeof globalThis === 'undefined') {\n return undefined;\n }\n const global = globalThis as typeof globalThis & GtmGlobalExtension;\n return global.google_tag_manager;\n};\n\nexport interface DataLayerState {\n name: string;\n dataLayer: DataLayerValue[];\n created: boolean;\n restore(): void;\n}\n\nexport interface Logger {\n debug(message: string, details?: Record<string, unknown>): void;\n info(message: string, details?: Record<string, unknown>): void;\n warn(message: string, details?: Record<string, unknown>): void;\n error(message: string, details?: Record<string, unknown>): void;\n}\n\nexport type PartialLogger = Partial<Logger>;\n\nexport type ScriptAttributeValue = string | boolean | null | undefined;\n\nexport interface ScriptAttributes {\n async?: boolean;\n defer?: boolean;\n nonce?: string;\n [attribute: string]: ScriptAttributeValue;\n}\n\n/**\n * Script load status:\n * - 'loaded': Script loaded and GTM initialized successfully\n * - 'failed': Script failed to load (network error, blocked, etc.)\n * - 'skipped': Script was skipped (already present, or no document available)\n * - 'partial': Script loaded but GTM failed to initialize (malformed container, etc.)\n */\nexport type ScriptLoadStatus = 'loaded' | 'failed' | 'skipped' | 'partial';\n\nexport interface ScriptLoadState {\n containerId: string;\n src?: string;\n status: ScriptLoadStatus;\n fromCache?: boolean;\n error?: string;\n /**\n * Time taken to load the script in milliseconds.\n * Only present for scripts that were actually loaded (not cached/skipped).\n */\n loadTimeMs?: number;\n}\n\nexport interface ContainerDescriptor {\n id: string;\n queryParams?: Record<string, string | number | boolean>;\n}\n\nexport type ContainerConfigInput = string | ContainerDescriptor;\n\n/**\n * Options for script retry behavior on load failures.\n */\nexport interface ScriptRetryOptions {\n /**\n * Number of retry attempts after initial failure.\n * Set to 0 to disable retries (default behavior).\n * @default 0\n */\n attempts?: number;\n\n /**\n * Initial delay in milliseconds before first retry.\n * Subsequent retries use exponential backoff (delay * 2^attempt).\n * @default 1000\n */\n delay?: number;\n\n /**\n * Maximum delay between retries in milliseconds.\n * Prevents exponential backoff from growing too large.\n * @default 30000\n */\n maxDelay?: number;\n}\n\nexport interface CreateGtmClientOptions {\n containers: ContainerConfigInput[] | ContainerConfigInput;\n dataLayerName?: string;\n host?: string;\n defaultQueryParams?: Record<string, string | number | boolean>;\n scriptAttributes?: ScriptAttributes;\n logger?: PartialLogger;\n\n /**\n * Enable debug mode with verbose console logging.\n * When true, all GTM operations are logged to the console with timestamps\n * and colored prefixes for easy debugging.\n *\n * Note: This overrides any custom logger if set to true.\n * For production, either set to false or use a custom logger.\n * @default false\n */\n debug?: boolean;\n\n /**\n * Script retry configuration for failed loads.\n * Enables automatic retry with exponential backoff.\n */\n retry?: ScriptRetryOptions;\n\n /**\n * Timeout in milliseconds for script load.\n * If a script doesn't load within this time, it's considered failed.\n * Set to 0 to disable timeout (not recommended).\n * @default 30000\n */\n scriptTimeout?: number;\n\n /**\n * Callback invoked when a script fails to load (after all retries exhausted).\n * Use this to handle errors gracefully in your application.\n */\n onScriptError?: (state: ScriptLoadState) => void;\n\n /**\n * Callback invoked when a script load times out.\n * Called before retry attempts if retries are configured.\n */\n onScriptTimeout?: (containerId: string) => void;\n\n /**\n * Maximum number of entries allowed in the dataLayer array.\n * When the limit is reached, oldest non-critical entries are removed to make room.\n * Critical entries (gtm.js start event, consent commands) are preserved.\n * Set to 0 to disable the limit (not recommended for long-running SPAs).\n * @default 500\n */\n maxDataLayerSize?: number;\n\n /**\n * Callback invoked when dataLayer entries are trimmed due to size limit.\n * Use this to monitor memory management or log analytics.\n */\n onDataLayerTrim?: (trimmedCount: number, currentSize: number) => void;\n\n /**\n * Whether to verify GTM initialization after script loads.\n * When enabled, checks for the gtm.js event in the dataLayer after script load.\n * If verification fails, the script status is set to 'partial'.\n * @default false\n */\n verifyInitialization?: boolean;\n\n /**\n * Timeout in milliseconds to wait for GTM initialization verification.\n * Only used when verifyInitialization is true.\n * @default 5000\n */\n initializationTimeout?: number;\n\n /**\n * Callback invoked when a script loads but GTM fails to initialize.\n * This indicates a partial load failure (script loaded but GTM didn't work).\n */\n onPartialLoad?: (state: ScriptLoadState) => void;\n}\n\n/**\n * Diagnostic information about the GTM client state.\n * Useful for debugging integration issues.\n */\nexport interface GtmDiagnostics {\n /** Whether the client has been initialized */\n initialized: boolean;\n /** Whether all scripts have finished loading */\n ready: boolean;\n /** Name of the dataLayer being used */\n dataLayerName: string;\n /** Current size of the dataLayer array */\n dataLayerSize: number;\n /** Number of items in the pre-init queue */\n queueSize: number;\n /** Number of consent commands delivered */\n consentCommandsDelivered: number;\n /** Container IDs configured */\n containers: string[];\n /** Script load states for each container */\n scriptStates: ScriptLoadState[];\n /** Time since client was created (ms) */\n uptimeMs: number;\n /** Whether debug mode is enabled */\n debugMode: boolean;\n}\n\nexport interface GtmClient {\n readonly dataLayerName: string;\n init(): void;\n push(value: DataLayerValue): void;\n setConsentDefaults(state: import('./consent').ConsentState, options?: import('./consent').ConsentRegionOptions): void;\n updateConsent(state: import('./consent').ConsentState, options?: import('./consent').ConsentRegionOptions): void;\n teardown(): void;\n isInitialized(): boolean;\n /**\n * Synchronously check if all GTM scripts have finished loading.\n * Returns true if all scripts have loaded (successfully or failed), false if still loading.\n */\n isReady(): boolean;\n whenReady(): Promise<ScriptLoadState[]>;\n onReady(callback: (state: ScriptLoadState[]) => void): () => void;\n /**\n * Get diagnostic information about the GTM client state.\n * Useful for debugging integration issues.\n */\n getDiagnostics(): GtmDiagnostics;\n}\n","export const DEFAULT_GTM_HOST = 'https://www.googletagmanager.com';\nexport const DEFAULT_DATA_LAYER_NAME = 'dataLayer';\nexport const DEFAULT_MAX_DATA_LAYER_SIZE = 500;\n\n/**\n * Maximum reasonable wait time for consent waitForUpdate (30 minutes).\n * Values exceeding this will trigger a warning.\n */\nexport const MAX_CONSENT_WAIT_MS = 30 * 60 * 1000; // 30 minutes\n\n/**\n * Default timeout for script loading (30 seconds).\n */\nexport const DEFAULT_SCRIPT_TIMEOUT_MS = 30000;\n\n/**\n * Default timeout for GTM initialization check (5 seconds).\n */\nexport const DEFAULT_INIT_TIMEOUT_MS = 5000;\n\n/**\n * Default delay between retry attempts (1 second).\n */\nexport const DEFAULT_RETRY_DELAY_MS = 1000;\n\n/**\n * Maximum delay between retry attempts (30 seconds).\n */\nexport const MAX_RETRY_DELAY_MS = 30000;\n","import type { DataLayerValue } from './types';\n\nconst CONSENT_COMMAND = 'consent' as const;\nconst CONSENT_DEFAULT = 'default' as const;\nconst CONSENT_UPDATE = 'update' as const;\n\n/**\n * The four consent categories tracked by Google Consent Mode v2.\n */\nconst CONSENT_KEYS = ['ad_storage', 'analytics_storage', 'ad_user_data', 'ad_personalization'] as const;\n\n/**\n * A consent category key: 'ad_storage' | 'analytics_storage' | 'ad_user_data' | 'ad_personalization'\n */\nexport type ConsentKey = (typeof CONSENT_KEYS)[number];\n\n/**\n * A consent decision: 'granted' or 'denied'\n */\nexport type ConsentDecision = 'granted' | 'denied';\n\n/**\n * Consent state object for one or more categories.\n *\n * This is a **partial** record - you only need to specify the categories you want to set.\n * Unspecified categories retain their previous state when using `updateConsent()`.\n *\n * @example\n * ```ts\n * // All four categories\n * const fullState: ConsentState = {\n * ad_storage: 'granted',\n * analytics_storage: 'granted',\n * ad_user_data: 'granted',\n * ad_personalization: 'granted'\n * };\n *\n * // Single category (partial update)\n * const partialState: ConsentState = {\n * analytics_storage: 'granted'\n * };\n *\n * // Multiple specific categories\n * const mixedState: ConsentState = {\n * analytics_storage: 'granted',\n * ad_storage: 'denied'\n * };\n * ```\n */\nexport type ConsentState = Partial<Record<ConsentKey, ConsentDecision>>;\n\nexport interface ConsentRegionOptions {\n /**\n * ISO 3166-2 region codes (e.g., `US-CA`, `EEA`) that the consent command applies to.\n */\n region?: readonly string[];\n /**\n * Milliseconds to wait for an explicit update before firing tags when using the default command.\n */\n waitForUpdate?: number;\n}\n\nexport type ConsentCommand = typeof CONSENT_DEFAULT | typeof CONSENT_UPDATE;\n\nexport interface ConsentCommandInput {\n command: ConsentCommand;\n state: ConsentState;\n options?: ConsentRegionOptions;\n}\n\nexport type ConsentCommandValue =\n | [typeof CONSENT_COMMAND, ConsentCommand, ConsentState]\n | [typeof CONSENT_COMMAND, ConsentCommand, ConsentState, Record<string, unknown>];\n\nconst isConsentKey = (value: string): value is ConsentKey => (CONSENT_KEYS as readonly string[]).includes(value);\n\nconst isConsentDecision = (value: unknown): value is ConsentDecision => value === 'granted' || value === 'denied';\n\nconst assertValidRegions = (regions: readonly string[]) => {\n if (!Array.isArray(regions)) {\n throw new Error(\n 'Consent region list must be an array of ISO 3166-2 region codes. ' +\n `Received: ${typeof regions}. ` +\n 'Example: { region: [\"US-CA\", \"EEA\"] }'\n );\n }\n\n for (const region of regions) {\n if (typeof region !== 'string' || region.trim().length === 0) {\n throw new Error(\n 'Consent region codes must be non-empty ISO 3166-2 strings. ' +\n `Received: ${region === null ? 'null' : typeof region}. ` +\n 'Example: \"US-CA\", \"EEA\", \"US\"'\n );\n }\n }\n};\n\nconst assertValidWaitForUpdate = (waitForUpdate: number) => {\n if (!Number.isFinite(waitForUpdate) || waitForUpdate < 0) {\n throw new Error(\n `Invalid waitForUpdate value: ${waitForUpdate}. ` +\n 'waitForUpdate must be a non-negative finite number representing milliseconds to wait for consent update. ' +\n 'Example: { waitForUpdate: 500 }'\n );\n }\n};\n\nexport const normalizeConsentState = (state: ConsentState): ConsentState => {\n const normalizedEntries = Object.entries(state ?? {}).map(([key, value]) => {\n if (!isConsentKey(key)) {\n throw new Error(\n `Invalid consent key: \"${key}\". ` +\n 'Valid keys are: ad_storage, analytics_storage, ad_user_data, ad_personalization. ' +\n 'Example: { ad_storage: \"granted\", analytics_storage: \"denied\" }'\n );\n }\n\n if (!isConsentDecision(value)) {\n throw new Error(\n `Invalid consent value for key \"${key}\": ${value === null ? 'null' : typeof value === 'string' ? `\"${value}\"` : value}. ` +\n 'Consent values must be \"granted\" or \"denied\". ' +\n 'Example: { ad_storage: \"granted\" }'\n );\n }\n\n return [key, value] as const;\n });\n\n if (!normalizedEntries.length) {\n throw new Error(\n 'At least one consent key/value pair is required. ' +\n 'Example: { ad_storage: \"granted\", analytics_storage: \"granted\" }'\n );\n }\n\n const normalizedState = {} as ConsentState;\n for (const [key, value] of normalizedEntries) {\n normalizedState[key as ConsentKey] = value;\n }\n\n return Object.freeze(normalizedState);\n};\n\nconst normalizeOptions = (options?: ConsentRegionOptions): Record<string, unknown> | undefined => {\n if (!options) {\n return undefined;\n }\n\n const payload: Record<string, unknown> = {};\n\n if (options.region) {\n assertValidRegions(options.region);\n if (options.region.length) {\n payload.region = [...options.region];\n }\n }\n\n if (typeof options.waitForUpdate === 'number') {\n assertValidWaitForUpdate(options.waitForUpdate);\n payload.wait_for_update = options.waitForUpdate;\n }\n\n return Object.keys(payload).length ? payload : undefined;\n};\n\nexport const buildConsentCommand = ({ command, state, options }: ConsentCommandInput): ConsentCommandValue => {\n if (command !== CONSENT_DEFAULT && command !== CONSENT_UPDATE) {\n throw new Error(\n `Unsupported consent command: \"${command}\". ` +\n 'Valid commands are \"default\" (for initial consent state) or \"update\" (for user consent changes). ' +\n 'Example: buildConsentCommand({ command: \"default\", state: { analytics_storage: \"denied\" } })'\n );\n }\n\n const normalizedState = normalizeConsentState(state);\n const normalizedOptions = normalizeOptions(options);\n\n if (normalizedOptions) {\n return [CONSENT_COMMAND, command, normalizedState, normalizedOptions];\n }\n\n return [CONSENT_COMMAND, command, normalizedState];\n};\n\nexport const createConsentCommandValue = (input: ConsentCommandInput): DataLayerValue => {\n // Spread the tuple to convert it to a plain array for DataLayerValue compatibility\n return [...buildConsentCommand(input)];\n};\n\nexport const createConsentDefaultsCommand = (state: ConsentState, options?: ConsentRegionOptions): DataLayerValue =>\n createConsentCommandValue({ command: CONSENT_DEFAULT, state, options });\n\nexport const createConsentUpdateCommand = (state: ConsentState, options?: ConsentRegionOptions): DataLayerValue =>\n createConsentCommandValue({ command: CONSENT_UPDATE, state, options });\n\nexport const consent = {\n buildConsentCommand,\n createConsentDefaultsCommand,\n createConsentUpdateCommand,\n normalizeConsentState\n};\n","import type { ConsentState } from '../consent';\n\n/**\n * Pre-configured consent state presets for common scenarios.\n *\n * These presets cover the most common consent patterns:\n * - `eeaDefault`: All denied (GDPR compliant default)\n * - `allGranted`: All granted (user accepts everything)\n * - `analyticsOnly`: Mixed state (analytics only, no ads)\n *\n * For custom combinations, pass a partial `ConsentState` object to `updateConsent()`.\n * You only need to specify the categories you want to update.\n *\n * @example\n * ```ts\n * // Use a preset\n * client.updateConsent(consentPresets.allGranted);\n *\n * // Or create a custom state\n * client.updateConsent({\n * analytics_storage: 'granted',\n * ad_storage: 'denied'\n * });\n *\n * // Partial updates (only update specific categories)\n * client.updateConsent({ analytics_storage: 'granted' });\n * ```\n */\nexport const consentPresets = {\n /**\n * All categories denied - GDPR/EEA compliant default.\n *\n * Use as the initial state for regions requiring explicit opt-in consent.\n * Tags will be blocked until the user grants specific permissions.\n *\n * | Category | State |\n * |----------|-------|\n * | ad_storage | denied |\n * | analytics_storage | denied |\n * | ad_user_data | denied |\n * | ad_personalization | denied |\n */\n eeaDefault: Object.freeze({\n ad_storage: 'denied',\n analytics_storage: 'denied',\n ad_user_data: 'denied',\n ad_personalization: 'denied'\n } satisfies ConsentState),\n\n /**\n * All categories granted - user accepts all tracking.\n *\n * Use when the user clicks \"Accept All\" or in regions where consent is implied.\n *\n * | Category | State |\n * |----------|-------|\n * | ad_storage | granted |\n * | analytics_storage | granted |\n * | ad_user_data | granted |\n * | ad_personalization | granted |\n */\n allGranted: Object.freeze({\n ad_storage: 'granted',\n analytics_storage: 'granted',\n ad_user_data: 'granted',\n ad_personalization: 'granted'\n } satisfies ConsentState),\n\n /**\n * Analytics allowed, advertising denied - mixed consent state.\n *\n * Use when the user accepts analytics/statistics but rejects advertising cookies.\n * This is a common \"essential + analytics\" consent pattern.\n *\n * | Category | State |\n * |----------|-------|\n * | ad_storage | denied |\n * | analytics_storage | granted |\n * | ad_user_data | denied |\n * | ad_personalization | denied |\n */\n analyticsOnly: Object.freeze({\n ad_storage: 'denied',\n analytics_storage: 'granted',\n ad_user_data: 'denied',\n ad_personalization: 'denied'\n } satisfies ConsentState)\n} as const;\n\nexport type ConsentPresetName = keyof typeof consentPresets;\n\nexport const getConsentPreset = (name: ConsentPresetName): ConsentState => ({\n ...consentPresets[name]\n});\n\n/**\n * Convenience export for the EEA default consent state.\n * All categories denied - GDPR/EEA compliant default.\n */\nexport const eeaDefault = consentPresets.eeaDefault;\n\n/**\n * Convenience export for the all-granted consent state.\n * All categories granted - user accepts all tracking.\n */\nexport const allGranted = consentPresets.allGranted;\n\n/**\n * Convenience export for the analytics-only consent state.\n * Analytics allowed, advertising denied.\n */\nexport const analyticsOnly = consentPresets.analyticsOnly;\n","import type { DataLayerState, DataLayerValue, Logger } from './types';\n\ninterface EnsureDataLayerResult extends DataLayerState {\n snapshot: DataLayerValue[] | undefined;\n}\n\nexport interface MutationTraceOptions {\n logger: Logger;\n dataLayerName: string;\n}\n\nconst isArray = (value: unknown): value is DataLayerValue[] => Array.isArray(value);\n\nexport const ensureDataLayer = (name: string): EnsureDataLayerResult => {\n const globalScope = globalThis as Record<string, unknown>;\n const existing = globalScope[name];\n const snapshot = isArray(existing) ? [...existing] : undefined;\n\n if (!isArray(existing)) {\n globalScope[name] = [] as DataLayerValue[];\n }\n\n return {\n name,\n dataLayer: globalScope[name] as DataLayerValue[],\n created: !isArray(existing),\n restore() {\n if (!isArray(existing)) {\n delete globalScope[name];\n return;\n }\n\n const clone = snapshot ? [...snapshot] : [];\n globalScope[name] = clone;\n },\n snapshot\n };\n};\n\nexport const pushToDataLayer = (state: DataLayerState, value: DataLayerValue) => {\n state.dataLayer.push(value);\n};\n\n/**\n * Creates a Proxy wrapper around a dataLayer array that logs all mutations.\n * Used in debug mode to help developers trace dataLayer changes.\n */\nexport const createTracedDataLayer = (dataLayer: DataLayerValue[], options: MutationTraceOptions): DataLayerValue[] => {\n const { logger, dataLayerName } = options;\n\n const formatValue = (value: unknown): string => {\n if (value === null) return 'null';\n if (value === undefined) return 'undefined';\n if (typeof value === 'function') return '[Function]';\n if (typeof value === 'object') {\n try {\n const str = JSON.stringify(value);\n return str.length > 100 ? str.slice(0, 100) + '...' : str;\n } catch {\n return '[Object with circular reference]';\n }\n }\n return String(value);\n };\n\n return new Proxy(dataLayer, {\n set(target, property, value) {\n const index = Number(property);\n const isIndex = !Number.isNaN(index) && Number.isInteger(index) && index >= 0;\n\n if (isIndex) {\n const isReplacement = index < target.length;\n if (isReplacement) {\n logger.debug(`[${dataLayerName}] Replaced value at index ${index}`, {\n previousValue: formatValue(target[index]),\n newValue: formatValue(value)\n });\n } else {\n logger.debug(`[${dataLayerName}] Added value at index ${index}`, {\n value: formatValue(value)\n });\n }\n }\n\n Reflect.set(target, property, value);\n return true;\n },\n\n deleteProperty(target, property) {\n const index = Number(property);\n const isIndex = !Number.isNaN(index) && Number.isInteger(index) && index >= 0;\n\n if (isIndex && index < target.length) {\n logger.debug(`[${dataLayerName}] Deleted value at index ${index}`, {\n deletedValue: formatValue(target[index])\n });\n }\n\n Reflect.deleteProperty(target, property);\n return true;\n },\n\n get(target, property) {\n const value = target[property as keyof typeof target];\n\n // Wrap mutating array methods to log their operations\n if (typeof value === 'function') {\n if (property === 'push') {\n return function (...args: DataLayerValue[]) {\n logger.debug(`[${dataLayerName}] push() called with ${args.length} item(s)`, {\n items: args.map((arg) => formatValue(arg)),\n previousLength: target.length\n });\n return Array.prototype.push.apply(target, args);\n };\n }\n\n if (property === 'pop') {\n return function () {\n const poppedValue = target[target.length - 1];\n logger.debug(`[${dataLayerName}] pop() called`, {\n poppedValue: formatValue(poppedValue),\n previousLength: target.length\n });\n return Array.prototype.pop.call(target);\n };\n }\n\n if (property === 'shift') {\n return function () {\n const shiftedValue = target[0];\n logger.debug(`[${dataLayerName}] shift() called`, {\n shiftedValue: formatValue(shiftedValue),\n previousLength: target.length\n });\n return Array.prototype.shift.call(target);\n };\n }\n\n if (property === 'unshift') {\n return function (...args: DataLayerValue[]) {\n logger.debug(`[${dataLayerName}] unshift() called with ${args.length} item(s)`, {\n items: args.map((arg) => formatValue(arg)),\n previousLength: target.length\n });\n return Array.prototype.unshift.apply(target, args);\n };\n }\n\n if (property === 'splice') {\n return function (start: number, deleteCount?: number, ...items: DataLayerValue[]) {\n const deletedItems = target.slice(start, start + (deleteCount ?? target.length - start));\n logger.debug(`[${dataLayerName}] splice() called`, {\n start,\n deleteCount: deleteCount ?? 'rest',\n deletedItems: deletedItems.map((item) => formatValue(item)),\n insertedItems: items.map((item) => formatValue(item)),\n previousLength: target.length\n });\n return Array.prototype.splice.apply(target, [start, deleteCount ?? target.length - start, ...items]);\n };\n }\n }\n\n return value;\n }\n });\n};\n","import type { Logger, PartialLogger } from './types';\n\ntype LogLevel = keyof Logger;\n\nconst levels: LogLevel[] = ['debug', 'info', 'warn', 'error'];\n\nconst noop = () => {\n /* intentionally empty */\n};\n\n/**\n * Color codes for different log levels in console output.\n * Uses ANSI-like browser console styling.\n */\nconst levelColors: Record<LogLevel, string> = {\n debug: 'color: #6b7280', // gray\n info: 'color: #3b82f6', // blue\n warn: 'color: #f59e0b', // amber\n error: 'color: #ef4444' // red\n};\n\nconst levelPrefixes: Record<LogLevel, string> = {\n debug: '[GTM-Kit DEBUG]',\n info: '[GTM-Kit INFO]',\n warn: '[GTM-Kit WARN]',\n error: '[GTM-Kit ERROR]'\n};\n\n/**\n * Creates a debug logger that outputs formatted messages to the console.\n * This is the built-in logger used when `debug: true` is set.\n */\nexport const createDebugLogger = (): Logger => {\n const createLogFn =\n (level: LogLevel) =>\n (message: string, details?: Record<string, unknown>): void => {\n const timestamp = new Date().toISOString().split('T')[1].slice(0, -1);\n const prefix = levelPrefixes[level];\n const style = levelColors[level];\n\n /* eslint-disable no-console -- Logger's purpose is to output to console */\n const consoleFn =\n level === 'error'\n ? console.error\n : level === 'warn'\n ? console.warn\n : level === 'info'\n ? console.info\n : console.log;\n /* eslint-enable no-console */\n\n if (details && Object.keys(details).length > 0) {\n consoleFn(`%c${timestamp} ${prefix}%c ${message}`, style, 'color: inherit', details);\n } else {\n consoleFn(`%c${timestamp} ${prefix}%c ${message}`, style, 'color: inherit');\n }\n };\n\n return {\n debug: createLogFn('debug'),\n info: createLogFn('info'),\n warn: createLogFn('warn'),\n error: createLogFn('error')\n };\n};\n\nexport const createLogger = (logger?: PartialLogger): Logger => {\n const safeLogger: Partial<Record<LogLevel, (message: string, details?: Record<string, unknown>) => void>> = {};\n\n for (const level of levels) {\n const provided = logger?.[level];\n if (typeof provided === 'function') {\n safeLogger[level] = provided.bind(logger);\n continue;\n }\n safeLogger[level] = noop;\n }\n\n return safeLogger as Logger;\n};\n\nexport type LoggerFacade = ReturnType<typeof createLogger>;\n","import { DEFAULT_DATA_LAYER_NAME, DEFAULT_GTM_HOST } from './constants';\nimport type { ContainerConfigInput, ContainerDescriptor } from './types';\n\n/**\n * Type guard to check if a value is a string.\n * @internal Primarily for internal use. API may change.\n */\nexport const isString = (value: unknown): value is string => typeof value === 'string';\n\n/**\n * Normalize a container input to a ContainerDescriptor.\n * @internal Primarily for internal use. API may change.\n */\nexport const normalizeContainer = (input: ContainerConfigInput): ContainerDescriptor => {\n if (isString(input)) {\n return { id: input };\n }\n return input;\n};\n\n/**\n * Normalize container inputs to an array of ContainerDescriptors.\n * @internal Primarily for internal use. API may change.\n */\nexport const normalizeContainers = (\n containers: ContainerConfigInput | ContainerConfigInput[]\n): ContainerDescriptor[] => {\n if (Array.isArray(containers)) {\n return containers.map(normalizeContainer);\n }\n return [normalizeContainer(containers)];\n};\n\n/**\n * Convert query params to a Record<string, string>.\n * @internal Primarily for internal use. API may change.\n */\nexport const toRecord = (params?: Record<string, string | number | boolean>): Record<string, string> => {\n if (!params) {\n return {};\n }\n return Object.entries(params).reduce<Record<string, string>>((acc, [key, value]) => {\n acc[key] = String(value);\n return acc;\n }, {});\n};\n\n/**\n * Normalize a host URL by removing trailing slashes.\n * @internal Primarily for internal use. API may change.\n */\nexport const normalizeHost = (host: string): string => (host.endsWith('/') ? host.slice(0, -1) : host);\n\ntype UrlKind = 'gtm' | 'ns';\n\nconst buildUrl = (\n kind: UrlKind,\n host: string,\n containerId: string,\n queryParams?: Record<string, string | number | boolean>,\n dataLayerName: string = DEFAULT_DATA_LAYER_NAME\n): string => {\n const normalizedHost = normalizeHost(host);\n const searchParams = new URLSearchParams({ id: containerId });\n\n const params = toRecord(queryParams);\n\n // Add dataLayer name parameter if using custom name\n if (dataLayerName !== DEFAULT_DATA_LAYER_NAME && params.l === undefined) {\n params.l = dataLayerName;\n }\n\n for (const [key, value] of Object.entries(params)) {\n if (key === 'id') {\n continue;\n }\n searchParams.set(key, value);\n }\n\n const suffix = kind === 'gtm' ? 'gtm.js' : 'ns.html';\n return `${normalizedHost}/${suffix}?${searchParams.toString()}`;\n};\n\n/**\n * Build a GTM script URL.\n */\nexport const buildGtmScriptUrl = (\n host: string,\n containerId: string,\n queryParams?: Record<string, string | number | boolean>,\n dataLayerName: string = DEFAULT_DATA_LAYER_NAME\n): string => buildUrl('gtm', host, containerId, queryParams, dataLayerName);\n\n/**\n * Build a GTM noscript iframe URL.\n */\nexport const buildGtmNoscriptUrl = (\n host: string,\n containerId: string,\n queryParams?: Record<string, string | number | boolean>,\n dataLayerName: string = DEFAULT_DATA_LAYER_NAME\n): string => buildUrl('ns', host, containerId, queryParams, dataLayerName);\n\n/**\n * Escape a string for use in HTML attributes.\n * @internal Primarily for internal use. API may change.\n */\nexport const escapeAttributeValue = (value: string): string =>\n value.replace(/&/g, '&amp;').replace(/\"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n\n// Re-export default host for convenience\nexport { DEFAULT_GTM_HOST };\n","import { DEFAULT_DATA_LAYER_NAME, DEFAULT_GTM_HOST } from './constants';\nimport { createLogger } from './logger';\nimport type {\n ContainerDescriptor,\n CreateGtmClientOptions,\n ScriptAttributes,\n ScriptLoadState,\n ScriptLoadStatus,\n ScriptRetryOptions\n} from './types';\nimport { getGoogleTagManager } from './types';\nimport { buildGtmScriptUrl } from './url-utils';\n\nconst CONTAINER_ATTR = 'data-gtm-container-id';\nconst INSTANCE_ATTR = 'data-gtm-kit-instance';\n\n// Default values for retry and timeout\nconst DEFAULT_RETRY_ATTEMPTS = 0;\nconst DEFAULT_RETRY_DELAY = 1000;\nconst DEFAULT_RETRY_MAX_DELAY = 30000;\nconst DEFAULT_SCRIPT_TIMEOUT = 30000;\nconst DEFAULT_INITIALIZATION_TIMEOUT = 5000;\n\ninterface Deferred<T> {\n promise: Promise<T>;\n resolve: (value: T) => void;\n settled: boolean;\n}\n\nconst createDeferred = <T>(): Deferred<T> => {\n let resolved = false;\n let resolver: (value: T) => void;\n\n const promise = new Promise<T>((resolve) => {\n resolver = resolve;\n });\n\n return {\n get settled() {\n return resolved;\n },\n promise,\n resolve: (value: T) => {\n if (resolved) {\n return;\n }\n\n resolved = true;\n resolver(value);\n }\n } as Deferred<T>;\n};\n\nexport interface NormalizedContainer extends ContainerDescriptor {\n queryParams?: Record<string, string | number | boolean>;\n}\n\nexport interface ScriptManagerOptions {\n instanceId: string;\n host?: string;\n dataLayerName?: string;\n scriptAttributes?: ScriptAttributes;\n defaultQueryParams?: Record<string, string | number | boolean>;\n logger?: CreateGtmClientOptions['logger'];\n retry?: ScriptRetryOptions;\n scriptTimeout?: number;\n onScriptError?: (state: ScriptLoadState) => void;\n onScriptTimeout?: (containerId: string) => void;\n verifyInitialization?: boolean;\n initializationTimeout?: number;\n onPartialLoad?: (state: ScriptLoadState) => void;\n}\n\nexport interface EnsureResult {\n inserted: HTMLScriptElement[];\n}\n\nconst findExistingScript = (containerId: string): HTMLScriptElement | null => {\n if (typeof document === 'undefined') {\n return null;\n }\n\n const attrSelector = `script[${CONTAINER_ATTR}=\"${containerId}\"]`;\n const existingWithAttr = document.querySelector(attrSelector);\n if (existingWithAttr) {\n return existingWithAttr as HTMLScriptElement;\n }\n\n const scripts = Array.from(document.getElementsByTagName('script'));\n return scripts.find((script) => script.src.includes(`id=${encodeURIComponent(containerId)}`)) || null;\n};\n\nconst formatErrorMessage = (event: Event): string => {\n if (event instanceof ErrorEvent) {\n if (event.error) {\n return String(event.error);\n }\n\n if (event.message) {\n return event.message;\n }\n }\n\n return 'Failed to load GTM script.';\n};\n\nexport class ScriptManager {\n private readonly logger = createLogger(this.options.logger);\n private readonly host = this.options.host ?? DEFAULT_GTM_HOST;\n private readonly dataLayerName = this.options.dataLayerName ?? DEFAULT_DATA_LAYER_NAME;\n private readonly defaultQueryParams = this.options.defaultQueryParams;\n private readonly scriptAttributes = this.options.scriptAttributes;\n private readonly insertedScripts = new Set<HTMLScriptElement>();\n private readonly readyCallbacks = new Set<(state: ScriptLoadState[]) => void>();\n private readiness = createDeferred<ScriptLoadState[]>();\n private readonly loadStates = new Map<string, ScriptLoadState>();\n private readonly pendingContainers = new Set<string>();\n\n // Retry configuration\n private readonly retryAttempts: number;\n private readonly retryDelay: number;\n private readonly retryMaxDelay: number;\n private readonly scriptTimeout: number;\n private readonly onScriptError?: (state: ScriptLoadState) => void;\n private readonly onScriptTimeout?: (containerId: string) => void;\n\n // Initialization verification\n private readonly verifyInitialization: boolean;\n private readonly initializationTimeout: number;\n private readonly onPartialLoad?: (state: ScriptLoadState) => void;\n\n // Retry tracking\n private readonly retryCounters = new Map<string, number>();\n private readonly activeTimeouts = new Map<string, ReturnType<typeof setTimeout>>();\n private readonly verificationTimeouts = new Map<string, ReturnType<typeof setTimeout>>();\n\n // Page unload handling\n private unloadHandler: (() => void) | null = null;\n private isUnloading = false;\n\n constructor(private readonly options: ScriptManagerOptions) {\n // Initialize retry configuration\n this.retryAttempts = options.retry?.attempts ?? DEFAULT_RETRY_ATTEMPTS;\n this.retryDelay = options.retry?.delay ?? DEFAULT_RETRY_DELAY;\n this.retryMaxDelay = options.retry?.maxDelay ?? DEFAULT_RETRY_MAX_DELAY;\n this.scriptTimeout = options.scriptTimeout ?? DEFAULT_SCRIPT_TIMEOUT;\n this.onScriptError = options.onScriptError;\n this.onScriptTimeout = options.onScriptTimeout;\n\n // Initialize verification configuration\n this.verifyInitialization = options.verifyInitialization ?? false;\n this.initializationTimeout = options.initializationTimeout ?? DEFAULT_INITIALIZATION_TIMEOUT;\n this.onPartialLoad = options.onPartialLoad;\n }\n\n whenReady(): Promise<ScriptLoadState[]> {\n return this.readiness.promise;\n }\n\n isReady(): boolean {\n return this.readiness.settled;\n }\n\n getScriptStates(): ScriptLoadState[] {\n return Array.from(this.loadStates.values());\n }\n\n onReady(callback: (state: ScriptLoadState[]) => void): () => void {\n this.readyCallbacks.add(callback);\n\n if (this.readiness.settled) {\n callback(Array.from(this.loadStates.values()));\n }\n\n return () => {\n this.readyCallbacks.delete(callback);\n };\n }\n\n private notifyReady(): void {\n const snapshot = Array.from(this.loadStates.values());\n\n if (!this.readiness.settled) {\n this.readiness.resolve(snapshot);\n }\n\n for (const callback of this.readyCallbacks) {\n callback(snapshot);\n }\n }\n\n private maybeNotifyReady(): void {\n if (this.pendingContainers.size === 0) {\n this.notifyReady();\n }\n }\n\n private recordState(state: ScriptLoadState): void {\n this.loadStates.set(state.containerId, state);\n }\n\n private resetReadiness(): void {\n this.pendingContainers.clear();\n this.loadStates.clear();\n this.readiness = createDeferred<ScriptLoadState[]>();\n }\n\n /**\n * Calculate delay for retry attempt using exponential backoff.\n * delay = min(initialDelay * 2^attempt, maxDelay)\n */\n private calculateRetryDelay(attempt: number): number {\n const delay = this.retryDelay * Math.pow(2, attempt);\n return Math.min(delay, this.retryMaxDelay);\n }\n\n /**\n * Get current retry count for a container.\n */\n private getRetryCount(containerId: string): number {\n return this.retryCounters.get(containerId) ?? 0;\n }\n\n /**\n * Check if retry is available for a container.\n */\n private canRetry(containerId: string): boolean {\n return this.getRetryCount(containerId) < this.retryAttempts;\n }\n\n /**\n * Clear timeout for a container.\n */\n private clearContainerTimeout(containerId: string): void {\n const timeout = this.activeTimeouts.get(containerId);\n if (timeout) {\n clearTimeout(timeout);\n this.activeTimeouts.delete(containerId);\n }\n }\n\n /**\n * Schedule a retry for a failed container.\n */\n private scheduleRetry(container: NormalizedContainer, targetParent: HTMLElement): void {\n const containerId = container.id;\n const currentAttempt = this.getRetryCount(containerId);\n const delay = this.calculateRetryDelay(currentAttempt);\n\n this.logger.info('Scheduling retry for GTM container.', {\n containerId,\n attempt: currentAttempt + 1,\n maxAttempts: this.retryAttempts,\n delay\n });\n\n this.retryCounters.set(containerId, currentAttempt + 1);\n\n const timerId = setTimeout(() => {\n this.activeTimeouts.delete(containerId);\n this.loadScript(container, targetParent);\n }, delay);\n this.activeTimeouts.set(containerId, timerId);\n }\n\n /**\n * Handle final failure after all retries exhausted.\n */\n private handleFinalFailure(containerId: string, url: string, error: string, isTimeout: boolean): void {\n const state: ScriptLoadState = {\n containerId,\n src: url,\n status: 'failed',\n error: isTimeout ? `Script load timeout (${this.scriptTimeout}ms)` : error,\n fromCache: false\n };\n\n this.recordState(state);\n this.pendingContainers.delete(containerId);\n\n // Call error callback\n if (this.onScriptError) {\n try {\n this.onScriptError(state);\n } catch (callbackError) {\n this.logger.error('Error in onScriptError callback.', { error: callbackError });\n }\n }\n\n this.maybeNotifyReady();\n }\n\n /**\n * Load a single container script with retry and timeout support.\n * Returns the created script element.\n */\n private loadScript(container: NormalizedContainer, targetParent: HTMLElement): HTMLScriptElement {\n const containerId = container.id;\n const params = {\n ...this.defaultQueryParams,\n ...container.queryParams\n };\n\n const script = document.createElement('script');\n const url = buildGtmScriptUrl(this.host, containerId, params, this.dataLayerName);\n script.src = url;\n script.setAttribute(CONTAINER_ATTR, containerId);\n script.setAttribute(INSTANCE_ATTR, this.options.instanceId);\n\n const attributes = this.scriptAttributes ?? {};\n if (attributes.async !== undefined) {\n script.async = attributes.async;\n } else {\n script.async = true;\n }\n if (attributes.defer !== undefined) {\n script.defer = attributes.defer;\n }\n\n for (const [key, value] of Object.entries(attributes)) {\n if (key === 'async' || key === 'defer') {\n continue;\n }\n\n if (value === undefined || value === null) {\n continue;\n }\n\n const stringValue = String(value);\n\n if (key === 'nonce') {\n script.nonce = stringValue;\n continue;\n }\n\n // Block src (already set) and event handler attributes to prevent XSS\n const lowerKey = key.toLowerCase();\n if (lowerKey === 'src' || lowerKey.startsWith('on')) {\n continue;\n }\n\n script.setAttribute(key, stringValue);\n }\n\n let settled = false;\n const loadStartTime = performance.now();\n\n const settle = (status: ScriptLoadStatus, event?: Event): void => {\n if (settled) {\n return;\n }\n settled = true;\n\n // Calculate load time\n const loadTimeMs = Math.round(performance.now() - loadStartTime);\n\n // Clear the timeout\n this.clearContainerTimeout(containerId);\n\n if (status === 'loaded') {\n // Script loaded - check if we need to verify GTM initialization\n if (this.verifyInitialization) {\n this.startInitializationVerification(containerId, url, loadTimeMs);\n } else {\n // No verification, mark as success immediately\n const state: ScriptLoadState = {\n containerId,\n src: url,\n status: 'loaded',\n fromCache: false,\n loadTimeMs\n };\n this.recordState(state);\n this.pendingContainers.delete(containerId);\n this.logger.info('GTM container script loaded successfully.', { containerId, src: url, loadTimeMs });\n this.maybeNotifyReady();\n }\n return;\n }\n\n // Failure - check if we can retry\n const errorMessage = event ? formatErrorMessage(event) : 'Script load failed';\n const canRetry = this.canRetry(containerId);\n\n if (canRetry) {\n this.logger.warn('GTM script load failed, will retry.', {\n containerId,\n src: url,\n error: errorMessage,\n retriesRemaining: this.retryAttempts - this.getRetryCount(containerId)\n });\n // Remove the failed script\n if (script.parentNode) {\n script.parentNode.removeChild(script);\n }\n this.insertedScripts.delete(script);\n this.scheduleRetry(container, targetParent);\n } else {\n this.logger.error('GTM script load failed, no retries remaining.', {\n containerId,\n src: url,\n error: errorMessage\n });\n this.handleFinalFailure(containerId, url, errorMessage, false);\n }\n };\n\n script.addEventListener('load', () => settle('loaded'));\n script.addEventListener('error', (event) => settle('failed', event));\n\n // Set up timeout if configured\n if (this.scriptTimeout > 0) {\n const timeoutId = setTimeout(() => {\n if (!settled) {\n this.logger.warn('GTM script load timeout.', {\n containerId,\n src: url,\n timeout: this.scriptTimeout\n });\n\n // Call timeout callback\n if (this.onScriptTimeout) {\n try {\n this.onScriptTimeout(containerId);\n } catch (callbackError) {\n this.logger.error('Error in onScriptTimeout callback.', { error: callbackError });\n }\n }\n\n // Treat timeout as failure for retry logic\n const canRetry = this.canRetry(containerId);\n if (canRetry) {\n settled = true;\n // Remove the timed-out script\n if (script.parentNode) {\n script.parentNode.removeChild(script);\n }\n this.insertedScripts.delete(script);\n this.scheduleRetry(container, targetParent);\n } else {\n settled = true;\n this.clearContainerTimeout(containerId);\n this.handleFinalFailure(containerId, url, `Script load timeout (${this.scriptTimeout}ms)`, true);\n }\n }\n }, this.scriptTimeout);\n\n this.activeTimeouts.set(containerId, timeoutId);\n }\n\n targetParent.appendChild(script);\n this.insertedScripts.add(script);\n this.logger.debug('Injecting GTM container script.', { containerId, src: url });\n\n return script;\n }\n\n ensure(containers: NormalizedContainer[]): EnsureResult {\n if (typeof document === 'undefined') {\n this.logger.warn('No document available – skipping script injection.');\n\n for (const container of containers) {\n if (!container.id) {\n continue;\n }\n\n this.recordState({\n containerId: container.id,\n status: 'skipped',\n error: 'Document unavailable for script injection.'\n });\n }\n\n this.maybeNotifyReady();\n return { inserted: [] };\n }\n\n const inserted: HTMLScriptElement[] = [];\n const targetParent = document.head || document.body;\n if (!targetParent) {\n this.logger.error('Unable to find document.head or document.body for script injection.');\n\n for (const container of containers) {\n if (!container.id) {\n continue;\n }\n\n this.recordState({\n containerId: container.id,\n status: 'skipped',\n error: 'Missing document.head and document.body for GTM script injection.'\n });\n }\n\n this.maybeNotifyReady();\n return { inserted: [] };\n }\n\n // Set up page unload handler to gracefully handle navigation during script load\n this.setupUnloadHandler();\n\n for (const container of containers) {\n if (!container.id || !container.id.trim()) {\n this.logger.warn('Skipping container with empty or invalid id.', { container });\n continue;\n }\n\n const existing = findExistingScript(container.id);\n if (existing) {\n this.logger.debug('Container script already present, skipping injection.', {\n containerId: container.id\n });\n\n this.recordState({\n containerId: container.id,\n src: existing.src,\n status: 'loaded',\n fromCache: true\n });\n continue;\n }\n\n // Initialize retry counter for this container\n this.retryCounters.set(container.id, 0);\n this.pendingContainers.add(container.id);\n\n // Load script with retry and timeout support\n const script = this.loadScript(container, targetParent);\n inserted.push(script);\n }\n\n this.maybeNotifyReady();\n return { inserted };\n }\n\n /**\n * Set up handler for page unload to gracefully resolve pending scripts.\n * Uses 'pagehide' event which is more reliable than 'beforeunload' for cleanup.\n */\n private setupUnloadHandler(): void {\n if (typeof window === 'undefined' || this.unloadHandler) {\n return;\n }\n\n this.unloadHandler = () => {\n this.handlePageUnload();\n };\n\n // Use 'pagehide' as it's more reliable for cleanup (fires even on bfcache navigation)\n window.addEventListener('pagehide', this.unloadHandler);\n }\n\n /**\n * Handle page unload by marking pending scripts as skipped and resolving promises.\n * This prevents hanging promises and ensures clean state during navigation.\n */\n private handlePageUnload(): void {\n if (this.isUnloading) {\n return;\n }\n\n this.isUnloading = true;\n\n // Mark all pending containers as skipped\n for (const containerId of this.pendingContainers) {\n this.recordState({\n containerId,\n status: 'skipped',\n error: 'Page navigation interrupted script load.'\n });\n }\n\n // Clear all pending containers\n this.pendingContainers.clear();\n\n // Clear all timeouts to prevent callbacks from firing after unload\n for (const timeout of this.activeTimeouts.values()) {\n clearTimeout(timeout);\n }\n this.activeTimeouts.clear();\n\n for (const timeout of this.verificationTimeouts.values()) {\n clearTimeout(timeout);\n }\n this.verificationTimeouts.clear();\n\n // Resolve the readiness promise immediately to prevent hanging\n this.notifyReady();\n }\n\n /**\n * Remove page unload handler.\n */\n private removeUnloadHandler(): void {\n if (typeof window === 'undefined' || !this.unloadHandler) {\n return;\n }\n\n window.removeEventListener('pagehide', this.unloadHandler);\n this.unloadHandler = null;\n }\n\n /**\n * Start initialization verification after script loads.\n * Checks for GTM initialization by looking for google_tag_manager global.\n */\n private startInitializationVerification(containerId: string, url: string, loadTimeMs?: number): void {\n const startTime = Date.now();\n const pollInterval = 100; // Check every 100ms\n\n const checkInitialization = (): boolean => {\n // Check for google_tag_manager global with this container\n const gtm = getGoogleTagManager();\n return gtm !== undefined && typeof gtm[containerId] !== 'undefined';\n };\n\n const poll = (): void => {\n if (checkInitialization()) {\n // GTM initialized successfully\n this.clearVerificationTimeout(containerId);\n const state: ScriptLoadState = {\n containerId,\n src: url,\n status: 'loaded',\n fromCache: false,\n loadTimeMs\n };\n this.recordState(state);\n this.pendingContainers.delete(containerId);\n this.logger.info('GTM container initialized successfully.', { containerId, src: url, loadTimeMs });\n this.maybeNotifyReady();\n return;\n }\n\n const elapsed = Date.now() - startTime;\n if (elapsed >= this.initializationTimeout) {\n // Timeout - mark as partial load failure\n this.clearVerificationTimeout(containerId);\n const state: ScriptLoadState = {\n containerId,\n src: url,\n status: 'partial',\n fromCache: false,\n error: `GTM failed to initialize within ${this.initializationTimeout}ms`,\n loadTimeMs\n };\n this.recordState(state);\n this.pendingContainers.delete(containerId);\n this.logger.warn('GTM container loaded but failed to initialize.', {\n containerId,\n src: url,\n timeout: this.initializationTimeout,\n loadTimeMs\n });\n\n // Call partial load callback\n if (this.onPartialLoad) {\n try {\n this.onPartialLoad(state);\n } catch (callbackError) {\n this.logger.error('Error in onPartialLoad callback.', { error: callbackError });\n }\n }\n\n this.maybeNotifyReady();\n return;\n }\n\n // Schedule next poll\n const timeoutId = setTimeout(poll, pollInterval);\n this.verificationTimeouts.set(containerId, timeoutId);\n };\n\n // Start polling\n poll();\n }\n\n /**\n * Clear verification timeout for a container.\n */\n private clearVerificationTimeout(containerId: string): void {\n const timeout = this.verificationTimeouts.get(containerId);\n if (timeout) {\n clearTimeout(timeout);\n this.verificationTimeouts.delete(containerId);\n }\n }\n\n teardown() {\n if (typeof document === 'undefined') {\n return;\n }\n\n // Remove page unload handler\n this.removeUnloadHandler();\n this.isUnloading = false;\n\n // Clear any active timeouts\n for (const timeout of this.activeTimeouts.values()) {\n clearTimeout(timeout);\n }\n this.activeTimeouts.clear();\n\n // Clear verification timeouts\n for (const timeout of this.verificationTimeouts.values()) {\n clearTimeout(timeout);\n }\n this.verificationTimeouts.clear();\n\n // Clear retry counters\n this.retryCounters.clear();\n\n for (const script of this.insertedScripts) {\n if (script.parentNode) {\n script.parentNode.removeChild(script);\n }\n }\n\n this.insertedScripts.clear();\n this.resetReadiness();\n }\n}\n","import { DEFAULT_DATA_LAYER_NAME, DEFAULT_MAX_DATA_LAYER_SIZE, MAX_CONSENT_WAIT_MS } from './constants';\nimport { ensureDataLayer, pushToDataLayer, createTracedDataLayer } from './data-layer';\nimport { createConsentCommandValue } from './consent';\nimport type { ConsentRegionOptions, ConsentState } from './consent';\nimport { createLogger, createDebugLogger } from './logger';\nimport { ScriptManager } from './script-manager';\nimport { normalizeContainer } from './url-utils';\nimport { isValidDataLayerName } from './types';\nimport type { CreateGtmClientOptions, DataLayerValue, GtmClient, GtmDiagnostics, ScriptLoadState } from './types';\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n};\n\n/**\n * WeakMap cache for serialization results.\n * Uses WeakMap to automatically clean up when objects are garbage collected,\n * preventing memory leaks while avoiding redundant serialization of the same objects.\n */\nconst serializationCache = new WeakMap<object, string | null>();\n\n/**\n * Serialize a value with circular reference detection.\n * @param value - The value to serialize\n * @param seen - Set of objects currently being serialized (for cycle detection)\n */\nconst serializeUnknown = (value: unknown, seen: Set<object> = new Set()): string | null => {\n // Check cache for object values (arrays and plain objects)\n if (typeof value === 'object' && value !== null) {\n if (serializationCache.has(value)) {\n return serializationCache.get(value) ?? null;\n }\n // Detect circular reference - if we've seen this object in the current path\n if (seen.has(value)) {\n // Circular reference detected, return null (cannot serialize)\n return null;\n }\n }\n\n if (value === null || typeof value === 'boolean' || typeof value === 'number') {\n return JSON.stringify(value);\n }\n\n if (typeof value === 'string') {\n return JSON.stringify(value);\n }\n\n if (Array.isArray(value)) {\n // Add to seen set before recursing\n seen.add(value);\n const parts: string[] = [];\n for (const entry of value) {\n const serialized = serializeUnknown(entry, seen);\n if (serialized === null) {\n seen.delete(value);\n serializationCache.set(value, null);\n return null;\n }\n parts.push(serialized);\n }\n seen.delete(value);\n const result = `[${parts.join(',')}]`;\n serializationCache.set(value, result);\n return result;\n }\n\n if (isPlainObject(value)) {\n // Add to seen set before recursing\n seen.add(value);\n const keys = Object.keys(value).sort();\n const parts: string[] = [];\n for (const key of keys) {\n const serialized = serializeUnknown(value[key], seen);\n if (serialized === null) {\n seen.delete(value);\n serializationCache.set(value, null);\n return null;\n }\n parts.push(`${JSON.stringify(key)}:${serialized}`);\n }\n seen.delete(value);\n const result = `{${parts.join(',')}}`;\n serializationCache.set(value, result);\n return result;\n }\n\n return null;\n};\n\nconst serializeDataLayerValue = (value: DataLayerValue): string | null => {\n if (Array.isArray(value)) {\n return serializeUnknown(value);\n }\n\n if (isPlainObject(value)) {\n return serializeUnknown(value);\n }\n\n return null;\n};\n\nconst isConsentCommandValue = (value: DataLayerValue): value is unknown[] =>\n Array.isArray(value) &&\n value.length >= 3 &&\n value[0] === 'consent' &&\n (value[1] === 'default' || value[1] === 'update');\n\nconst isStartEvent = (value: DataLayerValue): boolean => {\n if (!isPlainObject(value)) {\n return false;\n }\n\n return value.event === 'gtm.js';\n};\n\ninterface QueuedEntry {\n value: DataLayerValue;\n signature: string | null;\n}\n\nlet instanceCounter = 0;\n\n// Track active client instances per dataLayer name to warn about potential conflicts\nconst activeClientsPerDataLayer = new Map<string, Set<string>>();\n\n/**\n * Internal implementation of the GTM client.\n * Use {@link createGtmClient} to create instances.\n * @internal\n */\nexport class GtmClientImpl implements GtmClient {\n private readonly logger = this.options.debug ? createDebugLogger() : createLogger(this.options.logger);\n private readonly resolvedDataLayerName = this.options.dataLayerName ?? DEFAULT_DATA_LAYER_NAME;\n private readonly maxDataLayerSize = this.options.maxDataLayerSize ?? DEFAULT_MAX_DATA_LAYER_SIZE;\n private readonly containers = Array.isArray(this.options.containers)\n ? this.options.containers.map(normalizeContainer)\n : [normalizeContainer(this.options.containers)];\n private readonly queue: QueuedEntry[] = [];\n private readonly queuedConsentSignatures = new Set<string>();\n private readonly deliveredConsentSignatures = new Set<string>();\n private snapshotSignatures: Set<string> | null = null;\n private readonly scriptManager = new ScriptManager({\n instanceId: this.instanceId,\n host: this.options.host,\n dataLayerName: this.resolvedDataLayerName,\n defaultQueryParams: this.options.defaultQueryParams,\n scriptAttributes: this.options.scriptAttributes,\n logger: this.options.logger,\n retry: this.options.retry,\n scriptTimeout: this.options.scriptTimeout,\n onScriptError: this.options.onScriptError,\n onScriptTimeout: this.options.onScriptTimeout,\n verifyInitialization: this.options.verifyInitialization,\n initializationTimeout: this.options.initializationTimeout,\n onPartialLoad: this.options.onPartialLoad\n });\n private dataLayerState: ReturnType<typeof ensureDataLayer> | null = null;\n private initialized = false;\n private readonly startTimestamp = Date.now();\n\n constructor(\n private readonly options: CreateGtmClientOptions,\n private readonly instanceId: string\n ) {\n if (!this.containers.length) {\n throw new Error(\n 'At least one GTM container ID is required to initialize the client. ' +\n 'Example: createGtmClient({ containers: \"GTM-XXXXXX\" })'\n );\n }\n\n // Validate container IDs - filter out empty/whitespace-only IDs\n const invalidContainers = this.containers.filter((c) => !c.id || !c.id.trim());\n if (invalidContainers.length > 0) {\n if (invalidContainers.length === this.containers.length) {\n // All containers are invalid - throw\n throw new Error(\n 'All container IDs are empty or invalid. At least one valid GTM container ID is required. ' +\n 'Container IDs should be in the format \"GTM-XXXXXX\". ' +\n 'Example: createGtmClient({ containers: \"GTM-ABC123\" })'\n );\n } else {\n // Some containers are invalid - warn and continue with valid ones\n this.logger.warn(\n `${invalidContainers.length} container ID(s) are empty or invalid and will be skipped. ` +\n 'Valid container IDs should be in the format \"GTM-XXXXXX\".'\n );\n }\n }\n\n // Validate dataLayer name if provided\n if (this.options.dataLayerName !== undefined && !isValidDataLayerName(this.options.dataLayerName)) {\n throw new Error(\n `Invalid dataLayer name: \"${this.options.dataLayerName}\". ` +\n 'DataLayer names must be valid JavaScript identifiers (letters, numbers, underscores, dollar signs) ' +\n 'and cannot be reserved words. Example: \"dataLayer\", \"myCustomLayer\", \"gtm_data\"'\n );\n }\n }\n\n /**\n * Initializes the GTM client, setting up the dataLayer and loading GTM scripts.\n *\n * **Important**: Call `setConsentDefaults()` BEFORE `init()` if you need consent mode.\n * Events pushed before `init()` are queued and delivered after initialization.\n *\n * This method is idempotent - calling it multiple times has no effect after\n * the first call.\n *\n * @example\n * ```ts\n * const client = createGtmClient({ containers: 'GTM-XXXXXX' });\n *\n * // Set consent BEFORE init\n * client.setConsentDefaults({ analytics_storage: 'denied' });\n *\n * // Initialize GTM\n * client.init();\n *\n * // Now safe to push events\n * client.push({ event: 'page_view' });\n * ```\n */\n init(): void {\n if (this.initialized) {\n this.logger.debug('GTM client already initialized; skipping.');\n return;\n }\n\n this.initialized = true;\n\n this.logger.info('Initializing GTM client.', {\n containers: this.containers.map((container) => container.id),\n dataLayerName: this.resolvedDataLayerName\n });\n\n // Track this client instance for the dataLayer name\n if (!activeClientsPerDataLayer.has(this.resolvedDataLayerName)) {\n activeClientsPerDataLayer.set(this.resolvedDataLayerName, new Set());\n }\n const activeClients = activeClientsPerDataLayer.get(this.resolvedDataLayerName)!;\n\n // Warn if another client is already using this dataLayer\n if (activeClients.size > 0) {\n this.logger.warn(\n `Multiple GTM client instances are sharing the same dataLayer \"${this.resolvedDataLayerName}\". ` +\n 'This may cause unexpected behavior if one instance tears down while others are active. ' +\n 'Consider using different dataLayerName values for separate clients.',\n { activeInstances: activeClients.size + 1, dataLayerName: this.resolvedDataLayerName }\n );\n }\n activeClients.add(this.instanceId);\n\n // Warn if using custom dataLayerName but default 'dataLayer' already exists\n // This is a common misconfiguration - the existing dataLayer will be ignored\n const existingDataLayer = (globalThis as Record<string, unknown>)['dataLayer'];\n if (this.resolvedDataLayerName !== 'dataLayer' && typeof existingDataLayer !== 'undefined') {\n this.logger.warn(\n `Using custom dataLayerName \"${this.resolvedDataLayerName}\" but global \"dataLayer\" already exists. ` +\n 'The existing dataLayer will NOT be used. If you have existing GTM code using \"dataLayer\", ' +\n 'either remove the custom dataLayerName option or update your existing code to use the new name.',\n {\n customName: this.resolvedDataLayerName,\n existingDataLayerLength: Array.isArray(existingDataLayer) ? existingDataLayer.length : undefined\n }\n );\n }\n\n this.dataLayerState = ensureDataLayer(this.resolvedDataLayerName);\n\n // Wrap dataLayer with tracing proxy in debug mode\n if (this.options.debug) {\n const tracedDataLayer = createTracedDataLayer(this.dataLayerState.dataLayer, {\n logger: this.logger,\n dataLayerName: this.resolvedDataLayerName\n });\n // Update the global reference to use the traced version\n const globalScope = globalThis as Record<string, unknown>;\n globalScope[this.resolvedDataLayerName] = tracedDataLayer;\n // Also update our local reference\n this.dataLayerState.dataLayer = tracedDataLayer;\n this.logger.debug('DataLayer mutation tracing enabled.', {\n dataLayerName: this.resolvedDataLayerName\n });\n }\n\n this.captureSnapshotSignatures();\n this.pushStartEvent();\n this.flushQueue();\n this.scriptManager.ensure(this.containers);\n }\n\n /**\n * Pushes a value to the GTM dataLayer.\n *\n * **Queuing behavior:** If called before `init()`, values are silently queued\n * and delivered when `init()` is called. This allows you to push events early\n * (e.g., during app startup) without waiting for GTM initialization.\n *\n * **Error handling:** Push errors are caught and logged but do not throw.\n * This ensures analytics failures never crash your application.\n *\n * @param value - The value to push to the dataLayer. Can be:\n * - An event object: `{ event: 'page_view', page_title: 'Home' }`\n * - Data variables: `{ user_id: '123', user_type: 'premium' }`\n * - A callback function for timing: `() => console.log('Processed')`\n *\n * @example Pushing events\n * ```ts\n * // Page view event\n * client.push({ event: 'page_view', page_title: 'Home' });\n *\n * // Custom event with data\n * client.push({\n * event: 'button_click',\n * button_id: 'signup-cta',\n * button_text: 'Sign Up Now'\n * });\n * ```\n *\n * @example Pushing data (no event)\n * ```ts\n * // Set user properties (no event fired)\n * client.push({\n * user_id: 'usr_123',\n * user_type: 'premium',\n * account_age_days: 365\n * });\n * ```\n *\n * @example Pre-init queuing\n * ```ts\n * const client = createGtmClient({ containers: 'GTM-XXXXX' });\n *\n * // These are queued (init not called yet)\n * client.push({ event: 'early_event_1' });\n * client.push({ event: 'early_event_2' });\n *\n * // Later, when ready to initialize:\n * client.init(); // Queued events are now delivered to dataLayer\n * ```\n */\n push(value: DataLayerValue): void {\n if (value === undefined || value === null) {\n this.logger.warn('Skipped dataLayer push: value is null or undefined.', { value });\n return;\n }\n\n const immediate = this.deliverToDataLayer(value);\n\n if (immediate) {\n this.logger.debug('Pushed value to dataLayer.', { immediate: true });\n } else {\n this.logger.debug('Queued dataLayer value (pre-init).', { queueLength: this.queue.length });\n // Show queue visualization when items are queued\n this.logQueueVisualization('Current queue state');\n }\n }\n\n setConsentDefaults(state: ConsentState, options?: ConsentRegionOptions): void {\n // Error if called after init - consent defaults MUST be set BEFORE GTM loads\n if (this.initialized) {\n throw new Error(\n 'setConsentDefaults() must be called BEFORE init(). ' +\n 'Google requires consent defaults to be set before GTM loads to ensure proper tag behavior. ' +\n 'Move your setConsentDefaults() call before client.init().'\n );\n }\n\n // Validate waitForUpdate value\n if (options?.waitForUpdate !== undefined) {\n const waitValue = options.waitForUpdate;\n\n // Error on invalid values (negative, NaN, Infinity)\n if (typeof waitValue !== 'number' || !Number.isFinite(waitValue) || waitValue < 0) {\n throw new Error(\n `Invalid waitForUpdate value: ${waitValue}. ` +\n 'waitForUpdate must be a non-negative finite number representing milliseconds.'\n );\n }\n\n // Warn if waitForUpdate exceeds the maximum reasonable wait time\n if (waitValue > MAX_CONSENT_WAIT_MS) {\n this.logger.warn(\n `waitForUpdate value of ${waitValue}ms exceeds 30 minutes. ` +\n 'This may cause significant delays in tag firing. Consider using a smaller value.',\n { waitForUpdate: waitValue }\n );\n }\n }\n\n const value = createConsentCommandValue({ command: 'default', state, options });\n const immediate = this.deliverToDataLayer(value);\n\n this.logger.info('Applied consent defaults.', {\n immediate,\n state,\n options\n });\n }\n\n /**\n * Updates the consent state. Each unique consent state is pushed to the dataLayer.\n *\n * **Concurrent updates behavior (last-write-wins):**\n * - All unique consent updates are pushed to the dataLayer in the order they are called\n * - Duplicate consent updates (same state and options) are deduplicated via signature comparison\n * - GTM processes consent commands in order, so the last update for a given key wins\n * - This is intentional: it allows rapid UI changes to all be recorded while preventing duplicates\n *\n * @example\n * ```ts\n * // These concurrent updates are all pushed (all unique)\n * client.updateConsent({ ad_storage: 'granted' }); // Pushed\n * client.updateConsent({ analytics_storage: 'granted' }); // Pushed\n * client.updateConsent({ ad_storage: 'denied' }); // Pushed (different state)\n *\n * // This duplicate is deduplicated\n * client.updateConsent({ ad_storage: 'denied' }); // Skipped (duplicate)\n * ```\n */\n updateConsent(state: ConsentState, options?: ConsentRegionOptions): void {\n const value = createConsentCommandValue({ command: 'update', state, options });\n const immediate = this.deliverToDataLayer(value);\n\n this.logger.info('Updated consent state.', {\n immediate,\n state,\n options\n });\n }\n\n /**\n * Tears down the GTM client, restoring the dataLayer to its pre-init state.\n *\n * Use this for cleanup in React useEffect, Vue onUnmounted, etc.\n * After teardown, the client cannot be reused - create a new instance instead.\n *\n * **Warning**: If multiple clients share the same dataLayer name, teardown\n * will restore the dataLayer snapshot, which may affect other clients.\n *\n * @example React cleanup\n * ```tsx\n * useEffect(() => {\n * const client = createGtmClient({ containers: 'GTM-XXXXXX' });\n * client.init();\n *\n * return () => client.teardown();\n * }, []);\n * ```\n */\n teardown(): void {\n this.logger.info('Tearing down GTM client instance.', { dataLayerName: this.resolvedDataLayerName });\n\n // Remove this client from active tracking\n const activeClients = activeClientsPerDataLayer.get(this.resolvedDataLayerName);\n if (activeClients) {\n activeClients.delete(this.instanceId);\n\n // Warn if other clients are still using this dataLayer (restore may affect them)\n if (activeClients.size > 0 && this.dataLayerState) {\n this.logger.warn(\n `Tearing down GTM client while ${activeClients.size} other instance(s) are still using ` +\n `the same dataLayer \"${this.resolvedDataLayerName}\". ` +\n \"The dataLayer will be restored to this client's snapshot, which may affect other clients.\",\n { remainingInstances: activeClients.size, dataLayerName: this.resolvedDataLayerName }\n );\n }\n\n // Clean up the Map entry if no more clients\n if (activeClients.size === 0) {\n activeClientsPerDataLayer.delete(this.resolvedDataLayerName);\n }\n }\n\n this.scriptManager.teardown();\n if (this.dataLayerState) {\n this.dataLayerState.restore();\n }\n this.queue.length = 0;\n this.queuedConsentSignatures.clear();\n this.deliveredConsentSignatures.clear();\n this.snapshotSignatures = null;\n this.initialized = false;\n this.dataLayerState = null;\n }\n\n /**\n * Returns whether `init()` has been called.\n *\n * Note: This does NOT mean GTM scripts have loaded - use `isReady()` for that.\n *\n * @returns `true` if `init()` has been called, `false` otherwise\n */\n isInitialized(): boolean {\n return this.initialized;\n }\n\n /**\n * Returns whether all GTM scripts have finished loading (successfully or not).\n *\n * This is a synchronous check - use `whenReady()` if you need to wait.\n *\n * @returns `true` if all scripts have completed loading, `false` if still loading\n *\n * @example\n * ```ts\n * if (client.isReady()) {\n * // Scripts loaded, safe to check script states\n * } else {\n * // Scripts still loading\n * await client.whenReady();\n * }\n * ```\n */\n isReady(): boolean {\n return this.scriptManager.isReady();\n }\n\n /**\n * Returns a Promise that resolves when all GTM scripts have finished loading.\n *\n * The promise resolves with an array of script load states - check each state's\n * `status` to determine if scripts loaded successfully.\n *\n * @returns Promise resolving to array of script load states\n *\n * @example\n * ```ts\n * const states = await client.whenReady();\n *\n * const allSuccessful = states.every(s => s.status === 'loaded');\n * if (!allSuccessful) {\n * console.warn('Some GTM scripts failed to load');\n * }\n * ```\n */\n whenReady(): Promise<ScriptLoadState[]> {\n return this.scriptManager.whenReady();\n }\n\n /**\n * Registers a callback to be invoked when all GTM scripts have finished loading.\n *\n * If scripts are already loaded, the callback is invoked immediately.\n * Returns an unsubscribe function to cancel the callback.\n *\n * @param callback - Function to call with script load states\n * @returns Unsubscribe function\n *\n * @example\n * ```ts\n * const unsubscribe = client.onReady((states) => {\n * console.log('GTM loaded:', states);\n * });\n *\n * // Later, if needed:\n * unsubscribe();\n * ```\n */\n onReady(callback: (state: ScriptLoadState[]) => void): () => void {\n return this.scriptManager.onReady(callback);\n }\n\n /**\n * The resolved dataLayer name (defaults to 'dataLayer').\n */\n get dataLayerName(): string {\n return this.resolvedDataLayerName;\n }\n\n /**\n * Returns diagnostic information about the GTM client state.\n *\n * Useful for debugging and monitoring. Includes initialization status,\n * script states, queue size, and uptime.\n *\n * @returns Diagnostic information object\n *\n * @example\n * ```ts\n * const diagnostics = client.getDiagnostics();\n * console.log('GTM Status:', {\n * initialized: diagnostics.initialized,\n * ready: diagnostics.ready,\n * dataLayerSize: diagnostics.dataLayerSize,\n * uptime: `${diagnostics.uptimeMs}ms`\n * });\n * ```\n */\n getDiagnostics(): GtmDiagnostics {\n return {\n initialized: this.initialized,\n ready: this.scriptManager.isReady(),\n dataLayerName: this.resolvedDataLayerName,\n dataLayerSize: this.dataLayerState?.dataLayer.length ?? 0,\n queueSize: this.queue.length,\n consentCommandsDelivered: this.deliveredConsentSignatures.size,\n containers: this.containers.map((c) => c.id),\n scriptStates: this.scriptManager.getScriptStates(),\n uptimeMs: Date.now() - this.startTimestamp,\n debugMode: this.options.debug ?? false\n };\n }\n\n private flushQueue(): void {\n if (!this.dataLayerState) {\n return;\n }\n\n if (this.options.debug && this.queue.length > 0) {\n this.logQueueVisualization('Flushing queue');\n }\n\n while (this.queue.length) {\n const entry = this.queue.shift();\n if (!entry) {\n continue;\n }\n\n this.pushValueToDataLayer(entry.value, entry.signature);\n\n if (entry.signature) {\n this.queuedConsentSignatures.delete(entry.signature);\n }\n }\n\n if (this.options.debug) {\n this.logger.debug('Queue flushed successfully.', { queueLength: 0 });\n }\n }\n\n /**\n * Logs a visual representation of the event queue for debugging.\n * Shows event types, order, and basic structure.\n */\n private logQueueVisualization(action: string): void {\n if (!this.options.debug || this.queue.length === 0) {\n return;\n }\n\n const queueSummary = this.queue.map((entry, index) => {\n const value = entry.value;\n let eventType = 'unknown';\n let details = '';\n\n if (Array.isArray(value)) {\n // Consent command\n eventType = `consent:${value[1] ?? 'command'}`;\n details = JSON.stringify(value[2] ?? {}).slice(0, 50);\n } else if (typeof value === 'object' && value !== null) {\n const obj = value as Record<string, unknown>;\n if (obj.event) {\n eventType = String(obj.event);\n // Add ecommerce indicator if present\n if (obj.ecommerce) {\n details = '[ecommerce]';\n }\n } else {\n eventType = 'data';\n details = Object.keys(obj).slice(0, 3).join(', ');\n }\n } else if (typeof value === 'function') {\n eventType = 'callback';\n }\n\n return ` ${index + 1}. ${eventType}${details ? ` (${details})` : ''}`;\n });\n\n this.logger.debug(`[Queue Visualization] ${action}`, {\n queueLength: this.queue.length,\n entries: '\\n' + queueSummary.join('\\n')\n });\n }\n\n private deliverToDataLayer(value: DataLayerValue): boolean {\n if (this.initialized && this.dataLayerState) {\n this.pushValueToDataLayer(value);\n return true;\n }\n\n this.queueValue(value);\n return false;\n }\n\n private pushStartEvent(): void {\n if (!this.dataLayerState) {\n return;\n }\n\n if (this.hasExistingStartEvent()) {\n this.logger.debug('Detected existing gtm.js event; skipping duplicate start push.');\n return;\n }\n\n const startEvent = { 'gtm.start': this.startTimestamp, event: 'gtm.js' } as const;\n this.pushValueToDataLayer(startEvent);\n }\n\n private captureSnapshotSignatures(): void {\n if (!this.dataLayerState) {\n return;\n }\n\n const snapshot = this.dataLayerState.snapshot ?? [];\n this.snapshotSignatures = new Set<string>();\n\n for (const value of snapshot) {\n const signature = serializeDataLayerValue(value);\n if (signature) {\n this.snapshotSignatures.add(signature);\n if (isConsentCommandValue(value)) {\n this.deliveredConsentSignatures.add(signature);\n }\n }\n }\n }\n\n private queueValue(value: DataLayerValue): void {\n const signature = isConsentCommandValue(value) ? serializeDataLayerValue(value) : null;\n\n if (signature && this.queuedConsentSignatures.has(signature)) {\n this.logger.debug('Skipping duplicate queued dataLayer value.', { value });\n return;\n }\n\n const entry: QueuedEntry = { value, signature };\n\n if (isConsentCommandValue(value)) {\n const firstNonConsentIndex = this.queue.findIndex((queued) => !isConsentCommandValue(queued.value));\n\n if (firstNonConsentIndex === -1) {\n this.queue.push(entry);\n } else {\n this.queue.splice(firstNonConsentIndex, 0, entry);\n }\n } else {\n this.queue.push(entry);\n }\n\n if (signature) {\n this.queuedConsentSignatures.add(signature);\n }\n }\n\n private pushValueToDataLayer(value: DataLayerValue, existingSignature?: string | null): void {\n if (!this.dataLayerState) {\n return;\n }\n\n const signature = existingSignature ?? serializeDataLayerValue(value);\n const isConsentCommand = isConsentCommandValue(value);\n const seenInSnapshot = signature ? this.snapshotSignatures?.has(signature) : false;\n const alreadyDeliveredConsent =\n isConsentCommand && signature ? this.deliveredConsentSignatures.has(signature) : false;\n\n if (signature && seenInSnapshot) {\n this.logger.debug('Skipping duplicate dataLayer value detected during hydration.', { value });\n if (isConsentCommand) {\n this.deliveredConsentSignatures.add(signature);\n }\n return;\n }\n\n if (isConsentCommand && alreadyDeliveredConsent) {\n this.logger.debug('Skipping duplicate consent command.', { value });\n return;\n }\n\n // Enforce size limit before pushing to prevent unbounded growth\n this.enforceDataLayerSizeLimit();\n\n // Wrap dataLayer push in try/catch to prevent errors from crashing the app\n try {\n pushToDataLayer(this.dataLayerState, value);\n } catch (error) {\n this.logger.error('Failed to push value to dataLayer.', {\n error: error instanceof Error ? error.message : String(error),\n value\n });\n // Don't rethrow - let the app continue even if GTM tracking fails\n return;\n }\n\n if (isConsentCommand && signature) {\n this.deliveredConsentSignatures.add(signature);\n }\n }\n\n private hasExistingStartEvent(): boolean {\n if (!this.dataLayerState) {\n return false;\n }\n\n const snapshot = this.dataLayerState.snapshot ?? [];\n if (snapshot.some(isStartEvent)) {\n return true;\n }\n\n return this.dataLayerState.dataLayer.some(isStartEvent);\n }\n\n private enforceDataLayerSizeLimit(): void {\n if (this.maxDataLayerSize <= 0 || !this.dataLayerState) {\n return;\n }\n\n const dataLayer = this.dataLayerState.dataLayer;\n // Trim when at or above the limit to make room for the incoming push\n const excess = dataLayer.length - this.maxDataLayerSize;\n\n if (excess < 0) {\n return;\n }\n\n // Find indices of critical entries that should not be trimmed\n const criticalIndices = new Set<number>();\n for (let i = 0; i < dataLayer.length; i++) {\n const value = dataLayer[i];\n if (isStartEvent(value) || isConsentCommandValue(value)) {\n criticalIndices.add(i);\n }\n }\n\n // Remove at least 1 entry to make room for the incoming push\n const targetTrimCount = Math.max(1, excess);\n let trimmedCount = 0;\n let index = 0;\n\n while (trimmedCount < targetTrimCount && index < dataLayer.length) {\n if (!criticalIndices.has(index)) {\n dataLayer.splice(index, 1);\n trimmedCount++;\n // Adjust critical indices for removed element\n const newCriticalIndices = new Set<number>();\n for (const criticalIndex of criticalIndices) {\n if (criticalIndex > index) {\n newCriticalIndices.add(criticalIndex - 1);\n } else {\n newCriticalIndices.add(criticalIndex);\n }\n }\n criticalIndices.clear();\n for (const ci of newCriticalIndices) {\n criticalIndices.add(ci);\n }\n } else {\n index++;\n }\n }\n\n if (trimmedCount > 0) {\n this.logger.warn('DataLayer size limit reached; trimmed oldest entries.', {\n trimmedCount,\n currentSize: dataLayer.length,\n maxSize: this.maxDataLayerSize\n });\n\n this.options.onDataLayerTrim?.(trimmedCount, dataLayer.length);\n }\n }\n}\n\n/**\n * Creates a new GTM client instance for managing Google Tag Manager interactions.\n *\n * The client handles:\n * - DataLayer initialization and management\n * - GTM script loading with retry support\n * - Consent mode commands (defaults and updates)\n * - Event queuing before initialization\n * - Hydration-aware deduplication for SSR apps\n *\n * @param options - Configuration options for the GTM client\n * @returns A GTM client instance\n *\n * @example Basic usage\n * ```ts\n * import { createGtmClient } from '@jwiedeman/gtm-kit';\n *\n * const client = createGtmClient({\n * containers: 'GTM-XXXXXX'\n * });\n *\n * client.init();\n * client.push({ event: 'page_view', page_title: 'Home' });\n * ```\n *\n * @example With consent mode\n * ```ts\n * const client = createGtmClient({\n * containers: 'GTM-XXXXXX',\n * debug: true\n * });\n *\n * // Set consent defaults BEFORE init\n * client.setConsentDefaults({\n * ad_storage: 'denied',\n * analytics_storage: 'denied'\n * });\n *\n * client.init();\n *\n * // Update consent after user interaction\n * client.updateConsent({ analytics_storage: 'granted' });\n * ```\n *\n * @example With error handling\n * ```ts\n * const client = createGtmClient({\n * containers: 'GTM-XXXXXX',\n * retry: { attempts: 3, delay: 1000 },\n * onScriptError: (state) => {\n * console.error('GTM failed to load:', state.error);\n * }\n * });\n * ```\n *\n * @see {@link CreateGtmClientOptions} for all configuration options\n */\nexport const createGtmClient = (options: CreateGtmClientOptions): GtmClient => {\n const instanceId = `gtm-kit-${++instanceCounter}`;\n return new GtmClientImpl(options, instanceId);\n};\n","import type { GtmClient } from '../types';\nimport type {\n EcommerceEvent,\n EcommerceEventName,\n EcommercePayload,\n EventForName,\n EventPayload,\n GtmEvent\n} from './types';\n\nconst isRecord = (value: unknown): value is Record<string, unknown> => typeof value === 'object' && value !== null;\n\nconst clonePayload = <TPayload extends EventPayload | undefined>(payload: TPayload): TPayload => {\n if (!payload) {\n return payload;\n }\n\n return { ...payload } as TPayload;\n};\n\nexport const pushEvent = <TName extends string, TPayload extends EventPayload = EventPayload>(\n client: Pick<GtmClient, 'push'>,\n name: TName,\n payload?: TPayload\n): EventForName<TName> => {\n if (!name) {\n throw new Error(\n 'An event name is required when pushing to the dataLayer. ' +\n 'Example: pushEvent(client, \"page_view\", { page_path: \"/home\" })'\n );\n }\n\n if (payload !== undefined && !isRecord(payload)) {\n throw new Error(\n 'Event payloads must be plain objects when pushing to the dataLayer. ' +\n `Received: ${typeof payload}. ` +\n 'Example: pushEvent(client, \"click\", { button_name: \"cta\" })'\n );\n }\n\n const event = {\n event: name,\n ...(clonePayload(payload) ?? {})\n } as GtmEvent<TName, TPayload>;\n\n client.push(event);\n return event as EventForName<TName>;\n};\n\nexport interface PushEcommerceOptions<TExtras extends EventPayload = EventPayload> {\n extras?: TExtras;\n}\n\nexport const pushEcommerce = <TName extends EcommerceEventName, TExtras extends EventPayload = EventPayload>(\n client: Pick<GtmClient, 'push'>,\n name: TName,\n ecommerce: EcommercePayload,\n options?: PushEcommerceOptions<TExtras>\n): EcommerceEvent<TName, TExtras> => {\n if (!isRecord(ecommerce)) {\n throw new Error(\n 'Ecommerce payload must be an object. ' +\n `Received: ${ecommerce === null ? 'null' : typeof ecommerce}. ` +\n 'Example: pushEcommerce(client, \"purchase\", { transaction_id: \"T123\", value: 99.99, items: [...] })'\n );\n }\n\n const extras = options?.extras ?? {};\n\n if (!isRecord(extras)) {\n throw new Error(\n 'Ecommerce extras must be an object when provided. ' +\n `Received: ${typeof extras}. ` +\n 'Example: pushEcommerce(client, \"purchase\", ecommerce, { extras: { user_id: \"123\" } })'\n );\n }\n\n const payload = { ...extras, ecommerce } as { ecommerce: EcommercePayload } & TExtras;\n return pushEvent(client, name, payload) as EcommerceEvent<TName, TExtras>;\n};\n","import type { ContainerConfigInput, ContainerDescriptor } from './types';\nimport { DEFAULT_GTM_HOST } from './constants';\nimport { normalizeContainer, buildGtmNoscriptUrl, escapeAttributeValue } from './url-utils';\n\nconst DEFAULT_IFRAME_ATTRIBUTES: Record<string, string> = {\n height: '0',\n width: '0',\n style: 'display:none;visibility:hidden',\n title: 'Google Tag Manager'\n};\n\nconst buildAttributeString = (attributes: Record<string, string | number | boolean> | undefined): string => {\n if (!attributes) {\n return '';\n }\n\n const entries = Object.entries(attributes);\n if (!entries.length) {\n return '';\n }\n\n return entries.map(([key, value]) => `${key}=\"${escapeAttributeValue(String(value))}\"`).join(' ');\n};\n\nexport interface NoscriptOptions {\n host?: string;\n defaultQueryParams?: Record<string, string | number | boolean>;\n iframeAttributes?: Record<string, string | number | boolean>;\n}\n\nconst buildNoscriptForContainer = (container: ContainerDescriptor, options: NoscriptOptions): string => {\n if (!container.id) {\n throw new Error(\n 'Container ID is required to build noscript markup. ' + 'Example: createNoscriptMarkup(\"GTM-XXXXXX\")'\n );\n }\n\n const host = options.host ?? DEFAULT_GTM_HOST;\n const params = {\n ...options.defaultQueryParams,\n ...container.queryParams\n };\n\n const src = buildGtmNoscriptUrl(host, container.id, params);\n const iframeAttributes = {\n ...DEFAULT_IFRAME_ATTRIBUTES,\n ...options.iframeAttributes\n };\n const attributeString = buildAttributeString(iframeAttributes);\n\n const attrs = attributeString ? ` ${attributeString}` : '';\n return `<noscript><iframe src=\"${escapeAttributeValue(src)}\"${attrs}></iframe></noscript>`;\n};\n\nexport const createNoscriptMarkup = (\n containers: ContainerConfigInput[] | ContainerConfigInput,\n options: NoscriptOptions = {}\n): string => {\n const normalizedContainers = Array.isArray(containers)\n ? containers.map(normalizeContainer)\n : [normalizeContainer(containers)];\n\n if (!normalizedContainers.length) {\n throw new Error(\n 'At least one container is required to build noscript markup. ' +\n 'Example: createNoscriptMarkup(\"GTM-XXXXXX\") or createNoscriptMarkup([\"GTM-ABC123\", \"GTM-XYZ789\"])'\n );\n }\n\n return normalizedContainers.map((container) => buildNoscriptForContainer(container, options)).join('');\n};\n\nexport const DEFAULT_NOSCRIPT_IFRAME_ATTRIBUTES = { ...DEFAULT_IFRAME_ATTRIBUTES };\n","/**\n * Auto-queue: Automatic dataLayer buffering for race condition elimination.\n *\n * This module provides automatic buffering of dataLayer pushes that occur before\n * GTM.js loads. Events are captured, stored in order, and replayed once GTM is ready.\n *\n * @example\n * ```ts\n * // Call as early as possible (ideally inline in <head>)\n * import { installAutoQueue } from '@jwiedeman/gtm-kit';\n *\n * installAutoQueue(); // Start buffering immediately\n *\n * // Later, events pushed before GTM loads are automatically queued\n * window.dataLayer.push({ event: 'early_event' }); // Buffered!\n *\n * // When GTM loads, all buffered events replay in order\n * ```\n *\n * @example\n * ```html\n * <!-- Inline script for earliest possible buffering -->\n * <script>\n * // Minimal inline version for <head>\n * (function(w,d,n){\n * w[n]=w[n]||[];var q=[],o=w[n].push.bind(w[n]);\n * w[n].push=function(){q.push(arguments);return o.apply(this,arguments)};\n * w.__gtmkit_buffer=q;\n * })(window,document,'dataLayer');\n * </script>\n * ```\n */\n\nimport { DEFAULT_DATA_LAYER_NAME } from './constants';\nimport type { DataLayerValue } from './types';\n\n/**\n * Escape a string for safe use in JavaScript string literals.\n * Prevents XSS when interpolating values into inline scripts.\n */\nconst escapeJsString = (value: string): string =>\n value\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/'/g, \"\\\\'\")\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')\n .replace(/</g, '\\\\x3c')\n .replace(/>/g, '\\\\x3e')\n .replace(/\\u2028/g, '\\\\u2028')\n .replace(/\\u2029/g, '\\\\u2029');\n\n/**\n * Checks if a dataLayer value is the GTM.js load event.\n * Used to detect when GTM has finished loading.\n */\nconst isGtmLoadEvent = (value: DataLayerValue): boolean =>\n value !== null &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n (value as Record<string, unknown>).event === 'gtm.js';\n\n/**\n * Cleans up the inline buffer global reference.\n * Call this in error handlers to prevent memory leaks if the full\n * GTM Kit fails to initialize after the inline script ran.\n *\n * @example\n * ```ts\n * try {\n * // Initialize GTM Kit\n * const client = createGtmClient({ containers: 'GTM-XXXXX' });\n * client.init();\n * } catch (error) {\n * // Clean up inline buffer on error\n * cleanupInlineBuffer();\n * console.error('GTM initialization failed:', error);\n * }\n * ```\n */\nexport function cleanupInlineBuffer(): void {\n if (typeof globalThis === 'undefined') {\n return;\n }\n\n const globalScope = globalThis as Record<string, unknown>;\n if (globalScope.__gtmkit_buffer !== undefined) {\n delete globalScope.__gtmkit_buffer;\n }\n}\n\n/** Options for configuring the auto-queue behavior */\nexport interface AutoQueueOptions {\n /**\n * Name of the dataLayer array. Defaults to 'dataLayer'.\n */\n dataLayerName?: string;\n\n /**\n * Interval in milliseconds to check if GTM has loaded.\n * Lower values = faster detection, higher CPU usage.\n * @default 50\n */\n pollInterval?: number;\n\n /**\n * Maximum time in milliseconds to wait for GTM before giving up.\n * Set to 0 for unlimited waiting.\n * @default 30000 (30 seconds)\n */\n timeout?: number;\n\n /**\n * Maximum number of events to buffer.\n * Prevents memory issues if GTM never loads.\n * @default 1000\n */\n maxBufferSize?: number;\n\n /**\n * Callback fired when the buffer is replayed.\n */\n onReplay?: (bufferedCount: number) => void;\n\n /**\n * Callback fired if timeout is reached before GTM loads.\n */\n onTimeout?: (bufferedCount: number) => void;\n}\n\n/** State of the auto-queue system */\nexport interface AutoQueueState {\n /** Whether the auto-queue is currently active */\n active: boolean;\n /** Number of events currently buffered */\n bufferedCount: number;\n /** Whether GTM has been detected as ready */\n gtmReady: boolean;\n /** Manually trigger replay (useful for testing) */\n replay: () => void;\n /** Uninstall the auto-queue and restore original push */\n uninstall: () => void;\n}\n\ninterface BufferedEntry {\n value: DataLayerValue;\n timestamp: number;\n}\n\n/**\n * Installs automatic dataLayer buffering that captures events before GTM loads.\n *\n * Call this as early as possible in your application lifecycle, ideally before\n * any other scripts that might push to the dataLayer.\n *\n * The auto-queue:\n * 1. Creates the dataLayer if it doesn't exist\n * 2. Intercepts all pushes to capture them in a buffer\n * 3. Detects when GTM.js loads by watching for the 'gtm.js' event\n * 4. Replays all buffered events in order once GTM is ready\n * 5. Removes itself, allowing normal dataLayer operation\n *\n * @param options - Configuration options\n * @returns State object with control methods\n *\n * @example\n * ```ts\n * const queue = installAutoQueue({\n * onReplay: (count) => console.log(`Replayed ${count} buffered events`),\n * onTimeout: (count) => console.warn(`GTM didn't load, ${count} events buffered`)\n * });\n *\n * // Check state\n * console.log(queue.bufferedCount); // Number of events waiting\n *\n * // Manual control (usually not needed)\n * queue.replay(); // Force replay now\n * queue.uninstall(); // Remove the interceptor\n * ```\n */\nexport function installAutoQueue(options: AutoQueueOptions = {}): AutoQueueState {\n const {\n dataLayerName = DEFAULT_DATA_LAYER_NAME,\n pollInterval = 50,\n timeout = 30000,\n maxBufferSize = 1000,\n onReplay,\n onTimeout\n } = options;\n\n // Skip in non-browser environments\n if (typeof globalThis === 'undefined' || typeof globalThis.document === 'undefined') {\n return createNoopState();\n }\n\n const globalScope = globalThis as Record<string, unknown>;\n\n // Create dataLayer if it doesn't exist\n if (!Array.isArray(globalScope[dataLayerName])) {\n globalScope[dataLayerName] = [];\n }\n\n const dataLayer = globalScope[dataLayerName] as DataLayerValue[];\n const buffer: BufferedEntry[] = [];\n const originalPush = dataLayer.push.bind(dataLayer);\n\n let active = true;\n let gtmReady = false;\n let pollTimer: ReturnType<typeof setInterval> | null = null;\n let timeoutTimer: ReturnType<typeof setTimeout> | null = null;\n let replayTimer: ReturnType<typeof setTimeout> | null = null;\n\n // Check if GTM.js event is present (indicating GTM has loaded)\n const isGtmLoaded = (): boolean => dataLayer.some(isGtmLoadEvent);\n\n // Replay all buffered events to the dataLayer\n const replay = (): void => {\n if (!active) return;\n\n active = false;\n gtmReady = true;\n\n // Clear all timers\n if (pollTimer) {\n clearInterval(pollTimer);\n pollTimer = null;\n }\n if (timeoutTimer) {\n clearTimeout(timeoutTimer);\n timeoutTimer = null;\n }\n if (replayTimer) {\n clearTimeout(replayTimer);\n replayTimer = null;\n }\n\n // Restore original push\n dataLayer.push = originalPush;\n\n // Replay buffered events in order\n const count = buffer.length;\n for (const entry of buffer) {\n originalPush(entry.value);\n }\n buffer.length = 0;\n\n onReplay?.(count);\n };\n\n // Uninstall without replaying\n const uninstall = (): void => {\n if (!active) return;\n\n active = false;\n\n // Clear all timers\n if (pollTimer) {\n clearInterval(pollTimer);\n pollTimer = null;\n }\n if (timeoutTimer) {\n clearTimeout(timeoutTimer);\n timeoutTimer = null;\n }\n if (replayTimer) {\n clearTimeout(replayTimer);\n replayTimer = null;\n }\n\n dataLayer.push = originalPush;\n buffer.length = 0;\n\n // Clean up any lingering global buffer reference\n cleanupInlineBuffer();\n };\n\n // Create intercepted push function\n const interceptedPush = function (this: DataLayerValue[], ...args: DataLayerValue[]): number {\n for (const value of args) {\n // Always push to actual dataLayer (GTM may already be listening)\n originalPush(value);\n\n // Buffer the value for potential replay\n if (active && buffer.length < maxBufferSize) {\n buffer.push({\n value,\n timestamp: Date.now()\n });\n }\n\n // Check if this push indicates GTM is ready\n if (active && !replayTimer && isGtmLoadEvent(value)) {\n // GTM just loaded! Trigger replay on next tick to ensure\n // this event is fully processed first\n replayTimer = setTimeout(replay, 0);\n }\n }\n\n return dataLayer.length;\n };\n\n // Install the interceptor\n dataLayer.push = interceptedPush;\n\n // Check if GTM was already loaded before we installed\n if (isGtmLoaded()) {\n // GTM already present, replay immediately\n replayTimer = setTimeout(replay, 0);\n } else {\n // Poll for GTM readiness as backup detection\n pollTimer = setInterval(() => {\n if (isGtmLoaded()) {\n replay();\n }\n }, pollInterval);\n\n // Set timeout if configured\n if (timeout > 0) {\n timeoutTimer = setTimeout(() => {\n if (active) {\n onTimeout?.(buffer.length);\n // Don't uninstall on timeout - keep buffering in case GTM loads late\n }\n }, timeout);\n }\n }\n\n // Return state object\n return {\n get active() {\n return active;\n },\n get bufferedCount() {\n return buffer.length;\n },\n get gtmReady() {\n return gtmReady;\n },\n replay,\n uninstall\n };\n}\n\n/**\n * Creates a minimal inline script for earliest possible buffering.\n *\n * This returns a script that can be embedded directly in the HTML `<head>`\n * before any other scripts. It's a minimal version of installAutoQueue()\n * that captures events until the full GTM Kit is loaded.\n *\n * @param dataLayerName - Name of the dataLayer array\n * @returns Inline script string to embed in HTML\n *\n * @example\n * ```ts\n * // In your SSR template\n * const inlineScript = createAutoQueueScript();\n * // Output: <script>{inlineScript}</script> in <head>\n * ```\n */\nexport function createAutoQueueScript(dataLayerName: string = DEFAULT_DATA_LAYER_NAME): string {\n // Minified inline script that:\n // 1. Creates dataLayer if missing\n // 2. Overrides push to capture events\n // 3. Stores buffer in __gtmkit_buffer for later retrieval\n // SECURITY: Escape the dataLayerName to prevent XSS via malicious input\n const safeName = escapeJsString(dataLayerName);\n return `(function(w,n){w[n]=w[n]||[];var q=[],o=w[n].push.bind(w[n]);w[n].push=function(){for(var i=0;i<arguments.length;i++){q.push({v:arguments[i],t:Date.now()});o(arguments[i])}return w[n].length};w.__gtmkit_buffer={q:q,o:o,n:n}})(window,'${safeName}');`;\n}\n\n/**\n * Attaches to an existing inline buffer created by createAutoQueueScript().\n *\n * If you used the inline script in your HTML head, call this when the full\n * GTM Kit loads to take over buffer management and enable replay.\n *\n * @param options - Configuration options\n * @returns State object, or null if no inline buffer exists\n *\n * @example\n * ```ts\n * // After GTM Kit bundle loads\n * const queue = attachToInlineBuffer({\n * onReplay: (count) => console.log(`Replayed ${count} events`)\n * });\n *\n * if (queue) {\n * console.log(`Taking over ${queue.bufferedCount} buffered events`);\n * }\n * ```\n */\nexport function attachToInlineBuffer(options: Omit<AutoQueueOptions, 'dataLayerName'> = {}): AutoQueueState | null {\n if (typeof globalThis === 'undefined') {\n return null;\n }\n\n const globalScope = globalThis as Record<string, unknown>;\n const inlineBuffer = globalScope.__gtmkit_buffer as\n | {\n q: { v: DataLayerValue; t: number }[];\n o: (...args: DataLayerValue[]) => number;\n n: string;\n }\n | undefined;\n\n if (!inlineBuffer) {\n return null;\n }\n\n const { n: dataLayerName } = inlineBuffer;\n\n // Clean up the global reference\n delete globalScope.__gtmkit_buffer;\n\n // Install full auto-queue with the same dataLayer name\n // The buffer from the inline script is already in the dataLayer,\n // so we just need to continue monitoring from here\n return installAutoQueue({\n ...options,\n dataLayerName\n });\n}\n\n/** Creates a no-op state for SSR environments */\nfunction createNoopState(): AutoQueueState {\n // No-op functions for SSR - these do nothing intentionally\n const noop = (): void => {\n /* no-op for SSR */\n };\n return {\n active: false,\n bufferedCount: 0,\n gtmReady: false,\n replay: noop,\n uninstall: noop\n };\n}\n"]}