@walkeros/transformer-ga4 4.1.0-next-1778668930820
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 +181 -0
- package/dist/dev.d.mts +190 -0
- package/dist/dev.d.ts +190 -0
- package/dist/dev.js +1 -0
- package/dist/dev.js.map +1 -0
- package/dist/dev.mjs +1 -0
- package/dist/dev.mjs.map +1 -0
- package/dist/index.d.mts +143 -0
- package/dist/index.d.ts +143 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1 -0
- package/dist/index.mjs.map +1 -0
- package/dist/walkerOS.json +436 -0
- package/package.json +67 -0
package/README.md
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# @walkeros/transformer-ga4
|
|
2
|
+
|
|
3
|
+
Decode Google Analytics 4 Measurement Protocol v2 hits into walkerOS events.
|
|
4
|
+
|
|
5
|
+
[Source Code](https://github.com/elbwalker/walkerOS/tree/main/packages/transformers/ga4)
|
|
6
|
+
| [NPM](https://www.npmjs.com/package/@walkeros/transformer-ga4) |
|
|
7
|
+
[Documentation](https://www.walkeros.io/docs/transformers/ga4)
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @walkeros/transformer-ga4
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Wire it up
|
|
16
|
+
|
|
17
|
+
`transformer-ga4` is a `source.before` transformer. Drop it in front of any
|
|
18
|
+
server source that delivers the raw HTTP request to `ingest`:
|
|
19
|
+
|
|
20
|
+
```json
|
|
21
|
+
{
|
|
22
|
+
"version": 4,
|
|
23
|
+
"flows": {
|
|
24
|
+
"default": {
|
|
25
|
+
"config": { "platform": "server" },
|
|
26
|
+
"sources": {
|
|
27
|
+
"http": {
|
|
28
|
+
"package": "@walkeros/server-source-express",
|
|
29
|
+
"config": {
|
|
30
|
+
"ingest": {
|
|
31
|
+
"url": "req.url",
|
|
32
|
+
"body": "req.body"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"before": "ga4"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"transformers": {
|
|
39
|
+
"ga4": { "package": "@walkeros/transformer-ga4" }
|
|
40
|
+
},
|
|
41
|
+
"destinations": {
|
|
42
|
+
"log": { "package": "@walkeros/destination-demo" }
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The transformer reads two keys from `ctx.ingest`:
|
|
50
|
+
|
|
51
|
+
| Key | Type | Required | Notes |
|
|
52
|
+
| ------ | -------- | -------- | ---------------------------------------------------- |
|
|
53
|
+
| `url` | `string` | yes | Full request URL including the query string. |
|
|
54
|
+
| `body` | `string` | no | Raw POST body. Multi-event lines are `\n`-separated. |
|
|
55
|
+
|
|
56
|
+
If `url` is missing or not a string, the transformer drops the event silently.
|
|
57
|
+
|
|
58
|
+
## Default mappings
|
|
59
|
+
|
|
60
|
+
Out of the box, ~30 standard GA4 event names map to walkerOS event names:
|
|
61
|
+
|
|
62
|
+
| GA4 (`en`) | walkerOS (`name`) | Notes |
|
|
63
|
+
| ------------------- | ----------------- | -------------------------------------- |
|
|
64
|
+
| `page_view` | `page view` | `id`, `title`, `referrer` from hit |
|
|
65
|
+
| `purchase` | `order complete` | id, currency, total, tax, shipping |
|
|
66
|
+
| `view_item` | `product view` | currency, value |
|
|
67
|
+
| `add_to_cart` | `product add` | currency, value |
|
|
68
|
+
| `remove_from_cart` | `product remove` | currency, value |
|
|
69
|
+
| `view_cart` | `cart view` | currency, value |
|
|
70
|
+
| `begin_checkout` | `order start` | currency, value, coupon |
|
|
71
|
+
| `add_shipping_info` | `order shipping` | currency, value, tier |
|
|
72
|
+
| `add_payment_info` | `order payment` | currency, value, type |
|
|
73
|
+
| `refund` | `order refund` | id, currency, total |
|
|
74
|
+
| `add_to_wishlist` | `wishlist add` | currency, value |
|
|
75
|
+
| `view_item_list` | `list view` | id, name |
|
|
76
|
+
| `select_item` | `product click` | list_id, list_name |
|
|
77
|
+
| `view_promotion` | `promotion view` | reads from `items[0]` |
|
|
78
|
+
| `select_promotion` | `promotion click` | reads from `items[0]` |
|
|
79
|
+
| `select_content` | `content select` | type, id |
|
|
80
|
+
| `scroll` | `page scroll` | percent |
|
|
81
|
+
| `click` | `link click` | url, domain, outbound |
|
|
82
|
+
| `file_download` | `file download` | name, extension, url |
|
|
83
|
+
| `video_start` | `video start` | title, duration, current, percent |
|
|
84
|
+
| `video_progress` | `video progress` | same as video_start |
|
|
85
|
+
| `video_complete` | `video complete` | same as video_start |
|
|
86
|
+
| `form_start` | `form start` | id, name, destination |
|
|
87
|
+
| `form_submit` | `form submit` | id, name, destination |
|
|
88
|
+
| `search` | `search submit` | term |
|
|
89
|
+
| `login` | `session login` | method |
|
|
90
|
+
| `sign_up` | `session signup` | method |
|
|
91
|
+
| `generate_lead` | `lead generate` | currency, value |
|
|
92
|
+
| `share` | `content share` | method, type, id |
|
|
93
|
+
| `user_engagement` | (dropped) | `ignore: true` by default |
|
|
94
|
+
| `session_start` | (dropped) | `ignore: true` by default |
|
|
95
|
+
| `first_visit` | (dropped) | `ignore: true` by default |
|
|
96
|
+
| `*` (fallback) | `ga4 track` | `event_name` carries the original `en` |
|
|
97
|
+
|
|
98
|
+
See the [website docs](https://www.walkeros.io/docs/transformers/ga4) for the
|
|
99
|
+
authoritative reference.
|
|
100
|
+
|
|
101
|
+
## Override a default field
|
|
102
|
+
|
|
103
|
+
User config replaces matching default keys per event name. Untouched events keep
|
|
104
|
+
the default rule. To swap one mapped field on `purchase`:
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
{
|
|
108
|
+
"transformers": {
|
|
109
|
+
"ga4": {
|
|
110
|
+
"package": "@walkeros/transformer-ga4",
|
|
111
|
+
"config": {
|
|
112
|
+
"settings": {
|
|
113
|
+
"mapping": {
|
|
114
|
+
"purchase": {
|
|
115
|
+
"name": "order complete",
|
|
116
|
+
"data": {
|
|
117
|
+
"map": {
|
|
118
|
+
"coupon": "params.ep.promo_code"
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Replace semantics: the entire rule for `purchase` is taken from user config.
|
|
131
|
+
There is no additive merge inside `data.map` in v1 — copy the fields you want to
|
|
132
|
+
keep.
|
|
133
|
+
|
|
134
|
+
## Drop an event
|
|
135
|
+
|
|
136
|
+
Set `ignore: true` on any key:
|
|
137
|
+
|
|
138
|
+
```json
|
|
139
|
+
"mapping": {
|
|
140
|
+
"click": { "ignore": true }
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Custom events
|
|
145
|
+
|
|
146
|
+
Either override `'*'` to change the fallback rule, or add a specific key for an
|
|
147
|
+
event you fire from `gtag('event', '<your_name>', ...)`:
|
|
148
|
+
|
|
149
|
+
```json
|
|
150
|
+
"mapping": {
|
|
151
|
+
"newsletter_subscribe": {
|
|
152
|
+
"name": "newsletter signup",
|
|
153
|
+
"data": { "map": { "source": "params.ep.source" } }
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Unknown event names fall through to `'*'`, which by default emits a `ga4 track`
|
|
159
|
+
event with `data.event_name` set to the original `en`.
|
|
160
|
+
|
|
161
|
+
## Caveats
|
|
162
|
+
|
|
163
|
+
- **Replace semantics, not merge.** User mappings replace the matching default
|
|
164
|
+
rule. There's no per-field merge.
|
|
165
|
+
- **GA4 v2 only.** The transformer assumes the v2 Measurement Protocol layout
|
|
166
|
+
(`ep.`, `epn.`, `up.`, `upn.`, `prN`, `gcs`). v1 is out of scope.
|
|
167
|
+
- **`G-` tids only.** By default `tidPattern` is `^G-`, so Ads (`AW-`) and DC
|
|
168
|
+
(`DC-`) hits are dropped. Override `settings.tidPattern` (string regex) to
|
|
169
|
+
widen.
|
|
170
|
+
- **Basic `gcs` only.** Maps `G1XX` to `marketing`/`analytics` booleans.
|
|
171
|
+
Functional/preferences flags and `gcd` are not decoded.
|
|
172
|
+
- **Body must be raw text.** The transformer parses POST bodies as URL-encoded
|
|
173
|
+
form lines. If the source already JSON-parses the body, pass through the
|
|
174
|
+
original string or skip this transformer.
|
|
175
|
+
- **`Ingest` contract.** The transformer reads `ctx.ingest.url` (required) and
|
|
176
|
+
`ctx.ingest.body` (optional). Source wiring must populate them.
|
|
177
|
+
|
|
178
|
+
## Related
|
|
179
|
+
|
|
180
|
+
- [Documentation](https://www.walkeros.io/docs/transformers/ga4)
|
|
181
|
+
- [Transformers Overview](https://www.walkeros.io/docs/transformers)
|
package/dist/dev.d.mts
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { Mapping, WalkerOS, Flow } from '@walkeros/core';
|
|
2
|
+
|
|
3
|
+
/** Raw input to the decoder. Origin-agnostic (express, lambda, pubsub, etc). */
|
|
4
|
+
interface GA4Request {
|
|
5
|
+
/** Full request URL including query string. */
|
|
6
|
+
url: string;
|
|
7
|
+
/** POST body if present. May be \n- or \r\n-separated multi-event lines. */
|
|
8
|
+
body?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Parsed GA4 wire payload. One request → one hit → N events.
|
|
12
|
+
* IMPORTANT: dotted GA4 keys (`ep.transaction_id`, `epn.value`) are nested
|
|
13
|
+
* into structured objects at parse time so the mapping engine's getByPath
|
|
14
|
+
* (which splits paths on `.`) can resolve them.
|
|
15
|
+
*/
|
|
16
|
+
interface GA4Hit {
|
|
17
|
+
/** Hit-level params from the URL query string. v, tid, cid, sid, dl, dt, ul, sr, gcs, gtm, p. */
|
|
18
|
+
hit: GA4HitParams;
|
|
19
|
+
/** One entry per body line (POST) or single entry (GET). */
|
|
20
|
+
events: GA4Event[];
|
|
21
|
+
}
|
|
22
|
+
/** Hit-level params extracted from URL query. Known keys typed; unknown keys allowed. */
|
|
23
|
+
interface GA4HitParams {
|
|
24
|
+
v?: string;
|
|
25
|
+
tid?: string;
|
|
26
|
+
cid?: string;
|
|
27
|
+
sid?: string;
|
|
28
|
+
sct?: string;
|
|
29
|
+
seg?: string;
|
|
30
|
+
_p?: string;
|
|
31
|
+
_z?: string;
|
|
32
|
+
gtm?: string;
|
|
33
|
+
dl?: string;
|
|
34
|
+
dt?: string;
|
|
35
|
+
dr?: string;
|
|
36
|
+
ul?: string;
|
|
37
|
+
sr?: string;
|
|
38
|
+
uid?: string;
|
|
39
|
+
_dbg?: string;
|
|
40
|
+
_s?: string;
|
|
41
|
+
_ss?: string;
|
|
42
|
+
_fv?: string;
|
|
43
|
+
gcs?: string;
|
|
44
|
+
gcd?: string;
|
|
45
|
+
dma?: string;
|
|
46
|
+
dma_cps?: string;
|
|
47
|
+
npa?: string;
|
|
48
|
+
p?: string;
|
|
49
|
+
[other: string]: string | undefined;
|
|
50
|
+
}
|
|
51
|
+
interface GA4Event {
|
|
52
|
+
/** Event name from `en` param. */
|
|
53
|
+
en: string;
|
|
54
|
+
/**
|
|
55
|
+
* Per-event params with dotted keys nested:
|
|
56
|
+
* raw `ep.transaction_id` → `params.ep.transaction_id`
|
|
57
|
+
* raw `epn.value` → `params.epn.value`
|
|
58
|
+
* raw `up.role` → `params.up.role`
|
|
59
|
+
* raw `upn.score` → `params.upn.score`
|
|
60
|
+
* Standalone keys: `_et`, `_c` stay flat.
|
|
61
|
+
*/
|
|
62
|
+
params: GA4EventParams;
|
|
63
|
+
/** Parsed items from pr1, pr2, ..., prN. Empty array if none. */
|
|
64
|
+
items: GA4Item[];
|
|
65
|
+
}
|
|
66
|
+
interface GA4EventParams {
|
|
67
|
+
/** String event params from ep.<name>. */
|
|
68
|
+
ep: Record<string, string>;
|
|
69
|
+
/** Numeric event params from epn.<name>. Values are coerced via Number(). */
|
|
70
|
+
epn: Record<string, number>;
|
|
71
|
+
/** String user properties from up.<name>. */
|
|
72
|
+
up: Record<string, string>;
|
|
73
|
+
/** Numeric user properties from upn.<name>. */
|
|
74
|
+
upn: Record<string, number>;
|
|
75
|
+
/** Engagement time delta (ms). */
|
|
76
|
+
_et?: number;
|
|
77
|
+
/** Is-conversion flag. */
|
|
78
|
+
_c?: string;
|
|
79
|
+
}
|
|
80
|
+
/** Parsed product item from one pr<N> param. */
|
|
81
|
+
interface GA4Item {
|
|
82
|
+
id?: string;
|
|
83
|
+
name?: string;
|
|
84
|
+
brand?: string;
|
|
85
|
+
category?: string;
|
|
86
|
+
category2?: string;
|
|
87
|
+
category3?: string;
|
|
88
|
+
category4?: string;
|
|
89
|
+
category5?: string;
|
|
90
|
+
variant?: string;
|
|
91
|
+
price?: number;
|
|
92
|
+
quantity?: number;
|
|
93
|
+
coupon?: string;
|
|
94
|
+
discount?: number;
|
|
95
|
+
listName?: string;
|
|
96
|
+
listId?: string;
|
|
97
|
+
listPosition?: number;
|
|
98
|
+
locationId?: string;
|
|
99
|
+
affiliation?: string;
|
|
100
|
+
creativeName?: string;
|
|
101
|
+
creativeSlot?: string;
|
|
102
|
+
promotionId?: string;
|
|
103
|
+
promotionName?: string;
|
|
104
|
+
/** Custom item params from k<N>/v<N> pairs (multi-digit N supported). */
|
|
105
|
+
custom: Record<string, string>;
|
|
106
|
+
}
|
|
107
|
+
/** Decoder settings. */
|
|
108
|
+
interface GA4Settings {
|
|
109
|
+
/**
|
|
110
|
+
* Mapping registry keyed by GA4 event name (`en`).
|
|
111
|
+
* User config replaces matching package defaults at the per-event key.
|
|
112
|
+
* Use `'*'` for the unknown-event fallback.
|
|
113
|
+
* Set a rule's `ignore: true` to drop matching events.
|
|
114
|
+
*/
|
|
115
|
+
mapping?: GA4Mapping;
|
|
116
|
+
/**
|
|
117
|
+
* Regex string to filter `tid` values. Default `^G-` (drops Ads `AW-`/DC `DC-`).
|
|
118
|
+
* String at config time, compiled to RegExp once at init.
|
|
119
|
+
*/
|
|
120
|
+
tidPattern?: string;
|
|
121
|
+
}
|
|
122
|
+
/** Per-event mapping rule keyed by GA4 event name. */
|
|
123
|
+
type GA4Mapping = Record<string, Mapping.Rule | undefined> & {
|
|
124
|
+
'*'?: Mapping.Rule;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
declare function parseQuery(url: string): Record<string, string>;
|
|
128
|
+
declare function parseBody(body: string): Record<string, string>[];
|
|
129
|
+
declare function parseItem(value: string): GA4Item;
|
|
130
|
+
declare function parseConsent(hit: {
|
|
131
|
+
gcs?: string;
|
|
132
|
+
}): WalkerOS.Consent;
|
|
133
|
+
declare function parseRequest(req: GA4Request): GA4Hit;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Default GA4 event-name → walkerOS mapping rules.
|
|
137
|
+
* Users may override or extend these via settings.mapping at config time.
|
|
138
|
+
* The `'*'` key is the fallback for unknown event names.
|
|
139
|
+
*
|
|
140
|
+
* Field naming for `data.map`:
|
|
141
|
+
* - Monetary: `currency` from `ep.currency`, `value`/`total` from `epn.value`,
|
|
142
|
+
* `tax` from `epn.tax`, `shipping` from `epn.shipping`, `coupon` from
|
|
143
|
+
* `ep.coupon`.
|
|
144
|
+
* - Promotions read from `firstItem` (synthetic `items[0]` reference exposed by
|
|
145
|
+
* the mapper), since GA4 encodes promotion info inside item tilde strings.
|
|
146
|
+
*/
|
|
147
|
+
declare const defaultMapping: GA4Mapping;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Convert a parsed GA4 hit into zero or more walkerOS events.
|
|
151
|
+
* One GA4 hit may carry several events (POST batch); each is mapped
|
|
152
|
+
* independently with hit-level metadata merged in.
|
|
153
|
+
*/
|
|
154
|
+
declare function mapHitToEvents(hit: GA4Hit, mapping: GA4Mapping): WalkerOS.DeepPartialEvent[];
|
|
155
|
+
|
|
156
|
+
declare const pageView: Flow.StepExample;
|
|
157
|
+
declare const purchase: Flow.StepExample;
|
|
158
|
+
declare const viewItem: Flow.StepExample;
|
|
159
|
+
declare const addToCart: Flow.StepExample;
|
|
160
|
+
declare const beginCheckout: Flow.StepExample;
|
|
161
|
+
declare const scroll: Flow.StepExample;
|
|
162
|
+
declare const search: Flow.StepExample;
|
|
163
|
+
declare const login: Flow.StepExample;
|
|
164
|
+
declare const customEvent: Flow.StepExample;
|
|
165
|
+
declare const consentDenied: Flow.StepExample;
|
|
166
|
+
declare const userEngagementIgnored: Flow.StepExample;
|
|
167
|
+
declare const batchPost: Flow.StepExample;
|
|
168
|
+
|
|
169
|
+
declare const step_addToCart: typeof addToCart;
|
|
170
|
+
declare const step_batchPost: typeof batchPost;
|
|
171
|
+
declare const step_beginCheckout: typeof beginCheckout;
|
|
172
|
+
declare const step_consentDenied: typeof consentDenied;
|
|
173
|
+
declare const step_customEvent: typeof customEvent;
|
|
174
|
+
declare const step_login: typeof login;
|
|
175
|
+
declare const step_pageView: typeof pageView;
|
|
176
|
+
declare const step_purchase: typeof purchase;
|
|
177
|
+
declare const step_scroll: typeof scroll;
|
|
178
|
+
declare const step_search: typeof search;
|
|
179
|
+
declare const step_userEngagementIgnored: typeof userEngagementIgnored;
|
|
180
|
+
declare const step_viewItem: typeof viewItem;
|
|
181
|
+
declare namespace step {
|
|
182
|
+
export { step_addToCart as addToCart, step_batchPost as batchPost, step_beginCheckout as beginCheckout, step_consentDenied as consentDenied, step_customEvent as customEvent, step_login as login, step_pageView as pageView, step_purchase as purchase, step_scroll as scroll, step_search as search, step_userEngagementIgnored as userEngagementIgnored, step_viewItem as viewItem };
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
declare const index_step: typeof step;
|
|
186
|
+
declare namespace index {
|
|
187
|
+
export { index_step as step };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export { type GA4Event, type GA4EventParams, type GA4Hit, type GA4HitParams, type GA4Item, type GA4Mapping, type GA4Request, type GA4Settings, defaultMapping, index as examples, mapHitToEvents, parseBody, parseConsent, parseItem, parseQuery, parseRequest };
|
package/dist/dev.d.ts
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { Mapping, WalkerOS, Flow } from '@walkeros/core';
|
|
2
|
+
|
|
3
|
+
/** Raw input to the decoder. Origin-agnostic (express, lambda, pubsub, etc). */
|
|
4
|
+
interface GA4Request {
|
|
5
|
+
/** Full request URL including query string. */
|
|
6
|
+
url: string;
|
|
7
|
+
/** POST body if present. May be \n- or \r\n-separated multi-event lines. */
|
|
8
|
+
body?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Parsed GA4 wire payload. One request → one hit → N events.
|
|
12
|
+
* IMPORTANT: dotted GA4 keys (`ep.transaction_id`, `epn.value`) are nested
|
|
13
|
+
* into structured objects at parse time so the mapping engine's getByPath
|
|
14
|
+
* (which splits paths on `.`) can resolve them.
|
|
15
|
+
*/
|
|
16
|
+
interface GA4Hit {
|
|
17
|
+
/** Hit-level params from the URL query string. v, tid, cid, sid, dl, dt, ul, sr, gcs, gtm, p. */
|
|
18
|
+
hit: GA4HitParams;
|
|
19
|
+
/** One entry per body line (POST) or single entry (GET). */
|
|
20
|
+
events: GA4Event[];
|
|
21
|
+
}
|
|
22
|
+
/** Hit-level params extracted from URL query. Known keys typed; unknown keys allowed. */
|
|
23
|
+
interface GA4HitParams {
|
|
24
|
+
v?: string;
|
|
25
|
+
tid?: string;
|
|
26
|
+
cid?: string;
|
|
27
|
+
sid?: string;
|
|
28
|
+
sct?: string;
|
|
29
|
+
seg?: string;
|
|
30
|
+
_p?: string;
|
|
31
|
+
_z?: string;
|
|
32
|
+
gtm?: string;
|
|
33
|
+
dl?: string;
|
|
34
|
+
dt?: string;
|
|
35
|
+
dr?: string;
|
|
36
|
+
ul?: string;
|
|
37
|
+
sr?: string;
|
|
38
|
+
uid?: string;
|
|
39
|
+
_dbg?: string;
|
|
40
|
+
_s?: string;
|
|
41
|
+
_ss?: string;
|
|
42
|
+
_fv?: string;
|
|
43
|
+
gcs?: string;
|
|
44
|
+
gcd?: string;
|
|
45
|
+
dma?: string;
|
|
46
|
+
dma_cps?: string;
|
|
47
|
+
npa?: string;
|
|
48
|
+
p?: string;
|
|
49
|
+
[other: string]: string | undefined;
|
|
50
|
+
}
|
|
51
|
+
interface GA4Event {
|
|
52
|
+
/** Event name from `en` param. */
|
|
53
|
+
en: string;
|
|
54
|
+
/**
|
|
55
|
+
* Per-event params with dotted keys nested:
|
|
56
|
+
* raw `ep.transaction_id` → `params.ep.transaction_id`
|
|
57
|
+
* raw `epn.value` → `params.epn.value`
|
|
58
|
+
* raw `up.role` → `params.up.role`
|
|
59
|
+
* raw `upn.score` → `params.upn.score`
|
|
60
|
+
* Standalone keys: `_et`, `_c` stay flat.
|
|
61
|
+
*/
|
|
62
|
+
params: GA4EventParams;
|
|
63
|
+
/** Parsed items from pr1, pr2, ..., prN. Empty array if none. */
|
|
64
|
+
items: GA4Item[];
|
|
65
|
+
}
|
|
66
|
+
interface GA4EventParams {
|
|
67
|
+
/** String event params from ep.<name>. */
|
|
68
|
+
ep: Record<string, string>;
|
|
69
|
+
/** Numeric event params from epn.<name>. Values are coerced via Number(). */
|
|
70
|
+
epn: Record<string, number>;
|
|
71
|
+
/** String user properties from up.<name>. */
|
|
72
|
+
up: Record<string, string>;
|
|
73
|
+
/** Numeric user properties from upn.<name>. */
|
|
74
|
+
upn: Record<string, number>;
|
|
75
|
+
/** Engagement time delta (ms). */
|
|
76
|
+
_et?: number;
|
|
77
|
+
/** Is-conversion flag. */
|
|
78
|
+
_c?: string;
|
|
79
|
+
}
|
|
80
|
+
/** Parsed product item from one pr<N> param. */
|
|
81
|
+
interface GA4Item {
|
|
82
|
+
id?: string;
|
|
83
|
+
name?: string;
|
|
84
|
+
brand?: string;
|
|
85
|
+
category?: string;
|
|
86
|
+
category2?: string;
|
|
87
|
+
category3?: string;
|
|
88
|
+
category4?: string;
|
|
89
|
+
category5?: string;
|
|
90
|
+
variant?: string;
|
|
91
|
+
price?: number;
|
|
92
|
+
quantity?: number;
|
|
93
|
+
coupon?: string;
|
|
94
|
+
discount?: number;
|
|
95
|
+
listName?: string;
|
|
96
|
+
listId?: string;
|
|
97
|
+
listPosition?: number;
|
|
98
|
+
locationId?: string;
|
|
99
|
+
affiliation?: string;
|
|
100
|
+
creativeName?: string;
|
|
101
|
+
creativeSlot?: string;
|
|
102
|
+
promotionId?: string;
|
|
103
|
+
promotionName?: string;
|
|
104
|
+
/** Custom item params from k<N>/v<N> pairs (multi-digit N supported). */
|
|
105
|
+
custom: Record<string, string>;
|
|
106
|
+
}
|
|
107
|
+
/** Decoder settings. */
|
|
108
|
+
interface GA4Settings {
|
|
109
|
+
/**
|
|
110
|
+
* Mapping registry keyed by GA4 event name (`en`).
|
|
111
|
+
* User config replaces matching package defaults at the per-event key.
|
|
112
|
+
* Use `'*'` for the unknown-event fallback.
|
|
113
|
+
* Set a rule's `ignore: true` to drop matching events.
|
|
114
|
+
*/
|
|
115
|
+
mapping?: GA4Mapping;
|
|
116
|
+
/**
|
|
117
|
+
* Regex string to filter `tid` values. Default `^G-` (drops Ads `AW-`/DC `DC-`).
|
|
118
|
+
* String at config time, compiled to RegExp once at init.
|
|
119
|
+
*/
|
|
120
|
+
tidPattern?: string;
|
|
121
|
+
}
|
|
122
|
+
/** Per-event mapping rule keyed by GA4 event name. */
|
|
123
|
+
type GA4Mapping = Record<string, Mapping.Rule | undefined> & {
|
|
124
|
+
'*'?: Mapping.Rule;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
declare function parseQuery(url: string): Record<string, string>;
|
|
128
|
+
declare function parseBody(body: string): Record<string, string>[];
|
|
129
|
+
declare function parseItem(value: string): GA4Item;
|
|
130
|
+
declare function parseConsent(hit: {
|
|
131
|
+
gcs?: string;
|
|
132
|
+
}): WalkerOS.Consent;
|
|
133
|
+
declare function parseRequest(req: GA4Request): GA4Hit;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Default GA4 event-name → walkerOS mapping rules.
|
|
137
|
+
* Users may override or extend these via settings.mapping at config time.
|
|
138
|
+
* The `'*'` key is the fallback for unknown event names.
|
|
139
|
+
*
|
|
140
|
+
* Field naming for `data.map`:
|
|
141
|
+
* - Monetary: `currency` from `ep.currency`, `value`/`total` from `epn.value`,
|
|
142
|
+
* `tax` from `epn.tax`, `shipping` from `epn.shipping`, `coupon` from
|
|
143
|
+
* `ep.coupon`.
|
|
144
|
+
* - Promotions read from `firstItem` (synthetic `items[0]` reference exposed by
|
|
145
|
+
* the mapper), since GA4 encodes promotion info inside item tilde strings.
|
|
146
|
+
*/
|
|
147
|
+
declare const defaultMapping: GA4Mapping;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Convert a parsed GA4 hit into zero or more walkerOS events.
|
|
151
|
+
* One GA4 hit may carry several events (POST batch); each is mapped
|
|
152
|
+
* independently with hit-level metadata merged in.
|
|
153
|
+
*/
|
|
154
|
+
declare function mapHitToEvents(hit: GA4Hit, mapping: GA4Mapping): WalkerOS.DeepPartialEvent[];
|
|
155
|
+
|
|
156
|
+
declare const pageView: Flow.StepExample;
|
|
157
|
+
declare const purchase: Flow.StepExample;
|
|
158
|
+
declare const viewItem: Flow.StepExample;
|
|
159
|
+
declare const addToCart: Flow.StepExample;
|
|
160
|
+
declare const beginCheckout: Flow.StepExample;
|
|
161
|
+
declare const scroll: Flow.StepExample;
|
|
162
|
+
declare const search: Flow.StepExample;
|
|
163
|
+
declare const login: Flow.StepExample;
|
|
164
|
+
declare const customEvent: Flow.StepExample;
|
|
165
|
+
declare const consentDenied: Flow.StepExample;
|
|
166
|
+
declare const userEngagementIgnored: Flow.StepExample;
|
|
167
|
+
declare const batchPost: Flow.StepExample;
|
|
168
|
+
|
|
169
|
+
declare const step_addToCart: typeof addToCart;
|
|
170
|
+
declare const step_batchPost: typeof batchPost;
|
|
171
|
+
declare const step_beginCheckout: typeof beginCheckout;
|
|
172
|
+
declare const step_consentDenied: typeof consentDenied;
|
|
173
|
+
declare const step_customEvent: typeof customEvent;
|
|
174
|
+
declare const step_login: typeof login;
|
|
175
|
+
declare const step_pageView: typeof pageView;
|
|
176
|
+
declare const step_purchase: typeof purchase;
|
|
177
|
+
declare const step_scroll: typeof scroll;
|
|
178
|
+
declare const step_search: typeof search;
|
|
179
|
+
declare const step_userEngagementIgnored: typeof userEngagementIgnored;
|
|
180
|
+
declare const step_viewItem: typeof viewItem;
|
|
181
|
+
declare namespace step {
|
|
182
|
+
export { step_addToCart as addToCart, step_batchPost as batchPost, step_beginCheckout as beginCheckout, step_consentDenied as consentDenied, step_customEvent as customEvent, step_login as login, step_pageView as pageView, step_purchase as purchase, step_scroll as scroll, step_search as search, step_userEngagementIgnored as userEngagementIgnored, step_viewItem as viewItem };
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
declare const index_step: typeof step;
|
|
186
|
+
declare namespace index {
|
|
187
|
+
export { index_step as step };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export { type GA4Event, type GA4EventParams, type GA4Hit, type GA4HitParams, type GA4Item, type GA4Mapping, type GA4Request, type GA4Settings, defaultMapping, index as examples, mapHitToEvents, parseBody, parseConsent, parseItem, parseQuery, parseRequest };
|
package/dist/dev.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var e,t=Object.defineProperty,a=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.prototype.hasOwnProperty,n=(e,a)=>{for(var r in a)t(e,r,{get:a[r],enumerable:!0})},o={};function c(e){const t={},a=e.indexOf("?");if(-1===a)return t;return new URLSearchParams(e.slice(a+1)).forEach((e,a)=>{t[a]=e}),t}function s(e){return e?e.split(/\r?\n/).map(e=>e.trim()).filter(e=>e.length>0).map(e=>{const t={};return new URLSearchParams(e).forEach((e,a)=>{t[a]=e}),t}):[]}n(o,{defaultMapping:()=>_,examples:()=>E,mapHitToEvents:()=>h,parseBody:()=>s,parseConsent:()=>v,parseItem:()=>l,parseQuery:()=>c,parseRequest:()=>y}),module.exports=(e=o,((e,n,o,c)=>{if(n&&"object"==typeof n||"function"==typeof n)for(let s of r(n))i.call(e,s)||s===o||t(e,s,{get:()=>n[s],enumerable:!(c=a(n,s))||c.enumerable});return e})(t({},"__esModule",{value:!0}),e));var p={id:"id",nm:"name",br:"brand",ca:"category",c2:"category2",c3:"category3",c4:"category4",c5:"category5",va:"variant",cp:"coupon",ln:"listName",li:"listId",lo:"locationId",af:"affiliation",cn:"creativeName",cs:"creativeSlot",pi:"promotionId",pn:"promotionName"},d={pr:"price",qt:"quantity",ds:"discount",lp:"listPosition"};function m(e,t,a){switch(t){case"id":return void(e.id=a);case"name":return void(e.name=a);case"brand":return void(e.brand=a);case"category":return void(e.category=a);case"category2":return void(e.category2=a);case"category3":return void(e.category3=a);case"category4":return void(e.category4=a);case"category5":return void(e.category5=a);case"variant":return void(e.variant=a);case"coupon":return void(e.coupon=a);case"listName":return void(e.listName=a);case"listId":return void(e.listId=a);case"locationId":return void(e.locationId=a);case"affiliation":return void(e.affiliation=a);case"creativeName":return void(e.creativeName=a);case"creativeSlot":return void(e.creativeSlot=a);case"promotionId":return void(e.promotionId=a);case"promotionName":return void(e.promotionName=a)}}function u(e,t,a){switch(t){case"price":return void(e.price=a);case"quantity":return void(e.quantity=a);case"discount":return void(e.discount=a);case"listPosition":return void(e.listPosition=a)}}function l(e){const t={custom:{}},a=new Map,r=new Map;for(const i of e.split("~")){if(0===i.length)continue;const e=/^([kv])(\d+)(.*)$/.exec(i);if(e){const[,t,i,n]=e;"k"===t?a.set(i,n):r.set(i,n);continue}if(i.length<2)continue;const n=i.slice(0,2),o=i.slice(2),c=p[n];if(void 0!==c){m(t,c,o);continue}const s=d[n];if(void 0!==s){const e=Number(o);Number.isNaN(e)||u(t,s,e);continue}}for(const[e,i]of a){const a=r.get(e);void 0!==a&&(t.custom[i]=a)}return t}function v(e){const t=e.gcs;return t&&/^G[01]{3}$/.test(t)?{marketing:"1"===t[2],analytics:"1"===t[3]}:{}}var g=new Set(["v","tid","cid","sid","sct","seg","_p","_z","gtm","dl","dt","dr","ul","sr","uid","_dbg","_s","_ss","_fv","gcs","gcd","dma","dma_cps","npa","p"]);function y(e){const t=c(e.url),a={},r={};for(const[e,i]of Object.entries(t))g.has(e)?a[e]=i:r[e]=i;const i=e.body?s(e.body):[];return{hit:a,events:(i.length>0?i:Object.keys(r).length>0?[r]:[]).filter(e=>"string"==typeof e.en&&e.en.length>0).map(e=>function(e){const t={ep:{},epn:{},up:{},upn:{}},a=[];for(const[r,i]of Object.entries(e)){if("en"===r)continue;const e=/^pr(\d+)$/.exec(r);if(e)a.push([Number(e[1]),i]);else if(r.startsWith("ep."))t.ep[r.slice(3)]=i;else{if(r.startsWith("epn.")){const e=Number(i);Number.isNaN(e)||(t.epn[r.slice(4)]=e);continue}if(r.startsWith("up."))t.up[r.slice(3)]=i;else{if(r.startsWith("upn.")){const e=Number(i);Number.isNaN(e)||(t.upn[r.slice(4)]=e);continue}if("_et"===r){const e=Number(i);Number.isNaN(e)||(t._et=e);continue}"_c"!==r||(t._c=i)}}}a.sort((e,t)=>e[0]-t[0]);const r=a.map(([,e])=>l(e));return{en:e.en,params:t,items:r}}(e))}}var _={page_view:{name:"page view",data:{map:{id:"hit.dl",title:"hit.dt",referrer:"hit.dr"}}},purchase:{name:"order complete",data:{map:{id:"params.ep.transaction_id",currency:"params.ep.currency",total:"params.epn.value",tax:"params.epn.tax",shipping:"params.epn.shipping",coupon:"params.ep.coupon"}}},view_item:{name:"product view",data:{map:{currency:"params.ep.currency",value:"params.epn.value"}}},add_to_cart:{name:"product add",data:{map:{currency:"params.ep.currency",value:"params.epn.value"}}},remove_from_cart:{name:"product remove",data:{map:{currency:"params.ep.currency",value:"params.epn.value"}}},view_cart:{name:"cart view",data:{map:{currency:"params.ep.currency",value:"params.epn.value"}}},begin_checkout:{name:"order start",data:{map:{currency:"params.ep.currency",value:"params.epn.value",coupon:"params.ep.coupon"}}},add_shipping_info:{name:"order shipping",data:{map:{currency:"params.ep.currency",value:"params.epn.value",tier:"params.ep.shipping_tier"}}},add_payment_info:{name:"order payment",data:{map:{currency:"params.ep.currency",value:"params.epn.value",type:"params.ep.payment_type"}}},refund:{name:"order refund",data:{map:{id:"params.ep.transaction_id",currency:"params.ep.currency",total:"params.epn.value"}}},add_to_wishlist:{name:"wishlist add",data:{map:{currency:"params.ep.currency",value:"params.epn.value"}}},view_item_list:{name:"list view",data:{map:{id:"params.ep.item_list_id",name:"params.ep.item_list_name"}}},select_item:{name:"product click",data:{map:{list_id:"params.ep.item_list_id",list_name:"params.ep.item_list_name"}}},view_promotion:{name:"promotion view",data:{map:{id:"firstItem.promotionId",name:"firstItem.promotionName",creative:"firstItem.creativeName",slot:"firstItem.creativeSlot"}}},select_promotion:{name:"promotion click",data:{map:{id:"firstItem.promotionId",name:"firstItem.promotionName",creative:"firstItem.creativeName",slot:"firstItem.creativeSlot"}}},select_content:{name:"content select",data:{map:{type:"params.ep.content_type",id:"params.ep.content_id"}}},scroll:{name:"page scroll",data:{map:{percent:"params.epn.percent_scrolled"}}},click:{name:"link click",data:{map:{url:"params.ep.link_url",domain:"params.ep.link_domain",outbound:"params.ep.outbound"}}},file_download:{name:"file download",data:{map:{name:"params.ep.file_name",extension:"params.ep.file_extension",url:"params.ep.link_url"}}},video_start:{name:"video start",data:{map:{title:"params.ep.video_title",duration:"params.epn.video_duration",current:"params.epn.video_current_time",percent:"params.epn.video_percent"}}},video_progress:{name:"video progress",data:{map:{title:"params.ep.video_title",duration:"params.epn.video_duration",current:"params.epn.video_current_time",percent:"params.epn.video_percent"}}},video_complete:{name:"video complete",data:{map:{title:"params.ep.video_title",duration:"params.epn.video_duration",current:"params.epn.video_current_time",percent:"params.epn.video_percent"}}},form_start:{name:"form start",data:{map:{id:"params.ep.form_id",name:"params.ep.form_name",destination:"params.ep.form_destination"}}},form_submit:{name:"form submit",data:{map:{id:"params.ep.form_id",name:"params.ep.form_name",destination:"params.ep.form_destination"}}},search:{name:"search submit",data:{map:{term:"params.ep.search_term"}}},login:{name:"session login",data:{map:{method:"params.ep.method"}}},sign_up:{name:"session signup",data:{map:{method:"params.ep.method"}}},generate_lead:{name:"lead generate",data:{map:{currency:"params.ep.currency",value:"params.epn.value"}}},share:{name:"content share",data:{map:{method:"params.ep.method",type:"params.ep.content_type",id:"params.ep.item_id"}}},user_engagement:{ignore:!0},session_start:{ignore:!0},first_visit:{ignore:!0},"*":{name:"ga4 track",data:{map:{event_name:"en"}}}},f=require("@walkeros/core");function h(e,t){const a=[];for(const r of e.events){const i=w(e.hit,r,t);i&&a.push(i)}return a}function w(e,t,a){const r=a[t.en]??a["*"];if(!r)return null;const i=Array.isArray(r)?r[0]:r;if(!i||i.ignore)return null;const n={hit:e,params:t.params,items:t.items,en:t.en,...t.items.length>0?{firstItem:t.items[0]}:{}},o={};if(i.name){const[e,...t]=i.name.split(" ");o.name=i.name,o.entity=e,o.action=t.join(" ")}if(void 0!==i.data){const e=b(i.data,n);void 0!==e&&(o.data=e)}o.user={...void 0!==e.uid?{id:e.uid}:{},...void 0!==e.cid?{device:e.cid}:{},...void 0!==e.sid?{session:e.sid}:{}},o.globals={...void 0!==e.ul?{language:e.ul}:{},...void 0!==e.sr?{screen:e.sr}:{}},o.source={type:"ga4",...void 0!==e.p?{platform:e.p}:{}},o.consent=v(e),o.id=e._p??(0,f.getId)();const c=e.sid?Number(e.sid):NaN;return o.timestamp=!Number.isNaN(c)&&c>0?1e3*c:Date.now(),o.timing=t.params._et??0,o.trigger="ga4",t.items.length>0&&(o.nested=t.items.map(e=>{const t={};void 0!==e.id&&(t.id=e.id),void 0!==e.name&&(t.name=e.name),void 0!==e.brand&&(t.brand=e.brand),void 0!==e.category&&(t.category=e.category),void 0!==e.category2&&(t.category2=e.category2),void 0!==e.category3&&(t.category3=e.category3),void 0!==e.category4&&(t.category4=e.category4),void 0!==e.category5&&(t.category5=e.category5),void 0!==e.variant&&(t.variant=e.variant),void 0!==e.price&&(t.price=e.price),void 0!==e.quantity&&(t.quantity=e.quantity),void 0!==e.coupon&&(t.coupon=e.coupon),void 0!==e.discount&&(t.discount=e.discount),void 0!==e.listName&&(t.list_name=e.listName),void 0!==e.listId&&(t.list_id=e.listId),void 0!==e.listPosition&&(t.list_position=e.listPosition),void 0!==e.locationId&&(t.location_id=e.locationId),void 0!==e.affiliation&&(t.affiliation=e.affiliation),void 0!==e.creativeName&&(t.creative_name=e.creativeName),void 0!==e.creativeSlot&&(t.creative_slot=e.creativeSlot),void 0!==e.promotionId&&(t.promotion_id=e.promotionId),void 0!==e.promotionName&&(t.promotion_name=e.promotionName);for(const[a,r]of Object.entries(e.custom))t[a]=r;return{entity:"product",data:t,nested:[],context:{}}})),o}function b(e,t){if(Array.isArray(e))for(const a of e){const e=b(a,t);if(null!=e)return e}else{if("string"==typeof e)return(0,f.getByPath)(t,e);if("object"==typeof e&&null!==e){if("value"in e&&void 0!==e.value)return e.value;if("key"in e&&"string"==typeof e.key)return(0,f.getByPath)(t,e.key);if("map"in e&&e.map){const a={};for(const[r,i]of Object.entries(e.map)){const e=b(i,t);void 0!==e&&(a[r]=e)}return a}}}}var E={};n(E,{step:()=>N});var N={};n(N,{addToCart:()=>G,batchPost:()=>j,beginCheckout:()=>S,consentDenied:()=>U,customEvent:()=>R,login:()=>L,pageView:()=>P,purchase:()=>I,scroll:()=>M,search:()=>x,userEngagementIgnored:()=>X,viewItem:()=>O});var k="1700000000";function A(e){return{id:"p1",timestamp:17e11,timing:0,trigger:"ga4",user:{device:"cid-1",session:k},globals:{},source:{type:"ga4"},consent:{},...e}}var P={title:"Page view",description:"A standard GA4 page_view hit decoded to a walkerOS page view with id, title, and referrer.",in:{url:"https://www.google-analytics.com/g/collect?v=2&tid=G-EXAMPLE&_p=p1&cid=cid-1&sid="+k+"&en=page_view&dl=https%3A%2F%2Fshop.example.com%2Fproducts%2Fsku-123&dt=Trail%20Runner%20Pro&dr=https%3A%2F%2Fshop.example.com%2F"},out:[["return",A({name:"page view",entity:"page",action:"view",data:{id:"https://shop.example.com/products/sku-123",title:"Trail Runner Pro",referrer:"https://shop.example.com/"}})]]},I={title:"Purchase (canary)",description:"A GA4 purchase hit decoded to a walkerOS order complete event with id, currency, total, tax, shipping, and coupon.",in:{url:"https://www.google-analytics.com/g/collect?v=2&tid=G-EXAMPLE&_p=p1&cid=cid-1&sid="+k+"&en=purchase&ep.transaction_id=T-9001&ep.currency=EUR&epn.value=149.97&epn.tax=23.97&epn.shipping=4.95&ep.coupon=WELCOME10"},out:[["return",A({name:"order complete",entity:"order",action:"complete",data:{id:"T-9001",currency:"EUR",total:149.97,tax:23.97,shipping:4.95,coupon:"WELCOME10"}})]]},O={title:"View item",description:"A GA4 view_item hit decoded to a walkerOS product view event with currency and value.",in:{url:"https://www.google-analytics.com/g/collect?v=2&tid=G-EXAMPLE&_p=p1&cid=cid-1&sid="+k+"&en=view_item&ep.currency=EUR&epn.value=129.99"},out:[["return",A({name:"product view",entity:"product",action:"view",data:{currency:"EUR",value:129.99}})]]},G={title:"Add to cart",description:"A GA4 add_to_cart hit decoded to a walkerOS product add event with currency and value.",in:{url:"https://www.google-analytics.com/g/collect?v=2&tid=G-EXAMPLE&_p=p1&cid=cid-1&sid="+k+"&en=add_to_cart&ep.currency=EUR&epn.value=129.99"},out:[["return",A({name:"product add",entity:"product",action:"add",data:{currency:"EUR",value:129.99}})]]},S={title:"Begin checkout",description:"A GA4 begin_checkout hit decoded to a walkerOS order start event with currency, value, and coupon.",in:{url:"https://www.google-analytics.com/g/collect?v=2&tid=G-EXAMPLE&_p=p1&cid=cid-1&sid="+k+"&en=begin_checkout&ep.currency=EUR&epn.value=149.97&ep.coupon=WELCOME10"},out:[["return",A({name:"order start",entity:"order",action:"start",data:{currency:"EUR",value:149.97,coupon:"WELCOME10"}})]]},M={title:"Scroll",description:"A GA4 scroll hit decoded to a walkerOS page scroll event with the percent_scrolled value.",in:{url:"https://www.google-analytics.com/g/collect?v=2&tid=G-EXAMPLE&_p=p1&cid=cid-1&sid="+k+"&en=scroll&epn.percent_scrolled=90"},out:[["return",A({name:"page scroll",entity:"page",action:"scroll",data:{percent:90}})]]},x={title:"Search",description:"A GA4 search hit decoded to a walkerOS search submit event carrying the search term.",in:{url:"https://www.google-analytics.com/g/collect?v=2&tid=G-EXAMPLE&_p=p1&cid=cid-1&sid="+k+"&en=search&ep.search_term=trail%20runner"},out:[["return",A({name:"search submit",entity:"search",action:"submit",data:{term:"trail runner"}})]]},L={title:"Login",description:"A GA4 login hit decoded to a walkerOS session login event with the auth method.",in:{url:"https://www.google-analytics.com/g/collect?v=2&tid=G-EXAMPLE&_p=p1&cid=cid-1&sid="+k+"&en=login&ep.method=google"},out:[["return",A({name:"session login",entity:"session",action:"login",data:{method:"google"}})]]},R={title:"Custom event (* fallback)",description:"Unknown GA4 event names hit the * fallback rule and surface as a ga4 track event carrying the original name.",in:{url:"https://www.google-analytics.com/g/collect?v=2&tid=G-EXAMPLE&_p=p1&cid=cid-1&sid="+k+"&en=newsletter_subscribe&ep.source=footer"},out:[["return",A({name:"ga4 track",entity:"ga4",action:"track",data:{event_name:"newsletter_subscribe"}})]]},U={title:"Consent denied (gcs=G100)",description:"A page_view hit with gcs=G100 still maps, with consent.{marketing,analytics} both false on the resulting event.",in:{url:"https://www.google-analytics.com/g/collect?v=2&tid=G-EXAMPLE&_p=p1&cid=cid-1&sid="+k+"&gcs=G100&en=page_view&dl=https%3A%2F%2Fx&dt=X"},out:[["return",A({name:"page view",entity:"page",action:"view",data:{id:"https://x",title:"X"},consent:{marketing:!1,analytics:!1}})]]},X={title:"user_engagement (ignored)",description:"Auto-fired GA4 user_engagement events are dropped by default — the transformer returns false.",in:{url:"https://www.google-analytics.com/g/collect?v=2&tid=G-EXAMPLE&_p=p1&cid=cid-1&sid="+k+"&en=user_engagement&_et=1500"},out:[["return",!1]]},j={title:"Batched POST (fan-out)",description:"A single POST request carrying two newline-separated events fans out into two walkerOS events.",in:{url:"https://www.google-analytics.com/g/collect?v=2&tid=G-EXAMPLE&_p=p1&cid=cid-1&sid="+k,body:["en=add_to_cart&ep.currency=EUR&epn.value=19.99","en=add_to_cart&ep.currency=EUR&epn.value=29.99"].join("\n")},out:[["return",A({name:"product add",entity:"product",action:"add",data:{currency:"EUR",value:19.99}})],["return",A({name:"product add",entity:"product",action:"add",data:{currency:"EUR",value:29.99}})]]};//# sourceMappingURL=dev.js.map
|