@aranova/tracking-react 0.6.1 → 0.7.0

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/README.md CHANGED
@@ -52,6 +52,32 @@ createRoot(document.getElementById('root')!).render(
52
52
  );
53
53
  ```
54
54
 
55
+ ### Multiple gtag IDs
56
+
57
+ To install multiple Google Ads tags simultaneously (for example a production MCC and a test MCC for verifying conversion actions before they touch the live account), pass `gtagIds` instead of `gtagId`. Every entry fires `gtag('config', ...)` on every page — gtag natively supports multiple configured tags.
58
+
59
+ ```tsx
60
+ <TrackingProvider
61
+ gtagIds={{
62
+ production: 'AW-111111111', // real client account
63
+ test: 'AW-222222222', // test MCC for development
64
+ }}
65
+ >
66
+ <App />
67
+ </TrackingProvider>
68
+ ```
69
+
70
+ The labels are arbitrary and surface in the Aranova dashboard's SDK versions table. You can also stamp events with a deployment environment so the dashboard can filter out test traffic:
71
+
72
+ ```ts
73
+ createTracking({
74
+ apiKey: import.meta.env.VITE_ARANOVA_TRACKING_API_KEY,
75
+ endpoint: import.meta.env.VITE_ARANOVA_TRACKING_ENDPOINT,
76
+ environment: import.meta.env.MODE, // 'production' | 'development'
77
+ triggers: { /* ... */ },
78
+ });
79
+ ```
80
+
55
81
  ## Manual Events
56
82
 
57
83
  Manual events must be registered under `triggers.manual` before `trackEvent()` accepts them.
package/dist/index.d.mts CHANGED
@@ -11,20 +11,6 @@ import { z } from 'zod';
11
11
  */
12
12
  declare function ConsentBanner(): react_jsx_runtime.JSX.Element | null;
13
13
 
14
- interface GoogleAdsTrackingProps {
15
- /**
16
- * Google Ads tag id, for example `AW-123456789`.
17
- */
18
- gtagId: string;
19
- }
20
- /**
21
- * Client component that loads Google Ads gtag and restores stored consent.
22
- *
23
- * Render once near the application root when the client site runs paid Google
24
- * Ads. The component renders nothing.
25
- */
26
- declare function GoogleAdsTracking({ gtagId }: GoogleAdsTrackingProps): null;
27
-
28
14
  /**
29
15
  * Visitor consent state stored by the SDK.
30
16
  *
@@ -62,6 +48,23 @@ interface TrackingParams {
62
48
  * whether a site uses the Next, React, or script-tag integration.
63
49
  */
64
50
  type TrackingInstallSurface = 'next' | 'react' | 'script';
51
+ /**
52
+ * Deployment environment label for event tagging.
53
+ *
54
+ * Used to stamp tracking events with the deployment context so the dashboard
55
+ * can distinguish production traffic from dev test traffic. The backend
56
+ * enforces this via a Postgres enum, so values are strictly one of
57
+ * `'production'` or `'development'`.
58
+ */
59
+ type TrackingEnvironment = 'production' | 'development';
60
+ /**
61
+ * Labelled map of Google Ads tag IDs.
62
+ *
63
+ * ALL entries are loaded simultaneously via `gtag('config', ...)` — the keys
64
+ * are human-readable labels (e.g. `production`, `test`) and the values are
65
+ * Google Ads tag IDs (e.g. `AW-123456789`).
66
+ */
67
+ type GtagEnvironmentMap = Record<string, string>;
65
68
  /**
66
69
  * Runtime context attached to tracking sessions and events.
67
70
  */
@@ -78,6 +81,10 @@ interface TrackingClientContext {
78
81
  page_title: string | null;
79
82
  /** Browser document referrer at client creation time. */
80
83
  referrer: string | null;
84
+ /** Deployment environment label, e.g. `'production'`, `'development'`. */
85
+ environment: TrackingEnvironment | null;
86
+ /** All active gtag IDs loaded on this page, keyed by label. */
87
+ active_gtag_ids: Record<string, string> | null;
81
88
  }
82
89
  /**
83
90
  * Session payload sent to `POST /tracking/events`.
@@ -127,6 +134,13 @@ interface TrackingInitConfig {
127
134
  endpoint?: string;
128
135
  /** Optional Google Ads tag id, for example `AW-123456789`. */
129
136
  gtagId?: string;
137
+ /**
138
+ * Labelled map of Google Ads tag IDs. ALL are loaded simultaneously.
139
+ * When provided, `gtagId` is ignored.
140
+ */
141
+ gtagIds?: GtagEnvironmentMap;
142
+ /** Deployment environment label reported in session context. */
143
+ environment?: TrackingEnvironment;
130
144
  /** Whether to capture attribution params from `window.location`. Defaults to true. */
131
145
  autoCaptureTrackingParams?: boolean;
132
146
  /** Whether the browser script should inject the default consent banner. */
@@ -174,6 +188,8 @@ interface TrackingContextInput {
174
188
  referrer?: string | null;
175
189
  sdkVersion?: string | null;
176
190
  siteOrigin?: string | null;
191
+ environment?: TrackingEnvironment | null;
192
+ activeGtagIds?: Record<string, string> | null;
177
193
  }
178
194
  interface TrackingEventInput {
179
195
  eventType: string;
@@ -275,6 +291,7 @@ declare const sdkHeartbeatMetadataSchema: z.ZodObject<{
275
291
  manual: string[];
276
292
  }>;
277
293
  trigger_config: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>>>>;
294
+ configured_gtag_ids: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodString>>>;
278
295
  }, "strict", z.ZodTypeAny, {
279
296
  sdk_version: string;
280
297
  package_name: string | null;
@@ -284,6 +301,7 @@ declare const sdkHeartbeatMetadataSchema: z.ZodObject<{
284
301
  manual: string[];
285
302
  };
286
303
  trigger_config?: Record<string, Record<string, unknown>> | null | undefined;
304
+ configured_gtag_ids?: Record<string, string> | null | undefined;
287
305
  }, {
288
306
  sdk_version: string;
289
307
  package_name: string | null;
@@ -293,6 +311,7 @@ declare const sdkHeartbeatMetadataSchema: z.ZodObject<{
293
311
  manual: string[];
294
312
  };
295
313
  trigger_config?: Record<string, Record<string, unknown>> | null | undefined;
314
+ configured_gtag_ids?: Record<string, string> | null | undefined;
296
315
  }>;
297
316
  type SdkHeartbeatMetadata = z.infer<typeof sdkHeartbeatMetadataSchema>;
298
317
  /**
@@ -1028,6 +1047,7 @@ declare const EVENT_REGISTRY: {
1028
1047
  manual: string[];
1029
1048
  }>;
1030
1049
  trigger_config: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>>>>;
1050
+ configured_gtag_ids: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodString>>>;
1031
1051
  }, "strict", z.ZodTypeAny, {
1032
1052
  sdk_version: string;
1033
1053
  package_name: string | null;
@@ -1037,6 +1057,7 @@ declare const EVENT_REGISTRY: {
1037
1057
  manual: string[];
1038
1058
  };
1039
1059
  trigger_config?: Record<string, Record<string, unknown>> | null | undefined;
1060
+ configured_gtag_ids?: Record<string, string> | null | undefined;
1040
1061
  }, {
1041
1062
  sdk_version: string;
1042
1063
  package_name: string | null;
@@ -1046,6 +1067,7 @@ declare const EVENT_REGISTRY: {
1046
1067
  manual: string[];
1047
1068
  };
1048
1069
  trigger_config?: Record<string, Record<string, unknown>> | null | undefined;
1070
+ configured_gtag_ids?: Record<string, string> | null | undefined;
1049
1071
  }>;
1050
1072
  readonly configSchema: z.ZodObject<{}, "strict", z.ZodTypeAny, {}, {}>;
1051
1073
  };
@@ -1370,6 +1392,27 @@ interface TypedTrackingClient<TRegistry extends TriggerRegistryConfig> {
1370
1392
  getVisitorId(): string;
1371
1393
  }
1372
1394
 
1395
+ /**
1396
+ * Props for the Google Ads tracking component.
1397
+ *
1398
+ * Accepts either a single `gtagId` (legacy) or a labelled `gtagIds` map
1399
+ * where ALL entries are loaded simultaneously via `gtag('config', ...)`.
1400
+ */
1401
+ type GoogleAdsTrackingProps = {
1402
+ gtagId: string;
1403
+ gtagIds?: undefined;
1404
+ } | {
1405
+ gtagId?: undefined;
1406
+ gtagIds: GtagEnvironmentMap;
1407
+ };
1408
+ /**
1409
+ * Client component that loads Google Ads gtag and restores stored consent.
1410
+ *
1411
+ * Render once near the application root when the client site runs paid Google
1412
+ * Ads. The component renders nothing.
1413
+ */
1414
+ declare function GoogleAdsTracking(props: GoogleAdsTrackingProps): null;
1415
+
1373
1416
  /**
1374
1417
  * Read the captured Google Ads click id from first-party cookies.
1375
1418
  *
@@ -1408,6 +1451,14 @@ interface CreateTrackingOptions<TRegistry extends TriggerRegistryConfig> {
1408
1451
  * `automatic.page_view` is required — every tracking install needs it.
1409
1452
  */
1410
1453
  triggers: TRegistry;
1454
+ /**
1455
+ * Deployment environment label reported in session context.
1456
+ *
1457
+ * Does not affect which gtag IDs are loaded — all configured IDs are
1458
+ * loaded simultaneously. This value is purely for event tagging so the
1459
+ * dashboard can filter by environment.
1460
+ */
1461
+ environment?: TrackingEnvironment;
1411
1462
  /**
1412
1463
  * When true, the typed client validates every `trackEvent()` metadata
1413
1464
  * payload through the Zod schema before forwarding. Errors are thrown
@@ -1419,9 +1470,14 @@ interface TrackingProviderProps {
1419
1470
  /**
1420
1471
  * Optional Google Ads tag id, for example `AW-123456789`.
1421
1472
  *
1422
- * If omitted, no gtag script is loaded by the provider.
1473
+ * If omitted and `gtagIds` is also omitted, no gtag script is loaded.
1423
1474
  */
1424
1475
  gtagId?: string;
1476
+ /**
1477
+ * Labelled map of Google Ads tag IDs. ALL are loaded simultaneously.
1478
+ * When provided, `gtagId` is ignored.
1479
+ */
1480
+ gtagIds?: GtagEnvironmentMap;
1425
1481
  /**
1426
1482
  * Application tree that should have access to the scoped tracking client.
1427
1483
  */
package/dist/index.d.ts CHANGED
@@ -11,20 +11,6 @@ import { z } from 'zod';
11
11
  */
12
12
  declare function ConsentBanner(): react_jsx_runtime.JSX.Element | null;
13
13
 
14
- interface GoogleAdsTrackingProps {
15
- /**
16
- * Google Ads tag id, for example `AW-123456789`.
17
- */
18
- gtagId: string;
19
- }
20
- /**
21
- * Client component that loads Google Ads gtag and restores stored consent.
22
- *
23
- * Render once near the application root when the client site runs paid Google
24
- * Ads. The component renders nothing.
25
- */
26
- declare function GoogleAdsTracking({ gtagId }: GoogleAdsTrackingProps): null;
27
-
28
14
  /**
29
15
  * Visitor consent state stored by the SDK.
30
16
  *
@@ -62,6 +48,23 @@ interface TrackingParams {
62
48
  * whether a site uses the Next, React, or script-tag integration.
63
49
  */
64
50
  type TrackingInstallSurface = 'next' | 'react' | 'script';
51
+ /**
52
+ * Deployment environment label for event tagging.
53
+ *
54
+ * Used to stamp tracking events with the deployment context so the dashboard
55
+ * can distinguish production traffic from dev test traffic. The backend
56
+ * enforces this via a Postgres enum, so values are strictly one of
57
+ * `'production'` or `'development'`.
58
+ */
59
+ type TrackingEnvironment = 'production' | 'development';
60
+ /**
61
+ * Labelled map of Google Ads tag IDs.
62
+ *
63
+ * ALL entries are loaded simultaneously via `gtag('config', ...)` — the keys
64
+ * are human-readable labels (e.g. `production`, `test`) and the values are
65
+ * Google Ads tag IDs (e.g. `AW-123456789`).
66
+ */
67
+ type GtagEnvironmentMap = Record<string, string>;
65
68
  /**
66
69
  * Runtime context attached to tracking sessions and events.
67
70
  */
@@ -78,6 +81,10 @@ interface TrackingClientContext {
78
81
  page_title: string | null;
79
82
  /** Browser document referrer at client creation time. */
80
83
  referrer: string | null;
84
+ /** Deployment environment label, e.g. `'production'`, `'development'`. */
85
+ environment: TrackingEnvironment | null;
86
+ /** All active gtag IDs loaded on this page, keyed by label. */
87
+ active_gtag_ids: Record<string, string> | null;
81
88
  }
82
89
  /**
83
90
  * Session payload sent to `POST /tracking/events`.
@@ -127,6 +134,13 @@ interface TrackingInitConfig {
127
134
  endpoint?: string;
128
135
  /** Optional Google Ads tag id, for example `AW-123456789`. */
129
136
  gtagId?: string;
137
+ /**
138
+ * Labelled map of Google Ads tag IDs. ALL are loaded simultaneously.
139
+ * When provided, `gtagId` is ignored.
140
+ */
141
+ gtagIds?: GtagEnvironmentMap;
142
+ /** Deployment environment label reported in session context. */
143
+ environment?: TrackingEnvironment;
130
144
  /** Whether to capture attribution params from `window.location`. Defaults to true. */
131
145
  autoCaptureTrackingParams?: boolean;
132
146
  /** Whether the browser script should inject the default consent banner. */
@@ -174,6 +188,8 @@ interface TrackingContextInput {
174
188
  referrer?: string | null;
175
189
  sdkVersion?: string | null;
176
190
  siteOrigin?: string | null;
191
+ environment?: TrackingEnvironment | null;
192
+ activeGtagIds?: Record<string, string> | null;
177
193
  }
178
194
  interface TrackingEventInput {
179
195
  eventType: string;
@@ -275,6 +291,7 @@ declare const sdkHeartbeatMetadataSchema: z.ZodObject<{
275
291
  manual: string[];
276
292
  }>;
277
293
  trigger_config: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>>>>;
294
+ configured_gtag_ids: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodString>>>;
278
295
  }, "strict", z.ZodTypeAny, {
279
296
  sdk_version: string;
280
297
  package_name: string | null;
@@ -284,6 +301,7 @@ declare const sdkHeartbeatMetadataSchema: z.ZodObject<{
284
301
  manual: string[];
285
302
  };
286
303
  trigger_config?: Record<string, Record<string, unknown>> | null | undefined;
304
+ configured_gtag_ids?: Record<string, string> | null | undefined;
287
305
  }, {
288
306
  sdk_version: string;
289
307
  package_name: string | null;
@@ -293,6 +311,7 @@ declare const sdkHeartbeatMetadataSchema: z.ZodObject<{
293
311
  manual: string[];
294
312
  };
295
313
  trigger_config?: Record<string, Record<string, unknown>> | null | undefined;
314
+ configured_gtag_ids?: Record<string, string> | null | undefined;
296
315
  }>;
297
316
  type SdkHeartbeatMetadata = z.infer<typeof sdkHeartbeatMetadataSchema>;
298
317
  /**
@@ -1028,6 +1047,7 @@ declare const EVENT_REGISTRY: {
1028
1047
  manual: string[];
1029
1048
  }>;
1030
1049
  trigger_config: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>>>>;
1050
+ configured_gtag_ids: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodString>>>;
1031
1051
  }, "strict", z.ZodTypeAny, {
1032
1052
  sdk_version: string;
1033
1053
  package_name: string | null;
@@ -1037,6 +1057,7 @@ declare const EVENT_REGISTRY: {
1037
1057
  manual: string[];
1038
1058
  };
1039
1059
  trigger_config?: Record<string, Record<string, unknown>> | null | undefined;
1060
+ configured_gtag_ids?: Record<string, string> | null | undefined;
1040
1061
  }, {
1041
1062
  sdk_version: string;
1042
1063
  package_name: string | null;
@@ -1046,6 +1067,7 @@ declare const EVENT_REGISTRY: {
1046
1067
  manual: string[];
1047
1068
  };
1048
1069
  trigger_config?: Record<string, Record<string, unknown>> | null | undefined;
1070
+ configured_gtag_ids?: Record<string, string> | null | undefined;
1049
1071
  }>;
1050
1072
  readonly configSchema: z.ZodObject<{}, "strict", z.ZodTypeAny, {}, {}>;
1051
1073
  };
@@ -1370,6 +1392,27 @@ interface TypedTrackingClient<TRegistry extends TriggerRegistryConfig> {
1370
1392
  getVisitorId(): string;
1371
1393
  }
1372
1394
 
1395
+ /**
1396
+ * Props for the Google Ads tracking component.
1397
+ *
1398
+ * Accepts either a single `gtagId` (legacy) or a labelled `gtagIds` map
1399
+ * where ALL entries are loaded simultaneously via `gtag('config', ...)`.
1400
+ */
1401
+ type GoogleAdsTrackingProps = {
1402
+ gtagId: string;
1403
+ gtagIds?: undefined;
1404
+ } | {
1405
+ gtagId?: undefined;
1406
+ gtagIds: GtagEnvironmentMap;
1407
+ };
1408
+ /**
1409
+ * Client component that loads Google Ads gtag and restores stored consent.
1410
+ *
1411
+ * Render once near the application root when the client site runs paid Google
1412
+ * Ads. The component renders nothing.
1413
+ */
1414
+ declare function GoogleAdsTracking(props: GoogleAdsTrackingProps): null;
1415
+
1373
1416
  /**
1374
1417
  * Read the captured Google Ads click id from first-party cookies.
1375
1418
  *
@@ -1408,6 +1451,14 @@ interface CreateTrackingOptions<TRegistry extends TriggerRegistryConfig> {
1408
1451
  * `automatic.page_view` is required — every tracking install needs it.
1409
1452
  */
1410
1453
  triggers: TRegistry;
1454
+ /**
1455
+ * Deployment environment label reported in session context.
1456
+ *
1457
+ * Does not affect which gtag IDs are loaded — all configured IDs are
1458
+ * loaded simultaneously. This value is purely for event tagging so the
1459
+ * dashboard can filter by environment.
1460
+ */
1461
+ environment?: TrackingEnvironment;
1411
1462
  /**
1412
1463
  * When true, the typed client validates every `trackEvent()` metadata
1413
1464
  * payload through the Zod schema before forwarding. Errors are thrown
@@ -1419,9 +1470,14 @@ interface TrackingProviderProps {
1419
1470
  /**
1420
1471
  * Optional Google Ads tag id, for example `AW-123456789`.
1421
1472
  *
1422
- * If omitted, no gtag script is loaded by the provider.
1473
+ * If omitted and `gtagIds` is also omitted, no gtag script is loaded.
1423
1474
  */
1424
1475
  gtagId?: string;
1476
+ /**
1477
+ * Labelled map of Google Ads tag IDs. ALL are loaded simultaneously.
1478
+ * When provided, `gtagId` is ignored.
1479
+ */
1480
+ gtagIds?: GtagEnvironmentMap;
1425
1481
  /**
1426
1482
  * Application tree that should have access to the scoped tracking client.
1427
1483
  */
package/dist/index.js CHANGED
@@ -81,7 +81,9 @@ function createTrackingClientContext(surface, input = {}) {
81
81
  package_name: input.packageName ?? null,
82
82
  site_origin: input.siteOrigin ?? (typeof window === "undefined" ? null : window.location.origin),
83
83
  page_title: input.pageTitle ?? (typeof document === "undefined" ? null : document.title || null),
84
- referrer: input.referrer ?? (typeof document === "undefined" ? null : document.referrer || null)
84
+ referrer: input.referrer ?? (typeof document === "undefined" ? null : document.referrer || null),
85
+ environment: input.environment ?? null,
86
+ active_gtag_ids: input.activeGtagIds ?? null
85
87
  };
86
88
  }
87
89
  function createTrackingSessionUpsertPayload(trackingParams, input, context) {
@@ -118,6 +120,10 @@ var TRACKING_SCRIPT_ATTRIBUTE = "data-aranova-tracking";
118
120
  function getScriptMarker(id) {
119
121
  return `aranova-${id}`;
120
122
  }
123
+ var GTAG_ID_PATTERN = /^[A-Z]{1,3}-[A-Za-z0-9_-]+$/;
124
+ function isValidGtagId(id) {
125
+ return GTAG_ID_PATTERN.test(id);
126
+ }
121
127
  function ensureGtagFunction() {
122
128
  window.dataLayer = window.dataLayer || [];
123
129
  if (typeof window.gtag === "function")
@@ -158,11 +164,28 @@ function initializeGtag(gtagId) {
158
164
  function bootstrapGoogleAdsTracking(gtagId) {
159
165
  if (typeof window === "undefined" || typeof document === "undefined")
160
166
  return;
167
+ if (!isValidGtagId(gtagId))
168
+ return;
161
169
  applyDefaultConsentState();
162
170
  loadGtagScript(gtagId);
163
171
  initializeGtag(gtagId);
164
172
  restoreStoredConsent();
165
173
  }
174
+ function bootstrapMultipleGtags(gtagIds) {
175
+ if (typeof window === "undefined" || typeof document === "undefined")
176
+ return;
177
+ const ids = Object.values(gtagIds).filter(isValidGtagId);
178
+ if (ids.length === 0)
179
+ return;
180
+ applyDefaultConsentState();
181
+ loadGtagScript(ids[0]);
182
+ const gtag = ensureGtagFunction();
183
+ gtag("js", /* @__PURE__ */ new Date());
184
+ for (const id of ids) {
185
+ gtag("config", id);
186
+ }
187
+ restoreStoredConsent();
188
+ }
166
189
 
167
190
  // ../tracking-core/src/tracking.ts
168
191
  var TRACKING_COOKIE_MAX_AGE_SECONDS = 7776e3;
@@ -437,7 +460,7 @@ function serializeValue(value) {
437
460
  }
438
461
  return value;
439
462
  }
440
- function buildHeartbeatMetadata(surface, sdkVersion, packageName, triggers) {
463
+ function buildHeartbeatMetadata(surface, sdkVersion, packageName, triggers, gtagIds = null) {
441
464
  const automaticNames = triggers ? Object.keys(triggers.automatic) : [];
442
465
  const manualNames = triggers?.manual ? Object.keys(triggers.manual) : [];
443
466
  let triggerConfig = null;
@@ -470,7 +493,8 @@ function buildHeartbeatMetadata(surface, sdkVersion, packageName, triggers) {
470
493
  automatic: automaticNames,
471
494
  manual: manualNames
472
495
  },
473
- trigger_config: triggerConfig
496
+ trigger_config: triggerConfig,
497
+ configured_gtag_ids: gtagIds
474
498
  };
475
499
  }
476
500
 
@@ -479,14 +503,16 @@ var DEFAULT_FLUSH_INTERVAL_MS = 2e3;
479
503
  var DEFAULT_MAX_QUEUE_SIZE = 10;
480
504
  var HARD_MAX_BATCH = 50;
481
505
  var API_KEY_HEADER = "X-Aranova-Api-Key";
482
- function buildContext(surface, sdkVersion, packageName) {
506
+ function buildContext(surface, sdkVersion, packageName, environment, activeGtagIds) {
483
507
  return {
484
508
  surface,
485
509
  sdk_version: sdkVersion,
486
510
  package_name: packageName,
487
511
  site_origin: typeof window === "undefined" ? null : window.location.origin,
488
512
  page_title: typeof document === "undefined" ? null : document.title || null,
489
- referrer: typeof document === "undefined" ? null : document.referrer || null
513
+ referrer: typeof document === "undefined" ? null : document.referrer || null,
514
+ environment,
515
+ active_gtag_ids: activeGtagIds
490
516
  };
491
517
  }
492
518
  function readTrackingParams() {
@@ -546,6 +572,8 @@ function createTrackingClient(config) {
546
572
  const maxQueueSize = Math.min(config.maxQueueSize ?? DEFAULT_MAX_QUEUE_SIZE, HARD_MAX_BATCH);
547
573
  const sdkVersion = config.sdkVersion ?? null;
548
574
  const packageName = config.packageName ?? null;
575
+ const environment = config.environment ?? null;
576
+ const activeGtagIds = config.activeGtagIds ?? null;
549
577
  const endpointBase = config.endpoint.replace(/\/$/, "");
550
578
  const eventsUrl = `${endpointBase}/events`;
551
579
  let queue = [];
@@ -562,7 +590,8 @@ function createTrackingClient(config) {
562
590
  config.surface,
563
591
  sdkVersion,
564
592
  packageName,
565
- config.triggers ?? null
593
+ config.triggers ?? null,
594
+ activeGtagIds
566
595
  );
567
596
  queue.push({
568
597
  event_type: "sdk_heartbeat",
@@ -581,7 +610,7 @@ function createTrackingClient(config) {
581
610
  }
582
611
  sessionId = rotated.id;
583
612
  const params = readTrackingParams();
584
- const context = buildContext(config.surface, sdkVersion, packageName);
613
+ const context = buildContext(config.surface, sdkVersion, packageName, environment, activeGtagIds);
585
614
  return {
586
615
  session_id: sessionId,
587
616
  visitor_id: visitorId,
@@ -703,7 +732,8 @@ var sdkHeartbeatMetadataSchema = import_zod3.z.object({
703
732
  package_name: import_zod3.z.string().nullable(),
704
733
  surface: import_zod3.z.enum(["next", "react", "script"]),
705
734
  triggers: sdkHeartbeatTriggersSchema,
706
- trigger_config: import_zod3.z.record(import_zod3.z.string(), import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown())).nullable().optional()
735
+ trigger_config: import_zod3.z.record(import_zod3.z.string(), import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown())).nullable().optional(),
736
+ configured_gtag_ids: import_zod3.z.record(import_zod3.z.string(), import_zod3.z.string()).nullable().optional()
707
737
  }).strict();
708
738
  var sdkHeartbeatConfigSchema = import_zod3.z.object({}).strict();
709
739
 
@@ -1293,10 +1323,19 @@ function ConsentBanner() {
1293
1323
 
1294
1324
  // src/GoogleAdsTracking.tsx
1295
1325
  var import_react2 = require("react");
1296
- function GoogleAdsTracking({ gtagId }) {
1326
+ function GoogleAdsTracking(props) {
1327
+ const { gtagId, gtagIds } = props;
1328
+ const gtagIdsKey = (0, import_react2.useMemo)(
1329
+ () => gtagIds ? JSON.stringify(gtagIds) : "",
1330
+ [gtagIds]
1331
+ );
1297
1332
  (0, import_react2.useEffect)(() => {
1298
- bootstrapGoogleAdsTracking(gtagId);
1299
- }, [gtagId]);
1333
+ if (gtagIds && Object.keys(gtagIds).length > 0) {
1334
+ bootstrapMultipleGtags(gtagIds);
1335
+ } else if (gtagId) {
1336
+ bootstrapGoogleAdsTracking(gtagId);
1337
+ }
1338
+ }, [gtagId, gtagIdsKey]);
1300
1339
  return null;
1301
1340
  }
1302
1341
 
@@ -1336,7 +1375,7 @@ function useConsentState() {
1336
1375
  var import_react4 = require("react");
1337
1376
 
1338
1377
  // package.json
1339
- var version = "0.6.1";
1378
+ var version = "0.7.0";
1340
1379
 
1341
1380
  // src/factory.tsx
1342
1381
  var import_jsx_runtime2 = require("react/jsx-runtime");
@@ -1349,7 +1388,7 @@ var NOOP_CLIENT = {
1349
1388
  getVisitorId: () => ""
1350
1389
  };
1351
1390
  function createTracking(options) {
1352
- const { apiKey, endpoint, triggers, debug } = options;
1391
+ const { apiKey, endpoint, triggers, environment, debug } = options;
1353
1392
  if (!apiKey || !endpoint) {
1354
1393
  if (apiKey || endpoint) {
1355
1394
  console.warn(
@@ -1363,7 +1402,8 @@ function createTracking(options) {
1363
1402
  };
1364
1403
  }
1365
1404
  const TrackingContext = (0, import_react4.createContext)(null);
1366
- function TrackingProvider({ gtagId, children }) {
1405
+ function TrackingProvider({ gtagId, gtagIds, children }) {
1406
+ const resolvedGtagIds = gtagIds ?? (gtagId ? { default: gtagId } : void 0);
1367
1407
  const client = (0, import_react4.useMemo)(
1368
1408
  () => createTypedClient(
1369
1409
  getOrCreateTrackingClient({
@@ -1373,6 +1413,8 @@ function createTracking(options) {
1373
1413
  packageName: "@aranova/tracking-react",
1374
1414
  sdkVersion: version,
1375
1415
  triggers,
1416
+ environment,
1417
+ activeGtagIds: resolvedGtagIds,
1376
1418
  debug
1377
1419
  }),
1378
1420
  triggers,
@@ -1380,10 +1422,14 @@ function createTracking(options) {
1380
1422
  ),
1381
1423
  []
1382
1424
  );
1425
+ const gtagIdsKey = (0, import_react4.useMemo)(() => gtagIds ? JSON.stringify(gtagIds) : "", [gtagIds]);
1383
1426
  (0, import_react4.useEffect)(() => {
1384
- if (!gtagId) return;
1385
- bootstrapGoogleAdsTracking(gtagId);
1386
- }, [gtagId]);
1427
+ if (gtagIds && Object.keys(gtagIds).length > 0) {
1428
+ bootstrapMultipleGtags(gtagIds);
1429
+ } else if (gtagId) {
1430
+ bootstrapGoogleAdsTracking(gtagId);
1431
+ }
1432
+ }, [gtagId, gtagIdsKey]);
1387
1433
  (0, import_react4.useEffect)(() => {
1388
1434
  const detachers = [];
1389
1435
  const rawClient = getOrCreateTrackingClient({
@@ -1392,6 +1438,8 @@ function createTracking(options) {
1392
1438
  surface: "react",
1393
1439
  packageName: "@aranova/tracking-react",
1394
1440
  triggers,
1441
+ environment,
1442
+ activeGtagIds: resolvedGtagIds,
1395
1443
  debug
1396
1444
  });
1397
1445
  detachers.push(attachAutoPageView(rawClient));