@walkeros/web-destination-gtag 0.0.0-next-20251219153324

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 ADDED
@@ -0,0 +1,314 @@
1
+ # Google Gtag Destination for walkerOS
2
+
3
+ [Source Code](https://github.com/elbwalker/walkerOS/tree/main/packages/web/destinations/gtag)
4
+ •
5
+ [NPM Package](https://www.npmjs.com/package/@walkeros/web-destination-gtag)
6
+
7
+ The Google Gtag destination provides a unified interface for sending events to
8
+ Google Analytics 4 (GA4), Google Ads, and Google Tag Manager (GTM) through a
9
+ single destination configuration.
10
+
11
+ ## Features
12
+
13
+ - **Unified Configuration**: Configure GA4, Google Ads, and GTM in a single
14
+ destination
15
+ - **Shared Script Loading**: Efficient gtag script loading shared across all
16
+ Google tools
17
+ - **Tool-Specific Mappings**: Individual mapping configurations for each Google
18
+ tool
19
+ - **TypeScript Support**: Full type safety with strict typing
20
+ - **Flexible Usage**: Use one, two, or all three Google tools as needed
21
+
22
+ ## Installation
23
+
24
+ ```bash
25
+ npm install @walkeros/web-destination-gtag
26
+ ```
27
+
28
+ ## Quick Start
29
+
30
+ Configure in your Flow JSON:
31
+
32
+ ```json
33
+ {
34
+ "version": 1,
35
+ "flows": {
36
+ "default": {
37
+ "web": {},
38
+ "destinations": {
39
+ "gtag": {
40
+ "package": "@walkeros/web-destination-gtag",
41
+ "config": {
42
+ "settings": {
43
+ "ga4": { "measurementId": "G-XXXXXXXXXX" },
44
+ "ads": { "conversionId": "AW-XXXXXXXXX" },
45
+ "gtm": { "containerId": "GTM-XXXXXXX" }
46
+ }
47
+ }
48
+ }
49
+ }
50
+ }
51
+ }
52
+ }
53
+ ```
54
+
55
+ Or programmatically:
56
+
57
+ ```typescript
58
+ import { startFlow } from '@walkeros/collector';
59
+ import { destinationGtag } from '@walkeros/web-destination-gtag';
60
+
61
+ const { elb } = await startFlow({
62
+ destinations: [
63
+ {
64
+ destination: destinationGtag,
65
+ config: {
66
+ settings: {
67
+ ga4: { measurementId: 'G-XXXXXXXXXX' },
68
+ ads: { conversionId: 'AW-XXXXXXXXX' },
69
+ gtm: { containerId: 'GTM-XXXXXXX' },
70
+ },
71
+ },
72
+ },
73
+ ],
74
+ });
75
+ ```
76
+
77
+ ## Configuration
78
+
79
+ | Name | Type | Description | Required | Example |
80
+ | ----- | ------------- | -------------------------------------------------- | -------- | ----------------------------------- |
81
+ | `ga4` | `GA4Settings` | GA4-specific configuration settings | No | `{ measurementId: 'G-XXXXXXXXXX' }` |
82
+ | `ads` | `AdsSettings` | Google Ads specific configuration settings | No | `{ conversionId: 'AW-XXXXXXXXX' }` |
83
+ | `gtm` | `GTMSettings` | Google Tag Manager specific configuration settings | No | `{ containerId: 'GTM-XXXXXXX' }` |
84
+
85
+ ### Event Mapping
86
+
87
+ For custom event mapping (`mapping.entity.action.settings`):
88
+
89
+ | Name | Type | Description | Required | Example |
90
+ | ----- | ------------ | ----------------------------------------------- | -------- | ---------------------------------- |
91
+ | `ga4` | `GA4Mapping` | GA4-specific event mapping configuration | No | `{ include: ['data', 'context'] }` |
92
+ | `ads` | `AdsMapping` | Google Ads specific event mapping configuration | No | `{ label: 'conversion_label' }` |
93
+ | `gtm` | `GTMMapping` | GTM specific event mapping configuration | No | `{}` |
94
+
95
+ ## Consent Mode
96
+
97
+ The gtag destination automatically handles Google Consent Mode v2 with a "deny
98
+ by default" approach. Configure consent mode using the `como` setting:
99
+
100
+ ```typescript
101
+ import { destinationGtag } from '@walkeros/web-destination-gtag';
102
+
103
+ const destination = destinationGtag({
104
+ settings: {
105
+ como: true, // Enable with default mapping
106
+ ga4: { measurementId: 'G-XXXXXXXXXX' },
107
+ },
108
+ });
109
+ ```
110
+
111
+ ### Configuration Options
112
+
113
+ | Value | Description | Default Mapping |
114
+ | -------- | -------------------- | ------------------------------------------------------------------------------------------------------ |
115
+ | `false` | Disable consent mode | - |
116
+ | `true` | Use default mapping | `marketing` → `ad_storage`, `ad_user_data`, `ad_personalization`<br>`functional` → `analytics_storage` |
117
+ | `object` | Custom mapping | `{ [walkerOSGroup]: gtagParameter \| gtagParameter[] }` |
118
+
119
+ ### Custom Mapping
120
+
121
+ ```typescript
122
+ const destination = destinationGtag({
123
+ settings: {
124
+ como: {
125
+ marketing: ['ad_storage', 'ad_personalization'],
126
+ analytics: 'analytics_storage',
127
+ },
128
+ ga4: { measurementId: 'G-XXXXXXXXXX' },
129
+ },
130
+ });
131
+ ```
132
+
133
+ ### Usage
134
+
135
+ Consent mode automatically activates when you send consent events through
136
+ walkerOS:
137
+
138
+ ```typescript
139
+ // Grant consent
140
+ elb('walker consent', { marketing: true, functional: true });
141
+
142
+ // Deny consent
143
+ elb('walker consent', { marketing: false, functional: false });
144
+ ```
145
+
146
+ The destination handles all gtag consent calls automatically, ensuring
147
+ compliance with privacy regulations.
148
+
149
+ ## Examples
150
+
151
+ ### E-commerce Purchase
152
+
153
+ ```typescript
154
+ import { destinationGtag } from '@walkeros/web-destination-gtag';
155
+
156
+ const destination = destinationGtag({
157
+ settings: {
158
+ ga4: { measurementId: 'G-XXXXXXXXXX' },
159
+ ads: { conversionId: 'AW-XXXXXXXXX' },
160
+ },
161
+ mapping: {
162
+ order: {
163
+ complete: {
164
+ name: 'purchase',
165
+ settings: {
166
+ ga4: { include: ['data'] },
167
+ ads: {
168
+ label: 'PURCHASE_LABEL', // Specify conversion label
169
+ },
170
+ },
171
+ data: {
172
+ map: {
173
+ transaction_id: 'data.id',
174
+ value: 'data.total',
175
+ currency: 'data.currency',
176
+ items: {
177
+ loop: [
178
+ 'nested',
179
+ {
180
+ condition: (entity) => entity.entity === 'product',
181
+ map: {
182
+ item_id: 'data.id',
183
+ item_name: 'data.name',
184
+ quantity: 'data.quantity',
185
+ },
186
+ },
187
+ ],
188
+ },
189
+ },
190
+ },
191
+ },
192
+ },
193
+ },
194
+ });
195
+ ```
196
+
197
+ ### Custom Event with All Tools
198
+
199
+ ```typescript
200
+ const customEventMapping = {
201
+ product: {
202
+ view: {
203
+ name: 'view_item',
204
+ settings: {
205
+ ga4: { include: ['data', 'context'] },
206
+ ads: {}, // No conversion tracking for product views
207
+ gtm: {}, // Send to GTM dataLayer
208
+ },
209
+ data: {
210
+ map: {
211
+ item_id: 'data.id',
212
+ item_name: 'data.name',
213
+ item_category: 'data.category',
214
+ value: 'data.price',
215
+ currency: 'data.currency',
216
+ },
217
+ },
218
+ },
219
+ },
220
+ };
221
+ ```
222
+
223
+ ## TypeScript
224
+
225
+ Full TypeScript support with strict typing:
226
+
227
+ ```typescript
228
+ import type { DestinationGtag } from '@walkeros/web-destination-gtag';
229
+
230
+ // Type-safe configuration
231
+ const config: DestinationGtag.Config = {
232
+ settings: {
233
+ ga4: {
234
+ measurementId: 'G-XXXXXXXXXX',
235
+ debug: true,
236
+ },
237
+ },
238
+ };
239
+
240
+ // Type-safe mapping rules
241
+ const rules: DestinationGtag.Rules = {
242
+ order: {
243
+ complete: {
244
+ name: 'purchase',
245
+ settings: {
246
+ ga4: { include: ['data'] },
247
+ },
248
+ data: {
249
+ map: {
250
+ transaction_id: 'data.id',
251
+ value: 'data.total',
252
+ },
253
+ },
254
+ },
255
+ },
256
+ };
257
+ ```
258
+
259
+ ## Best Practices
260
+
261
+ 1. **Use Combined Configuration**: When using multiple Google tools, configure
262
+ them in a single destination for better performance and maintenance.
263
+
264
+ 2. **Tool-Specific Mappings**: Use tool-specific mapping settings to customize
265
+ behavior for each Google product.
266
+
267
+ 3. **Conversion Labels**: For Google Ads, use descriptive conversion labels in
268
+ the mapping `name` field.
269
+
270
+ 4. **Data Inclusion**: Use GA4's `include` setting to control which data groups
271
+ are sent to minimize payload size.
272
+
273
+ 5. **Debug Mode**: Enable GA4 debug mode during development to verify event
274
+ tracking.
275
+
276
+ ## Troubleshooting
277
+
278
+ **Events not appearing in GA4:**
279
+
280
+ - Verify the measurement ID is correct
281
+ - Check that events are being triggered
282
+ - Enable debug mode to see events in GA4 DebugView
283
+
284
+ **Google Ads conversions not tracking:**
285
+
286
+ - Ensure conversion ID and labels are correctly configured
287
+ - Verify the `settings.ads.label` field contains the correct conversion label
288
+ - Check that the conversion action is set up in Google Ads
289
+
290
+ **GTM events not appearing:**
291
+
292
+ - Verify the container ID is correct
293
+ - Check the dataLayer name matches your GTM configuration
294
+ - Use GTM Preview mode to debug event flow
295
+
296
+ ## Type Definitions
297
+
298
+ See [src/types/](./src/types/) for TypeScript interfaces.
299
+
300
+ ## Related
301
+
302
+ - [Website Documentation](https://www.walkeros.io/docs/destinations/web/gtag/)
303
+ - [Destination Interface](../../../core/src/types/destination.ts)
304
+
305
+ ## Contribute
306
+
307
+ Feel free to contribute by submitting an
308
+ [issue](https://github.com/elbwalker/walkerOS/issues), starting a
309
+ [discussion](https://github.com/elbwalker/walkerOS/discussions), or getting in
310
+ [contact](https://calendly.com/elb-alexander/30min).
311
+
312
+ ## License
313
+
314
+ MIT
package/dist/dev.d.mts ADDED
@@ -0,0 +1,240 @@
1
+ import * as _walkeros_core_dev from '@walkeros/core/dev';
2
+ import { z } from '@walkeros/core/dev';
3
+ import { Mapping as Mapping$2 } from '@walkeros/core';
4
+ import { DestinationWeb } from '@walkeros/web-core';
5
+
6
+ /**
7
+ * Include configuration for GA4
8
+ * Specifies which event properties to include
9
+ */
10
+ declare const IncludeSchema: z.ZodArray<z.ZodEnum<{
11
+ all: "all";
12
+ context: "context";
13
+ data: "data";
14
+ event: "event";
15
+ globals: "globals";
16
+ source: "source";
17
+ user: "user";
18
+ version: "version";
19
+ }>>;
20
+ /**
21
+ * Consent Mode Configuration
22
+ * Can be false (disabled), true (use defaults), or custom mapping
23
+ */
24
+ declare const ConsentModeSchema: z.ZodUnion<readonly [z.ZodBoolean, z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>]>;
25
+ declare const GA4SettingsSchema: z.ZodObject<{
26
+ measurementId: z.ZodString;
27
+ debug: z.ZodOptional<z.ZodBoolean>;
28
+ include: z.ZodOptional<z.ZodArray<z.ZodEnum<{
29
+ all: "all";
30
+ context: "context";
31
+ data: "data";
32
+ event: "event";
33
+ globals: "globals";
34
+ source: "source";
35
+ user: "user";
36
+ version: "version";
37
+ }>>>;
38
+ pageview: z.ZodOptional<z.ZodBoolean>;
39
+ server_container_url: z.ZodOptional<z.ZodString>;
40
+ snakeCase: z.ZodOptional<z.ZodBoolean>;
41
+ transport_url: z.ZodOptional<z.ZodString>;
42
+ data: z.ZodOptional<z.ZodAny>;
43
+ }, z.core.$strip>;
44
+ /**
45
+ * Google Ads Settings Schema
46
+ * Configuration for Google Ads conversions
47
+ */
48
+ declare const AdsSettingsSchema: z.ZodObject<{
49
+ conversionId: z.ZodString;
50
+ currency: z.ZodOptional<z.ZodString>;
51
+ data: z.ZodOptional<z.ZodAny>;
52
+ }, z.core.$strip>;
53
+ /**
54
+ * GTM Settings Schema
55
+ * Configuration for Google Tag Manager
56
+ */
57
+ declare const GTMSettingsSchema: z.ZodObject<{
58
+ containerId: z.ZodString;
59
+ dataLayer: z.ZodOptional<z.ZodString>;
60
+ domain: z.ZodOptional<z.ZodString>;
61
+ data: z.ZodOptional<z.ZodAny>;
62
+ }, z.core.$strip>;
63
+
64
+ declare const SettingsSchema: z.ZodObject<{
65
+ como: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>]>>;
66
+ ga4: z.ZodOptional<z.ZodObject<{
67
+ measurementId: z.ZodString;
68
+ debug: z.ZodOptional<z.ZodBoolean>;
69
+ include: z.ZodOptional<z.ZodArray<z.ZodEnum<{
70
+ all: "all";
71
+ context: "context";
72
+ data: "data";
73
+ event: "event";
74
+ globals: "globals";
75
+ source: "source";
76
+ user: "user";
77
+ version: "version";
78
+ }>>>;
79
+ pageview: z.ZodOptional<z.ZodBoolean>;
80
+ server_container_url: z.ZodOptional<z.ZodString>;
81
+ snakeCase: z.ZodOptional<z.ZodBoolean>;
82
+ transport_url: z.ZodOptional<z.ZodString>;
83
+ data: z.ZodOptional<z.ZodAny>;
84
+ }, z.core.$strip>>;
85
+ ads: z.ZodOptional<z.ZodObject<{
86
+ conversionId: z.ZodString;
87
+ currency: z.ZodOptional<z.ZodString>;
88
+ data: z.ZodOptional<z.ZodAny>;
89
+ }, z.core.$strip>>;
90
+ gtm: z.ZodOptional<z.ZodObject<{
91
+ containerId: z.ZodString;
92
+ dataLayer: z.ZodOptional<z.ZodString>;
93
+ domain: z.ZodOptional<z.ZodString>;
94
+ data: z.ZodOptional<z.ZodAny>;
95
+ }, z.core.$strip>>;
96
+ }, z.core.$strip>;
97
+ type Settings = z.infer<typeof SettingsSchema>;
98
+
99
+ /**
100
+ * Gtag Mapping Schema
101
+ * Tool-specific event-level mappings
102
+ */
103
+ declare const MappingSchema: z.ZodObject<{
104
+ ga4: z.ZodOptional<z.ZodObject<{
105
+ include: z.ZodOptional<z.ZodArray<z.ZodEnum<{
106
+ all: "all";
107
+ context: "context";
108
+ data: "data";
109
+ event: "event";
110
+ globals: "globals";
111
+ source: "source";
112
+ user: "user";
113
+ version: "version";
114
+ }>>>;
115
+ }, z.core.$strip>>;
116
+ ads: z.ZodOptional<z.ZodObject<{
117
+ label: z.ZodOptional<z.ZodString>;
118
+ }, z.core.$strip>>;
119
+ gtm: z.ZodOptional<z.ZodObject<{}, z.core.$strip>>;
120
+ }, z.core.$strip>;
121
+ /**
122
+ * Type inference from MappingSchema
123
+ */
124
+ type Mapping$1 = z.infer<typeof MappingSchema>;
125
+
126
+ declare const settings: _walkeros_core_dev.JSONSchema;
127
+ declare const mapping$1: _walkeros_core_dev.JSONSchema;
128
+ declare const ga4: _walkeros_core_dev.JSONSchema;
129
+ declare const ads: _walkeros_core_dev.JSONSchema;
130
+ declare const gtm: _walkeros_core_dev.JSONSchema;
131
+
132
+ declare const index$1_AdsSettingsSchema: typeof AdsSettingsSchema;
133
+ declare const index$1_ConsentModeSchema: typeof ConsentModeSchema;
134
+ declare const index$1_GA4SettingsSchema: typeof GA4SettingsSchema;
135
+ declare const index$1_GTMSettingsSchema: typeof GTMSettingsSchema;
136
+ declare const index$1_IncludeSchema: typeof IncludeSchema;
137
+ declare const index$1_MappingSchema: typeof MappingSchema;
138
+ type index$1_Settings = Settings;
139
+ declare const index$1_SettingsSchema: typeof SettingsSchema;
140
+ declare const index$1_ads: typeof ads;
141
+ declare const index$1_ga4: typeof ga4;
142
+ declare const index$1_gtm: typeof gtm;
143
+ declare const index$1_settings: typeof settings;
144
+ declare namespace index$1 {
145
+ export { index$1_AdsSettingsSchema as AdsSettingsSchema, index$1_ConsentModeSchema as ConsentModeSchema, index$1_GA4SettingsSchema as GA4SettingsSchema, index$1_GTMSettingsSchema as GTMSettingsSchema, index$1_IncludeSchema as IncludeSchema, type Mapping$1 as Mapping, index$1_MappingSchema as MappingSchema, type index$1_Settings as Settings, index$1_SettingsSchema as SettingsSchema, index$1_ads as ads, index$1_ga4 as ga4, index$1_gtm as gtm, mapping$1 as mapping, index$1_settings as settings };
146
+ }
147
+
148
+ declare global {
149
+ interface Window {
150
+ gtag?: Gtag.Gtag;
151
+ [key: string]: unknown;
152
+ }
153
+ }
154
+ interface Env extends DestinationWeb.Env {
155
+ window: {
156
+ gtag: Gtag.Gtag;
157
+ dataLayer: unknown[];
158
+ };
159
+ document: {
160
+ createElement: (tagName: string) => {
161
+ src: string;
162
+ async?: boolean;
163
+ setAttribute: (name: string, value: string) => void;
164
+ removeAttribute: (name: string) => void;
165
+ };
166
+ head: {
167
+ appendChild: (node: unknown) => void;
168
+ };
169
+ };
170
+ }
171
+ interface AdsMapping {
172
+ label?: string;
173
+ }
174
+ interface Mapping {
175
+ ga4?: GA4Mapping;
176
+ ads?: AdsMapping;
177
+ gtm?: GTMMapping;
178
+ }
179
+ interface GA4Mapping {
180
+ include?: Include;
181
+ }
182
+ interface GTMMapping {
183
+ }
184
+ type Rule = Mapping$2.Rule<Mapping>;
185
+ type Include = Array<'all' | 'context' | 'data' | 'event' | 'globals' | 'source' | 'user' | 'version'>;
186
+
187
+ declare const init: Env | undefined;
188
+ declare const push: Env;
189
+ declare const simulation: string[];
190
+
191
+ declare const env_init: typeof init;
192
+ declare const env_push: typeof push;
193
+ declare const env_simulation: typeof simulation;
194
+ declare namespace env {
195
+ export { env_init as init, env_push as push, env_simulation as simulation };
196
+ }
197
+
198
+ declare function ga4Purchase$1(): unknown[];
199
+ declare function ga4AddToCart$1(): unknown[];
200
+ declare function adsConversion$1(): unknown[];
201
+ declare function gtmEvent(): Record<string, unknown>;
202
+
203
+ declare const events_gtmEvent: typeof gtmEvent;
204
+ declare namespace events {
205
+ export { adsConversion$1 as adsConversion, ga4AddToCart$1 as ga4AddToCart, ga4Purchase$1 as ga4Purchase, events_gtmEvent as gtmEvent };
206
+ }
207
+
208
+ declare const ga4Purchase: Rule;
209
+ declare const ga4AddToCart: Rule;
210
+ declare const adsConversion: Rule;
211
+ declare const gtmProductView: Rule;
212
+ declare const combinedPurchase: Rule;
213
+ declare const config: {
214
+ order: {
215
+ complete: Rule;
216
+ };
217
+ product: {
218
+ add: Rule;
219
+ view: Rule;
220
+ };
221
+ };
222
+
223
+ declare const mapping_adsConversion: typeof adsConversion;
224
+ declare const mapping_combinedPurchase: typeof combinedPurchase;
225
+ declare const mapping_config: typeof config;
226
+ declare const mapping_ga4AddToCart: typeof ga4AddToCart;
227
+ declare const mapping_ga4Purchase: typeof ga4Purchase;
228
+ declare const mapping_gtmProductView: typeof gtmProductView;
229
+ declare namespace mapping {
230
+ export { mapping_adsConversion as adsConversion, mapping_combinedPurchase as combinedPurchase, mapping_config as config, mapping_ga4AddToCart as ga4AddToCart, mapping_ga4Purchase as ga4Purchase, mapping_gtmProductView as gtmProductView };
231
+ }
232
+
233
+ declare const index_env: typeof env;
234
+ declare const index_events: typeof events;
235
+ declare const index_mapping: typeof mapping;
236
+ declare namespace index {
237
+ export { index_env as env, index_events as events, index_mapping as mapping };
238
+ }
239
+
240
+ export { index as examples, index$1 as schemas };