@walkeros/transformer-ga4 4.6.1 → 4.7.0-next-1790187973605

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/CHANGELOG.md CHANGED
@@ -1,5 +1,37 @@
1
1
  # @walkeros/transformer-ga4
2
2
 
3
+ ## 4.7.0-next-1790187973605
4
+
5
+ ### Minor Changes
6
+
7
+ - ef02916: New `settings.maxEvents` (default 100) caps the events decoded from
8
+ one request. A POST body with more lines is dropped whole, so one oversized
9
+ body can no longer fan out into thousands of concurrent events. The wiring
10
+ hint now sets `paths: ["/g/collect"]` on the express source and lists the
11
+ sources that decode batched gtag.js hits. Each `settings.mapping` entry is now
12
+ validated as a mapping rule, so a typo such as `ignore: "false"` fails
13
+ validation.
14
+
15
+ ### Patch Changes
16
+
17
+ - 8f8aea6: Each decoded GA4 event now gets its own event id. Before, every event
18
+ from the same page shared one id, so deduplicating on `event.id` dropped all
19
+ but the first. The id stays the same when a hit is delivered twice, so retries
20
+ are still deduplicated. `source` now also carries the raw GA4 `pageLoadId` and
21
+ `hitSequence`.
22
+ - Updated dependencies [57788bc]
23
+ - Updated dependencies [f5a1cfd]
24
+ - Updated dependencies [ef02916]
25
+ - Updated dependencies [ef02916]
26
+ - Updated dependencies [2aebc53]
27
+ - Updated dependencies [f5a1cfd]
28
+ - Updated dependencies [f5a1cfd]
29
+ - Updated dependencies [2aebc53]
30
+ - Updated dependencies [8f8aea6]
31
+ - Updated dependencies [2aebc53]
32
+ - Updated dependencies [2aebc53]
33
+ - @walkeros/core@4.7.0-next-1790187973605
34
+
3
35
  ## 4.6.1
4
36
 
5
37
  ### Patch Changes
package/dist/dev.d.mts CHANGED
@@ -1,5 +1,20 @@
1
1
  import { Mapping, WalkerOS, Flow, Hint } from '@walkeros/core';
2
+ import * as _walkeros_core_dev from '@walkeros/core/dev';
3
+ import { z } from '@walkeros/core/dev';
2
4
 
5
+ declare module '@walkeros/core' {
6
+ interface SourceMap {
7
+ ga4: {
8
+ type: 'ga4';
9
+ /** GA4 `p` param, when sent. */
10
+ platform?: string;
11
+ /** Raw GA4 page load id (`_p`), shared by every hit of one page load. */
12
+ pageLoadId?: string;
13
+ /** Raw GA4 hit sequence counter (`_s`) within the page load. */
14
+ hitSequence?: string;
15
+ };
16
+ }
17
+ }
3
18
  /** Raw input to the decoder. Origin-agnostic (express, lambda, pubsub, etc). */
4
19
  interface GA4Request {
5
20
  /** Full request URL including query string. */
@@ -118,6 +133,11 @@ interface GA4Settings {
118
133
  * String at config time, compiled to RegExp once at init.
119
134
  */
120
135
  tidPattern?: string;
136
+ /**
137
+ * Maximum number of events (POST body lines) decoded from one request.
138
+ * A request above the cap is dropped whole. Default `100`.
139
+ */
140
+ maxEvents?: number;
121
141
  }
122
142
  /** Per-event mapping rule keyed by GA4 event name. */
123
143
  type GA4Mapping = Record<string, Mapping.Rule | undefined> & {
@@ -153,6 +173,54 @@ declare const defaultMapping: GA4Mapping;
153
173
  */
154
174
  declare function mapHitToEvents(hit: GA4Hit, mapping: GA4Mapping): WalkerOS.DeepPartialEvent[];
155
175
 
176
+ declare const SettingsSchema: z.ZodObject<{
177
+ mapping: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
178
+ name: z.ZodOptional<z.ZodString>;
179
+ data: z.ZodOptional<z.ZodUnion<readonly [z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, z.ZodArray<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>]>>;
180
+ settings: z.ZodOptional<z.ZodUnknown>;
181
+ condition: z.ZodOptional<z.ZodString>;
182
+ consent: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
183
+ policy: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>>;
184
+ batch: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodObject<{
185
+ wait: z.ZodOptional<z.ZodNumber>;
186
+ size: z.ZodOptional<z.ZodNumber>;
187
+ age: z.ZodOptional<z.ZodNumber>;
188
+ }, z.core.$strip>]>>;
189
+ include: z.ZodOptional<z.ZodArray<z.ZodString>>;
190
+ ignore: z.ZodOptional<z.ZodBoolean>;
191
+ silent: z.ZodOptional<z.ZodBoolean>;
192
+ extend: z.ZodOptional<z.ZodObject<{
193
+ name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
194
+ data: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, z.ZodArray<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>]>>>;
195
+ settings: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
196
+ condition: z.ZodOptional<z.ZodNullable<z.ZodString>>;
197
+ consent: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodBoolean>>>;
198
+ policy: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>>>;
199
+ batch: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodNumber, z.ZodObject<{
200
+ wait: z.ZodOptional<z.ZodNumber>;
201
+ size: z.ZodOptional<z.ZodNumber>;
202
+ age: z.ZodOptional<z.ZodNumber>;
203
+ }, z.core.$strip>]>>>;
204
+ include: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
205
+ ignore: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
206
+ silent: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
207
+ }, z.core.$strip>>;
208
+ remove: z.ZodOptional<z.ZodArray<z.ZodString>>;
209
+ }, z.core.$strip>>>;
210
+ tidPattern: z.ZodOptional<z.ZodString>;
211
+ maxEvents: z.ZodOptional<z.ZodNumber>;
212
+ }, z.core.$strip>;
213
+ type Settings = z.infer<typeof SettingsSchema>;
214
+
215
+ declare const settings: _walkeros_core_dev.JSONSchema;
216
+
217
+ type index$1_Settings = Settings;
218
+ declare const index$1_SettingsSchema: typeof SettingsSchema;
219
+ declare const index$1_settings: typeof settings;
220
+ declare namespace index$1 {
221
+ export { type index$1_Settings as Settings, index$1_SettingsSchema as SettingsSchema, index$1_settings as settings };
222
+ }
223
+
156
224
  declare const pageView: Flow.StepExample;
157
225
  declare const purchase: Flow.StepExample;
158
226
  declare const viewItem: Flow.StepExample;
@@ -189,4 +257,4 @@ declare namespace index {
189
257
 
190
258
  declare const hints: Hint.Hints;
191
259
 
192
- export { type GA4Event, type GA4EventParams, type GA4Hit, type GA4HitParams, type GA4Item, type GA4Mapping, type GA4Request, type GA4Settings, defaultMapping, index as examples, hints, mapHitToEvents, parseBody, parseConsent, parseItem, parseQuery, parseRequest };
260
+ export { type GA4Event, type GA4EventParams, type GA4Hit, type GA4HitParams, type GA4Item, type GA4Mapping, type GA4Request, type GA4Settings, defaultMapping, index as examples, hints, mapHitToEvents, parseBody, parseConsent, parseItem, parseQuery, parseRequest, index$1 as schemas };
package/dist/dev.d.ts CHANGED
@@ -1,5 +1,20 @@
1
1
  import { Mapping, WalkerOS, Flow, Hint } from '@walkeros/core';
2
+ import * as _walkeros_core_dev from '@walkeros/core/dev';
3
+ import { z } from '@walkeros/core/dev';
2
4
 
5
+ declare module '@walkeros/core' {
6
+ interface SourceMap {
7
+ ga4: {
8
+ type: 'ga4';
9
+ /** GA4 `p` param, when sent. */
10
+ platform?: string;
11
+ /** Raw GA4 page load id (`_p`), shared by every hit of one page load. */
12
+ pageLoadId?: string;
13
+ /** Raw GA4 hit sequence counter (`_s`) within the page load. */
14
+ hitSequence?: string;
15
+ };
16
+ }
17
+ }
3
18
  /** Raw input to the decoder. Origin-agnostic (express, lambda, pubsub, etc). */
4
19
  interface GA4Request {
5
20
  /** Full request URL including query string. */
@@ -118,6 +133,11 @@ interface GA4Settings {
118
133
  * String at config time, compiled to RegExp once at init.
119
134
  */
120
135
  tidPattern?: string;
136
+ /**
137
+ * Maximum number of events (POST body lines) decoded from one request.
138
+ * A request above the cap is dropped whole. Default `100`.
139
+ */
140
+ maxEvents?: number;
121
141
  }
122
142
  /** Per-event mapping rule keyed by GA4 event name. */
123
143
  type GA4Mapping = Record<string, Mapping.Rule | undefined> & {
@@ -153,6 +173,54 @@ declare const defaultMapping: GA4Mapping;
153
173
  */
154
174
  declare function mapHitToEvents(hit: GA4Hit, mapping: GA4Mapping): WalkerOS.DeepPartialEvent[];
155
175
 
176
+ declare const SettingsSchema: z.ZodObject<{
177
+ mapping: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
178
+ name: z.ZodOptional<z.ZodString>;
179
+ data: z.ZodOptional<z.ZodUnion<readonly [z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, z.ZodArray<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>]>>;
180
+ settings: z.ZodOptional<z.ZodUnknown>;
181
+ condition: z.ZodOptional<z.ZodString>;
182
+ consent: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
183
+ policy: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>>;
184
+ batch: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodObject<{
185
+ wait: z.ZodOptional<z.ZodNumber>;
186
+ size: z.ZodOptional<z.ZodNumber>;
187
+ age: z.ZodOptional<z.ZodNumber>;
188
+ }, z.core.$strip>]>>;
189
+ include: z.ZodOptional<z.ZodArray<z.ZodString>>;
190
+ ignore: z.ZodOptional<z.ZodBoolean>;
191
+ silent: z.ZodOptional<z.ZodBoolean>;
192
+ extend: z.ZodOptional<z.ZodObject<{
193
+ name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
194
+ data: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, z.ZodArray<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>]>>>;
195
+ settings: z.ZodOptional<z.ZodNullable<z.ZodUnknown>>;
196
+ condition: z.ZodOptional<z.ZodNullable<z.ZodString>>;
197
+ consent: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodBoolean>>>;
198
+ policy: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>>>;
199
+ batch: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodNumber, z.ZodObject<{
200
+ wait: z.ZodOptional<z.ZodNumber>;
201
+ size: z.ZodOptional<z.ZodNumber>;
202
+ age: z.ZodOptional<z.ZodNumber>;
203
+ }, z.core.$strip>]>>>;
204
+ include: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
205
+ ignore: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
206
+ silent: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
207
+ }, z.core.$strip>>;
208
+ remove: z.ZodOptional<z.ZodArray<z.ZodString>>;
209
+ }, z.core.$strip>>>;
210
+ tidPattern: z.ZodOptional<z.ZodString>;
211
+ maxEvents: z.ZodOptional<z.ZodNumber>;
212
+ }, z.core.$strip>;
213
+ type Settings = z.infer<typeof SettingsSchema>;
214
+
215
+ declare const settings: _walkeros_core_dev.JSONSchema;
216
+
217
+ type index$1_Settings = Settings;
218
+ declare const index$1_SettingsSchema: typeof SettingsSchema;
219
+ declare const index$1_settings: typeof settings;
220
+ declare namespace index$1 {
221
+ export { type index$1_Settings as Settings, index$1_SettingsSchema as SettingsSchema, index$1_settings as settings };
222
+ }
223
+
156
224
  declare const pageView: Flow.StepExample;
157
225
  declare const purchase: Flow.StepExample;
158
226
  declare const viewItem: Flow.StepExample;
@@ -189,4 +257,4 @@ declare namespace index {
189
257
 
190
258
  declare const hints: Hint.Hints;
191
259
 
192
- export { type GA4Event, type GA4EventParams, type GA4Hit, type GA4HitParams, type GA4Item, type GA4Mapping, type GA4Request, type GA4Settings, defaultMapping, index as examples, hints, mapHitToEvents, parseBody, parseConsent, parseItem, parseQuery, parseRequest };
260
+ export { type GA4Event, type GA4EventParams, type GA4Hit, type GA4HitParams, type GA4Item, type GA4Mapping, type GA4Request, type GA4Settings, defaultMapping, index as examples, hints, mapHitToEvents, parseBody, parseConsent, parseItem, parseQuery, parseRequest, index$1 as schemas };
package/dist/dev.js CHANGED
@@ -1 +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:()=>h,examples:()=>k,hints:()=>T,mapHitToEvents:()=>_,parseBody:()=>s,parseConsent:()=>v,parseItem:()=>u,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 l(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 u(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)||l(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])=>u(e));return{en:e.en,params:t,items:r}}(e))}}var h={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 _(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){let e=b(i.data,n);if(i.remove&&(0,f.isObject)(e))for(const t of i.remove)e=(0,f.deleteByPath)(e,t);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 k={};n(k,{step:()=>E});var E={};n(E,{addToCart:()=>I,batchPost:()=>j,beginCheckout:()=>S,consentDenied:()=>R,customEvent:()=>q,login:()=>L,pageView:()=>O,purchase:()=>P,scroll:()=>G,search:()=>M,userEngagementIgnored:()=>U,viewItem:()=>x});var N="1700000000";function A(e){return{id:"p1",timestamp:17e11,timing:0,trigger:"ga4",user:{device:"cid-1",session:N},globals:{},source:{type:"ga4"},consent:{},...e}}var O={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="+N+"&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/"}})]]},P={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="+N+"&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"}})]]},x={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="+N+"&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}})]]},I={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="+N+"&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="+N+"&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"}})]]},G={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="+N+"&en=scroll&epn.percent_scrolled=90"},out:[["return",A({name:"page scroll",entity:"page",action:"scroll",data:{percent:90}})]]},M={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="+N+"&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="+N+"&en=login&ep.method=google"},out:[["return",A({name:"session login",entity:"session",action:"login",data:{method:"google"}})]]},q={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="+N+"&en=newsletter_subscribe&ep.source=footer"},out:[["return",A({name:"ga4 track",entity:"ga4",action:"track",data:{event_name:"newsletter_subscribe"}})]]},R={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="+N+"&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}})]]},U={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="+N+"&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="+N,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}})]]},T={wiring:{text:"This is a request-decoder: it reads the raw GA4 hit from ctx.ingest (ctx.ingest.url, optional ctx.ingest.body) and decodes it into walkerOS events. Place it on a server source's before chain (source.before), NOT on source.next and NOT on a destination.before chain; it runs before the collector to turn the incoming request into events. The source populates ctx.ingest from its config.ingest, which MUST be a map operator: { map: { url: { key: 'url' }, path: { key: 'path' }, method: { key: 'method' }, body: { key: 'body' } } }. The keys are direct fields on the Express req (no req. prefix): url is the full request URL with query string (what the decoder reads), path drives the /g/collect before match, method and body carry POST batches. A bare object like { url: 'req.url' } is silently inert: with no map operator the source passes the whole req through getMappingValue, a real Express req fails the property check (it carries functions and circular refs), ctx.ingest stays empty, and the decoder skips the hit. A pre-parsed JSON body will not decode; pass the raw body text.",code:[{lang:"json",code:JSON.stringify({sources:{http:{package:"@walkeros/server-source-express",config:{ingest:{map:{url:{key:"url"},path:{key:"path"},method:{key:"method"},body:{key:"body"}}}},before:"ga4"}},transformers:{ga4:{package:"@walkeros/transformer-ga4"}}},null,2)}]}};//# sourceMappingURL=dev.js.map
1
+ "use strict";var e,t=Object.defineProperty,a=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,n=Object.prototype.hasOwnProperty,i=(e,a)=>{for(var r in a)t(e,r,{get:a[r],enumerable:!0})},o={};function s(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 c(e){return function(e){return e?e.split(/\r?\n/).map(e=>e.trim()).filter(e=>e.length>0):[]}(e).map(e=>{const t={};return new URLSearchParams(e).forEach((e,a)=>{t[a]=e}),t})}i(o,{defaultMapping:()=>y,examples:()=>O,hints:()=>D,mapHitToEvents:()=>w,parseBody:()=>c,parseConsent:()=>v,parseItem:()=>u,parseQuery:()=>s,parseRequest:()=>h,schemas:()=>k}),module.exports=(e=o,((e,i,o,s)=>{if(i&&"object"==typeof i||"function"==typeof i)for(let c of r(i))n.call(e,c)||c===o||t(e,c,{get:()=>i[c],enumerable:!(s=a(i,c))||s.enumerable});return e})(t({},"__esModule",{value:!0}),e));var d={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"},p={pr:"price",qt:"quantity",ds:"discount",lp:"listPosition"};function l(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 m(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 u(e){const t={custom:{}},a=new Map,r=new Map;for(const n of e.split("~")){if(0===n.length)continue;const e=/^([kv])(\d+)(.*)$/.exec(n);if(e){const[,t,n,i]=e;"k"===t?a.set(n,i):r.set(n,i);continue}if(n.length<2)continue;const i=n.slice(0,2),o=n.slice(2),s=d[i];if(void 0!==s){l(t,s,o);continue}const c=p[i];if(void 0!==c){const e=Number(o);Number.isNaN(e)||m(t,c,e);continue}}for(const[e,n]of a){const a=r.get(e);void 0!==a&&(t.custom[n]=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 h(e){const t=s(e.url),a={},r={};for(const[e,n]of Object.entries(t))g.has(e)?a[e]=n:r[e]=n;const n=e.body?c(e.body):[];return{hit:a,events:(n.length>0?n: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,n]of Object.entries(e)){if("en"===r)continue;const e=/^pr(\d+)$/.exec(r);if(e)a.push([Number(e[1]),n]);else if(r.startsWith("ep."))t.ep[r.slice(3)]=n;else{if(r.startsWith("epn.")){const e=Number(n);Number.isNaN(e)||(t.epn[r.slice(4)]=e);continue}if(r.startsWith("up."))t.up[r.slice(3)]=n;else{if(r.startsWith("upn.")){const e=Number(n);Number.isNaN(e)||(t.upn[r.slice(4)]=e);continue}if("_et"===r){const e=Number(n);Number.isNaN(e)||(t._et=e);continue}"_c"!==r||(t._c=n)}}}a.sort((e,t)=>e[0]-t[0]);const r=a.map(([,e])=>u(e));return{en:e.en,params:t,items:r}}(e))}}var y={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"),_=require("@walkeros/core");function w(e,t){const a=[];return e.events.forEach((r,n)=>{const i=function(e,t,a,r){const n=r[t.en]??r["*"];if(!n)return null;const i=Array.isArray(n)?n[0]:n;if(!i||i.ignore)return null;const o={hit:e,params:t.params,items:t.items,en:t.en,...t.items.length>0?{firstItem:t.items[0]}:{}},s={};if(i.name){const[e,...t]=i.name.split(" ");s.name=i.name,s.entity=e,s.action=t.join(" ")}if(void 0!==i.data){let e=b(i.data,o);if(i.remove&&(0,f.isObject)(e))for(const t of i.remove)e=(0,f.deleteByPath)(e,t);void 0!==e&&(s.data=e)}s.user={...void 0!==e.uid?{id:e.uid}:{},...void 0!==e.cid?{device:e.cid}:{},...void 0!==e.sid?{session:e.sid}:{}},s.globals={...void 0!==e.ul?{language:e.ul}:{},...void 0!==e.sr?{screen:e.sr}:{}},s.source={type:"ga4",...void 0!==e.p?{platform:e.p}:{},...void 0!==e._p?{pageLoadId:e._p}:{},...void 0!==e._s?{hitSequence:e._s}:{}},s.consent=v(e),s.id=function(e,t){const{_p:a,_s:r}=e;return a&&r?(0,_.deriveSpanId)(JSON.stringify(["ga4",e.tid??"",e.cid??"",a,r]),t):(0,_.getSpanId)()}(e,a);const c=e.sid?Number(e.sid):NaN;s.timestamp=!Number.isNaN(c)&&c>0?1e3*c:Date.now(),s.timing=t.params._et??0,s.trigger="ga4",t.items.length>0&&(s.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:{}}}));return s}(e.hit,r,n,t);i&&a.push(i)}),a}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,n]of Object.entries(e.map)){const e=b(n,t);void 0!==e&&(a[r]=e)}return a}}}}var k={};i(k,{SettingsSchema:()=>N,settings:()=>S});var E=require("@walkeros/core/dev"),A=require("@walkeros/core/dev"),N=A.z.object({mapping:A.z.record(A.z.string(),A.schemas.MappingSchemas.RuleSchema).optional().describe("Mapping rules keyed by GA4 event name (`en`), `'*'` for unknown events. A rule replaces the matching default unless it sets `extend` or `remove`; `ignore: true` drops the event."),tidPattern:A.z.string().optional().describe("Regex string the tracking ID (`tid`) must match, compiled once at init. Default `^G-`, which drops Ads (`AW-`) and DC (`DC-`) hits."),maxEvents:A.z.number().int().min(1).optional().describe("Maximum number of events (POST body lines) decoded from one request. A request above the cap is dropped whole. Default 100.")}).describe("GA4 transformer: decodes GA4 Measurement Protocol v2 requests from ctx.ingest into walkerOS events."),S=(0,E.zodToSchema)(N),O={};i(O,{step:()=>P});var P={};i(P,{addToCart:()=>L,batchPost:()=>W,beginCheckout:()=>T,consentDenied:()=>C,customEvent:()=>X,login:()=>U,pageView:()=>G,purchase:()=>q,scroll:()=>R,search:()=>j,userEngagementIgnored:()=>F,viewItem:()=>M});var x="1700000000";function I(e,t,a){return{id:t,timestamp:17e11,timing:0,trigger:"ga4",user:{device:"cid-1",session:x},globals:{},source:{type:"ga4",pageLoadId:"p1",hitSequence:e},consent:{},...a}}var G={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&_s=1&cid=cid-1&sid="+x+"&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",I("1","619920d96220c8f5",{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/"}})]]},q={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&_s=2&cid=cid-1&sid="+x+"&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",I("2","07590930f34326b6",{name:"order complete",entity:"order",action:"complete",data:{id:"T-9001",currency:"EUR",total:149.97,tax:23.97,shipping:4.95,coupon:"WELCOME10"}})]]},M={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&_s=3&cid=cid-1&sid="+x+"&en=view_item&ep.currency=EUR&epn.value=129.99"},out:[["return",I("3","a6ef03f16d295aef",{name:"product view",entity:"product",action:"view",data:{currency:"EUR",value:129.99}})]]},L={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&_s=4&cid=cid-1&sid="+x+"&en=add_to_cart&ep.currency=EUR&epn.value=129.99"},out:[["return",I("4","21854a0390595250",{name:"product add",entity:"product",action:"add",data:{currency:"EUR",value:129.99}})]]},T={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&_s=5&cid=cid-1&sid="+x+"&en=begin_checkout&ep.currency=EUR&epn.value=149.97&ep.coupon=WELCOME10"},out:[["return",I("5","04a3521d6259b559",{name:"order start",entity:"order",action:"start",data:{currency:"EUR",value:149.97,coupon:"WELCOME10"}})]]},R={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&_s=6&cid=cid-1&sid="+x+"&en=scroll&epn.percent_scrolled=90"},out:[["return",I("6","f4211610dcdb861a",{name:"page scroll",entity:"page",action:"scroll",data:{percent:90}})]]},j={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&_s=7&cid=cid-1&sid="+x+"&en=search&ep.search_term=trail%20runner"},out:[["return",I("7","697710c0b9b403d3",{name:"search submit",entity:"search",action:"submit",data:{term:"trail runner"}})]]},U={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&_s=8&cid=cid-1&sid="+x+"&en=login&ep.method=google"},out:[["return",I("8","e6aa65225205bcf4",{name:"session login",entity:"session",action:"login",data:{method:"google"}})]]},X={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&_s=9&cid=cid-1&sid="+x+"&en=newsletter_subscribe&ep.source=footer"},out:[["return",I("9","d7dff1eae9d981dd",{name:"ga4 track",entity:"ga4",action:"track",data:{event_name:"newsletter_subscribe"}})]]},C={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&_s=10&cid=cid-1&sid="+x+"&gcs=G100&en=page_view&dl=https%3A%2F%2Fx&dt=X"},out:[["return",I("10","eeb7b2eaa3880daf",{name:"page view",entity:"page",action:"view",data:{id:"https://x",title:"X"},consent:{marketing:!1,analytics:!1}})]]},F={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&_s=11&cid=cid-1&sid="+x+"&en=user_engagement&_et=1500"},out:[["return",!1]]},W={title:"Batched POST (fan-out)",description:"A single POST request carrying two newline-separated events fans out into two walkerOS events, each with its own id.",in:{url:"https://www.google-analytics.com/g/collect?v=2&tid=G-EXAMPLE&_p=p1&_s=12&cid=cid-1&sid="+x,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",I("12","fa7fa5554916cbb5",{name:"product add",entity:"product",action:"add",data:{currency:"EUR",value:19.99}})],["return",I("12","fa82615549188e00",{name:"product add",entity:"product",action:"add",data:{currency:"EUR",value:29.99}})]]},D={wiring:{text:"This is a request-decoder: it reads the raw GA4 hit from ctx.ingest (ctx.ingest.url, optional ctx.ingest.body) and decodes it into walkerOS events. Place it on a server source's before chain (source.before), NOT on source.next and NOT on a destination.before chain; it runs before the collector to turn the incoming request into events. The source populates ctx.ingest from its config.ingest, which MUST be a map operator: { map: { url: { key: 'url' }, path: { key: 'path' }, method: { key: 'method' }, body: { key: 'body' } } }. The keys are direct field paths on the request scope (no req. prefix): url is the full request URL with query string (what the decoder reads), path drives the /g/collect before match, method and body carry POST batches. A bare object like { url: 'req.url' } is silently inert: without an operator no field is extracted, ctx.ingest stays empty, and the decoder skips the hit. A pre-parsed JSON body will not decode; pass the raw body text. The express source listens on /collect by default and matches paths exactly; gtag.js sends to /g/collect, so set settings.paths: ['/g/collect'] or every hit gets a 404.",code:[{lang:"json",code:JSON.stringify({sources:{http:{package:"@walkeros/server-source-express",config:{settings:{paths:["/g/collect"]},ingest:{map:{url:{key:"url"},path:{key:"path"},method:{key:"method"},body:{key:"body"}}}},before:"ga4"}},transformers:{ga4:{package:"@walkeros/transformer-ga4"}}},null,2)}]},"source-choice":{text:"gtag.js sends a single event as a POST without a body (parameters in the query string) and several events as one text/plain POST body, one event per line. @walkeros/server-source-express keeps a text/plain body that is not JSON as ingest.body, so it decodes GET, body-less POST and batched POST hits alike. @walkeros/server-source-fetch and sourceCloudFunction (@walkeros/server-source-gcp) do too, with the same ingest and before config. sourceLambda (@walkeros/server-source-aws) answers a POST without a body with 400, so single-event hits sent that way are lost on Lambda."}};//# sourceMappingURL=dev.js.map
package/dist/dev.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/dev.ts","../src/parse.ts","../src/defaults.ts","../src/map.ts","../src/examples/index.ts","../src/examples/step.ts","../src/hints.ts"],"sourcesContent":["/**\n * Development exports for transformer-ga4.\n * Used by website documentation, step examples, and downstream tests.\n *\n * Mirrors the validator's dev.ts pattern: only primitives leak out here, the\n * transformer instance is reached via the package entry (`./index.ts`).\n */\n\nexport {\n parseRequest,\n parseQuery,\n parseBody,\n parseItem,\n parseConsent,\n} from './parse';\nexport { defaultMapping } from './defaults';\nexport { mapHitToEvents } from './map';\nexport type {\n GA4Settings,\n GA4Mapping,\n GA4Request,\n GA4Hit,\n GA4Event,\n GA4EventParams,\n GA4HitParams,\n GA4Item,\n} from './types';\n\nexport * as examples from './examples';\nexport { hints } from './hints';\n","import type { WalkerOS } from '@walkeros/core';\nimport type {\n GA4Event,\n GA4EventParams,\n GA4Hit,\n GA4HitParams,\n GA4Item,\n GA4Request,\n} from './types';\n\nexport function parseQuery(url: string): Record<string, string> {\n const out: Record<string, string> = {};\n const qIdx = url.indexOf('?');\n if (qIdx === -1) return out;\n const usp = new URLSearchParams(url.slice(qIdx + 1));\n usp.forEach((value, key) => {\n out[key] = value;\n });\n return out;\n}\n\nexport function parseBody(body: string): Record<string, string>[] {\n if (!body) return [];\n return body\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter((line) => line.length > 0)\n .map((line) => {\n const out: Record<string, string> = {};\n const usp = new URLSearchParams(line);\n usp.forEach((v, k) => {\n out[k] = v;\n });\n return out;\n });\n}\n\n// Two separate dispatch maps keyed by 2-char prefix.\n// Split by type so the assignment site stays type-safe (no cast).\nconst ITEM_STRING_FIELDS: Readonly<Record<string, keyof GA4Item>> = {\n id: 'id',\n nm: 'name',\n br: 'brand',\n ca: 'category',\n c2: 'category2',\n c3: 'category3',\n c4: 'category4',\n c5: 'category5',\n va: 'variant',\n cp: 'coupon',\n ln: 'listName',\n li: 'listId',\n lo: 'locationId',\n af: 'affiliation',\n cn: 'creativeName',\n cs: 'creativeSlot',\n pi: 'promotionId',\n pn: 'promotionName',\n};\n\nconst ITEM_NUMBER_FIELDS: Readonly<Record<string, keyof GA4Item>> = {\n pr: 'price',\n qt: 'quantity',\n ds: 'discount',\n lp: 'listPosition',\n};\n\nfunction setItemString(item: GA4Item, key: keyof GA4Item, value: string): void {\n // Narrow assignment by key — these are the string-typed fields.\n switch (key) {\n case 'id':\n item.id = value;\n return;\n case 'name':\n item.name = value;\n return;\n case 'brand':\n item.brand = value;\n return;\n case 'category':\n item.category = value;\n return;\n case 'category2':\n item.category2 = value;\n return;\n case 'category3':\n item.category3 = value;\n return;\n case 'category4':\n item.category4 = value;\n return;\n case 'category5':\n item.category5 = value;\n return;\n case 'variant':\n item.variant = value;\n return;\n case 'coupon':\n item.coupon = value;\n return;\n case 'listName':\n item.listName = value;\n return;\n case 'listId':\n item.listId = value;\n return;\n case 'locationId':\n item.locationId = value;\n return;\n case 'affiliation':\n item.affiliation = value;\n return;\n case 'creativeName':\n item.creativeName = value;\n return;\n case 'creativeSlot':\n item.creativeSlot = value;\n return;\n case 'promotionId':\n item.promotionId = value;\n return;\n case 'promotionName':\n item.promotionName = value;\n return;\n }\n}\n\nfunction setItemNumber(item: GA4Item, key: keyof GA4Item, value: number): void {\n switch (key) {\n case 'price':\n item.price = value;\n return;\n case 'quantity':\n item.quantity = value;\n return;\n case 'discount':\n item.discount = value;\n return;\n case 'listPosition':\n item.listPosition = value;\n return;\n }\n}\n\nexport function parseItem(value: string): GA4Item {\n const item: GA4Item = { custom: {} };\n const customKeys = new Map<string, string>();\n const customVals = new Map<string, string>();\n\n for (const raw of value.split('~')) {\n if (raw.length === 0) continue;\n\n // Variable-length k<N>/v<N> (must match before 2-char prefix lookup\n // because k10/v10 etc are wider than 2 chars).\n const kvMatch = /^([kv])(\\d+)(.*)$/.exec(raw);\n if (kvMatch) {\n const [, kind, idx, val] = kvMatch;\n if (kind === 'k') customKeys.set(idx, val);\n else customVals.set(idx, val);\n continue;\n }\n\n if (raw.length < 2) continue;\n const prefix = raw.slice(0, 2);\n const val = raw.slice(2);\n\n const stringKey = ITEM_STRING_FIELDS[prefix];\n if (stringKey !== undefined) {\n setItemString(item, stringKey, val);\n continue;\n }\n const numberKey = ITEM_NUMBER_FIELDS[prefix];\n if (numberKey !== undefined) {\n const n = Number(val);\n if (!Number.isNaN(n)) setItemNumber(item, numberKey, n);\n continue;\n }\n }\n\n // Pair k<N> with v<N>; drop unmatched.\n for (const [idx, key] of customKeys) {\n const v = customVals.get(idx);\n if (v !== undefined) item.custom[key] = v;\n }\n return item;\n}\n\nexport function parseConsent(hit: { gcs?: string }): WalkerOS.Consent {\n const gcs = hit.gcs;\n if (!gcs || !/^G[01]{3}$/.test(gcs)) return {};\n // gcs[1] is reserved (always '1' for current consent mode v2)\n return {\n marketing: gcs[2] === '1', // ad_storage\n analytics: gcs[3] === '1', // analytics_storage\n };\n}\n\nconst HIT_PARAM_KEYS = new Set([\n 'v',\n 'tid',\n 'cid',\n 'sid',\n 'sct',\n 'seg',\n '_p',\n '_z',\n 'gtm',\n 'dl',\n 'dt',\n 'dr',\n 'ul',\n 'sr',\n 'uid',\n '_dbg',\n '_s',\n '_ss',\n '_fv',\n 'gcs',\n 'gcd',\n 'dma',\n 'dma_cps',\n 'npa',\n 'p',\n]);\n\nexport function parseRequest(req: GA4Request): GA4Hit {\n const queryParams = parseQuery(req.url);\n const hit: GA4HitParams = {};\n const queryEventParams: Record<string, string> = {};\n\n // Split URL params into hit-level vs event-level.\n for (const [k, v] of Object.entries(queryParams)) {\n if (HIT_PARAM_KEYS.has(k)) hit[k] = v;\n else queryEventParams[k] = v;\n }\n\n // GET: event params live in the URL alongside hit params.\n // POST: in body lines.\n const bodyLines = req.body ? parseBody(req.body) : [];\n const rawEvents =\n bodyLines.length > 0\n ? bodyLines\n : Object.keys(queryEventParams).length > 0\n ? [queryEventParams]\n : [];\n\n const events: GA4Event[] = rawEvents\n .filter((raw) => typeof raw.en === 'string' && raw.en.length > 0)\n .map((raw) => buildEvent(raw));\n\n return { hit, events };\n}\n\nfunction buildEvent(raw: Record<string, string>): GA4Event {\n const params: GA4EventParams = { ep: {}, epn: {}, up: {}, upn: {} };\n const itemEntries: Array<[number, string]> = [];\n\n for (const [k, v] of Object.entries(raw)) {\n if (k === 'en') continue;\n\n // pr<N> items\n const prMatch = /^pr(\\d+)$/.exec(k);\n if (prMatch) {\n itemEntries.push([Number(prMatch[1]), v]);\n continue;\n }\n\n // Dotted-key nesting\n if (k.startsWith('ep.')) {\n params.ep[k.slice(3)] = v;\n continue;\n }\n if (k.startsWith('epn.')) {\n const n = Number(v);\n if (!Number.isNaN(n)) params.epn[k.slice(4)] = n;\n continue;\n }\n if (k.startsWith('up.')) {\n params.up[k.slice(3)] = v;\n continue;\n }\n if (k.startsWith('upn.')) {\n const n = Number(v);\n if (!Number.isNaN(n)) params.upn[k.slice(4)] = n;\n continue;\n }\n\n // Standalone numeric keys\n if (k === '_et') {\n const n = Number(v);\n if (!Number.isNaN(n)) params._et = n;\n continue;\n }\n if (k === '_c') {\n params._c = v;\n continue;\n }\n // Unknown standalone keys: drop. Add to GA4EventParams type if a future\n // need surfaces.\n }\n\n itemEntries.sort((a, b) => a[0] - b[0]);\n const items = itemEntries.map(([, v]) => parseItem(v));\n\n return { en: raw.en, params, items };\n}\n","import type { GA4Mapping } from './types';\n\n/**\n * Default GA4 event-name → walkerOS mapping rules.\n * Users may override or extend these via settings.mapping at config time.\n * The `'*'` key is the fallback for unknown event names.\n *\n * Field naming for `data.map`:\n * - Monetary: `currency` from `ep.currency`, `value`/`total` from `epn.value`,\n * `tax` from `epn.tax`, `shipping` from `epn.shipping`, `coupon` from\n * `ep.coupon`.\n * - Promotions read from `firstItem` (synthetic `items[0]` reference exposed by\n * the mapper), since GA4 encodes promotion info inside item tilde strings.\n */\nexport const defaultMapping: GA4Mapping = {\n // --- page ---\n page_view: {\n name: 'page view',\n data: {\n map: {\n id: 'hit.dl',\n title: 'hit.dt',\n referrer: 'hit.dr',\n },\n },\n },\n\n // --- ecommerce ---\n purchase: {\n name: 'order complete',\n data: {\n map: {\n id: 'params.ep.transaction_id',\n currency: 'params.ep.currency',\n total: 'params.epn.value',\n tax: 'params.epn.tax',\n shipping: 'params.epn.shipping',\n coupon: 'params.ep.coupon',\n },\n },\n },\n view_item: {\n name: 'product view',\n data: {\n map: {\n currency: 'params.ep.currency',\n value: 'params.epn.value',\n },\n },\n },\n add_to_cart: {\n name: 'product add',\n data: {\n map: {\n currency: 'params.ep.currency',\n value: 'params.epn.value',\n },\n },\n },\n remove_from_cart: {\n name: 'product remove',\n data: {\n map: {\n currency: 'params.ep.currency',\n value: 'params.epn.value',\n },\n },\n },\n view_cart: {\n name: 'cart view',\n data: {\n map: {\n currency: 'params.ep.currency',\n value: 'params.epn.value',\n },\n },\n },\n begin_checkout: {\n name: 'order start',\n data: {\n map: {\n currency: 'params.ep.currency',\n value: 'params.epn.value',\n coupon: 'params.ep.coupon',\n },\n },\n },\n add_shipping_info: {\n name: 'order shipping',\n data: {\n map: {\n currency: 'params.ep.currency',\n value: 'params.epn.value',\n tier: 'params.ep.shipping_tier',\n },\n },\n },\n add_payment_info: {\n name: 'order payment',\n data: {\n map: {\n currency: 'params.ep.currency',\n value: 'params.epn.value',\n type: 'params.ep.payment_type',\n },\n },\n },\n refund: {\n name: 'order refund',\n data: {\n map: {\n id: 'params.ep.transaction_id',\n currency: 'params.ep.currency',\n total: 'params.epn.value',\n },\n },\n },\n add_to_wishlist: {\n name: 'wishlist add',\n data: {\n map: {\n currency: 'params.ep.currency',\n value: 'params.epn.value',\n },\n },\n },\n\n // --- list / promotion ---\n view_item_list: {\n name: 'list view',\n data: {\n map: {\n id: 'params.ep.item_list_id',\n name: 'params.ep.item_list_name',\n },\n },\n },\n select_item: {\n name: 'product click',\n data: {\n map: {\n list_id: 'params.ep.item_list_id',\n list_name: 'params.ep.item_list_name',\n },\n },\n },\n view_promotion: {\n name: 'promotion view',\n data: {\n map: {\n id: 'firstItem.promotionId',\n name: 'firstItem.promotionName',\n creative: 'firstItem.creativeName',\n slot: 'firstItem.creativeSlot',\n },\n },\n },\n select_promotion: {\n name: 'promotion click',\n data: {\n map: {\n id: 'firstItem.promotionId',\n name: 'firstItem.promotionName',\n creative: 'firstItem.creativeName',\n slot: 'firstItem.creativeSlot',\n },\n },\n },\n select_content: {\n name: 'content select',\n data: {\n map: {\n type: 'params.ep.content_type',\n id: 'params.ep.content_id',\n },\n },\n },\n\n // --- engagement ---\n scroll: {\n name: 'page scroll',\n data: {\n map: {\n percent: 'params.epn.percent_scrolled',\n },\n },\n },\n click: {\n name: 'link click',\n data: {\n map: {\n url: 'params.ep.link_url',\n domain: 'params.ep.link_domain',\n outbound: 'params.ep.outbound',\n },\n },\n },\n file_download: {\n name: 'file download',\n data: {\n map: {\n name: 'params.ep.file_name',\n extension: 'params.ep.file_extension',\n url: 'params.ep.link_url',\n },\n },\n },\n video_start: {\n name: 'video start',\n data: {\n map: {\n title: 'params.ep.video_title',\n duration: 'params.epn.video_duration',\n current: 'params.epn.video_current_time',\n percent: 'params.epn.video_percent',\n },\n },\n },\n video_progress: {\n name: 'video progress',\n data: {\n map: {\n title: 'params.ep.video_title',\n duration: 'params.epn.video_duration',\n current: 'params.epn.video_current_time',\n percent: 'params.epn.video_percent',\n },\n },\n },\n video_complete: {\n name: 'video complete',\n data: {\n map: {\n title: 'params.ep.video_title',\n duration: 'params.epn.video_duration',\n current: 'params.epn.video_current_time',\n percent: 'params.epn.video_percent',\n },\n },\n },\n form_start: {\n name: 'form start',\n data: {\n map: {\n id: 'params.ep.form_id',\n name: 'params.ep.form_name',\n destination: 'params.ep.form_destination',\n },\n },\n },\n form_submit: {\n name: 'form submit',\n data: {\n map: {\n id: 'params.ep.form_id',\n name: 'params.ep.form_name',\n destination: 'params.ep.form_destination',\n },\n },\n },\n search: {\n name: 'search submit',\n data: {\n map: {\n term: 'params.ep.search_term',\n },\n },\n },\n login: {\n name: 'session login',\n data: {\n map: {\n method: 'params.ep.method',\n },\n },\n },\n sign_up: {\n name: 'session signup',\n data: {\n map: {\n method: 'params.ep.method',\n },\n },\n },\n generate_lead: {\n name: 'lead generate',\n data: {\n map: {\n currency: 'params.ep.currency',\n value: 'params.epn.value',\n },\n },\n },\n share: {\n name: 'content share',\n data: {\n map: {\n method: 'params.ep.method',\n type: 'params.ep.content_type',\n id: 'params.ep.item_id',\n },\n },\n },\n\n // --- auto-fired noise: ignore by default (users can override) ---\n user_engagement: { ignore: true },\n session_start: { ignore: true },\n first_visit: { ignore: true },\n\n // --- fallback for unknown event names ---\n '*': {\n name: 'ga4 track',\n data: {\n map: {\n event_name: 'en',\n },\n },\n },\n};\n","import type { Mapping, WalkerOS } from '@walkeros/core';\nimport { getByPath, getId, deleteByPath, isObject } from '@walkeros/core';\nimport type {\n GA4Event,\n GA4Hit,\n GA4HitParams,\n GA4Item,\n GA4Mapping,\n} from './types';\nimport { parseConsent } from './parse';\n\n/**\n * Lookup root for mapping path resolution. Mapping rules reference keys via\n * dotted paths: `hit.dl`, `params.ep.transaction_id`, `params.epn.value`, `items`.\n *\n * `en` exposes the GA4 event name (used by the `*` fallback so unknown events\n * can carry their original name through). `firstItem` exposes `items[0]` so\n * promotion-style mappings can resolve `firstItem.promotionId` etc. without\n * needing array-index syntax in `getByPath`.\n *\n * Typed as `Record<string, unknown> & { ... }` so `getByPath` (which accepts\n * unknown) is happy without any narrowing cast on the call site.\n */\ntype LookupRoot = Record<string, unknown> & {\n hit: GA4HitParams;\n params: GA4Event['params'];\n items: GA4Event['items'];\n en: string;\n firstItem?: GA4Item;\n};\n\n/**\n * Convert a parsed GA4 hit into zero or more walkerOS events.\n * One GA4 hit may carry several events (POST batch); each is mapped\n * independently with hit-level metadata merged in.\n */\nexport function mapHitToEvents(\n hit: GA4Hit,\n mapping: GA4Mapping,\n): WalkerOS.DeepPartialEvent[] {\n const out: WalkerOS.DeepPartialEvent[] = [];\n for (const event of hit.events) {\n const mapped = mapOneEvent(hit.hit, event, mapping);\n if (mapped) out.push(mapped);\n }\n return out;\n}\n\nfunction mapOneEvent(\n hitParams: GA4HitParams,\n event: GA4Event,\n mapping: GA4Mapping,\n): WalkerOS.DeepPartialEvent | null {\n const ruleEntry = mapping[event.en] ?? mapping['*'];\n if (!ruleEntry) return null;\n // For v1, only single-rule entries are supported (no array fan-out).\n const rule: Mapping.Rule = Array.isArray(ruleEntry)\n ? ruleEntry[0]\n : ruleEntry;\n if (!rule || rule.ignore) return null;\n\n const lookup: LookupRoot = {\n hit: hitParams,\n params: event.params,\n items: event.items,\n en: event.en,\n ...(event.items.length > 0 ? { firstItem: event.items[0] } : {}),\n };\n\n const evaluated: WalkerOS.DeepPartialEvent = {};\n\n if (rule.name) {\n const [entity, ...rest] = rule.name.split(' ');\n evaluated.name = rule.name;\n evaluated.entity = entity;\n evaluated.action = rest.join(' ');\n }\n\n if (rule.data !== undefined) {\n let data = evalValue(rule.data, lookup);\n if (rule.remove && isObject(data)) {\n for (const path of rule.remove) data = deleteByPath(data, path);\n }\n if (data !== undefined) {\n evaluated.data = data as WalkerOS.Properties;\n }\n }\n\n // Hit-level merge: user / globals / source.\n evaluated.user = {\n ...(hitParams.uid !== undefined ? { id: hitParams.uid } : {}),\n ...(hitParams.cid !== undefined ? { device: hitParams.cid } : {}),\n ...(hitParams.sid !== undefined ? { session: hitParams.sid } : {}),\n };\n evaluated.globals = {\n ...(hitParams.ul !== undefined ? { language: hitParams.ul } : {}),\n ...(hitParams.sr !== undefined ? { screen: hitParams.sr } : {}),\n };\n evaluated.source = {\n type: 'ga4',\n ...(hitParams.p !== undefined ? { platform: hitParams.p } : {}),\n };\n\n // Consent from gcs string, id from hit._p (fallback to generated string),\n // timestamp from sid (epoch seconds → ms; falls back to wall-clock now),\n // timing from event._et (ms; 0 if absent), trigger hard-coded to \"ga4\" for v1.\n evaluated.consent = parseConsent(hitParams);\n evaluated.id = hitParams._p ?? getId();\n const sidNum = hitParams.sid ? Number(hitParams.sid) : NaN;\n evaluated.timestamp =\n !Number.isNaN(sidNum) && sidNum > 0 ? sidNum * 1000 : Date.now();\n evaluated.timing = event.params._et ?? 0;\n evaluated.trigger = 'ga4';\n\n if (event.items.length > 0) {\n evaluated.nested = itemsToNested(event.items);\n }\n\n return evaluated;\n}\n\n/**\n * GA4 items → walkerOS nested product entities.\n * Field naming: camelCase GA4Item keys are emitted as snake_case data keys\n * (`listName` → `list_name`, `promotionId` → `promotion_id`, etc).\n * Custom k<N>/v<N> pairs are spread as-is.\n *\n * Returns `WalkerOS.Entities` (i.e. `Array<WalkerOS.Entity>`). Note that the\n * canonical `WalkerOS.Entity` interface uses `entity: string` as the kind\n * discriminator (not `type`).\n */\nfunction itemsToNested(items: GA4Item[]): WalkerOS.Entities {\n return items.map((item): WalkerOS.Entity => {\n const data: WalkerOS.Properties = {};\n if (item.id !== undefined) data.id = item.id;\n if (item.name !== undefined) data.name = item.name;\n if (item.brand !== undefined) data.brand = item.brand;\n if (item.category !== undefined) data.category = item.category;\n if (item.category2 !== undefined) data.category2 = item.category2;\n if (item.category3 !== undefined) data.category3 = item.category3;\n if (item.category4 !== undefined) data.category4 = item.category4;\n if (item.category5 !== undefined) data.category5 = item.category5;\n if (item.variant !== undefined) data.variant = item.variant;\n if (item.price !== undefined) data.price = item.price;\n if (item.quantity !== undefined) data.quantity = item.quantity;\n if (item.coupon !== undefined) data.coupon = item.coupon;\n if (item.discount !== undefined) data.discount = item.discount;\n if (item.listName !== undefined) data.list_name = item.listName;\n if (item.listId !== undefined) data.list_id = item.listId;\n if (item.listPosition !== undefined) data.list_position = item.listPosition;\n if (item.locationId !== undefined) data.location_id = item.locationId;\n if (item.affiliation !== undefined) data.affiliation = item.affiliation;\n if (item.creativeName !== undefined) data.creative_name = item.creativeName;\n if (item.creativeSlot !== undefined) data.creative_slot = item.creativeSlot;\n if (item.promotionId !== undefined) data.promotion_id = item.promotionId;\n if (item.promotionName !== undefined)\n data.promotion_name = item.promotionName;\n for (const [k, v] of Object.entries(item.custom)) data[k] = v;\n return { entity: 'product', data, nested: [], context: {} };\n });\n}\n\n/**\n * Minimal mapping evaluator. v1 supports:\n * - string → path lookup via getByPath\n * - Array<Value> → fallback chain: first non-undefined wins\n * - { value: X } → literal\n * - { key: 'path' } → path lookup\n * - { map: {...} } → recursive object build\n *\n * Deferred to v2: condition, loop, fn, validate, set, consent, $code.\n */\nfunction evalValue(\n value: Mapping.Value | Mapping.Values,\n root: LookupRoot,\n): unknown {\n if (Array.isArray(value)) {\n for (const v of value) {\n const resolved = evalValue(v, root);\n if (resolved !== undefined && resolved !== null) return resolved;\n }\n return undefined;\n }\n if (typeof value === 'string') {\n return getByPath(root, value);\n }\n if (typeof value === 'object' && value !== null) {\n if ('value' in value && value.value !== undefined) return value.value;\n if ('key' in value && typeof value.key === 'string') {\n return getByPath(root, value.key);\n }\n if ('map' in value && value.map) {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value.map)) {\n const resolved = evalValue(v, root);\n if (resolved !== undefined) out[k] = resolved;\n }\n return out;\n }\n }\n return undefined;\n}\n","export * as step from './step';\n","import type { Flow } from '@walkeros/core';\n\n/**\n * Step examples for transformer-ga4.\n *\n * `in` is a raw `GA4Request` (`{ url, body? }`) — the shape the transformer\n * reads from `ctx.ingest`. `out` is the array of effect tuples produced by\n * pushing that request through the transformer:\n *\n * - Mapped event (single): `out: [['return', event]]`\n * - Mapped events (fan-out): `out: [['return', e1], ['return', e2], ...]`\n * - Dropped (ignore / no en): `out: [['return', false]]`\n *\n * Examples set `_p` (becomes `event.id`) and `sid` (becomes `event.timestamp`\n * in ms via `sid * 1000`) so the assertions are deterministic. The synthetic\n * walkerOS event shape mirrors what `mapHitToEvents` produces in `map.ts`:\n * - `entity` + `action` derived from rule.name's first/rest words\n * - `user.{id,device,session}` from `uid/cid/sid`\n * - `source: { type: 'ga4', platform? }` from `p`\n * - `consent` from `gcs` (`G100` → all false, `G111` → all true)\n * - `timing` from event `_et` (defaults to 0 if absent)\n * - `trigger: 'ga4'` (hard-coded in v1)\n * - `nested[]` only set when items are present (POST-only example below)\n */\n\n// --- helpers (typed, no casts) -----------------------------------------------\n\nconst SID = '1700000000'; // → timestamp 1700000000000\n\nfunction ga4Event(overrides: Record<string, unknown>): Record<string, unknown> {\n return {\n id: 'p1',\n timestamp: 1700000000000,\n timing: 0,\n trigger: 'ga4',\n user: { device: 'cid-1', session: SID },\n globals: {},\n source: { type: 'ga4' },\n consent: {},\n ...overrides,\n };\n}\n\n// --- examples ---------------------------------------------------------------\n\nexport const pageView: Flow.StepExample = {\n title: 'Page view',\n description:\n 'A standard GA4 page_view hit decoded to a walkerOS page view with id, title, and referrer.',\n in: {\n url:\n 'https://www.google-analytics.com/g/collect' +\n '?v=2&tid=G-EXAMPLE&_p=p1&cid=cid-1&sid=' +\n SID +\n '&en=page_view' +\n '&dl=https%3A%2F%2Fshop.example.com%2Fproducts%2Fsku-123' +\n '&dt=Trail%20Runner%20Pro' +\n '&dr=https%3A%2F%2Fshop.example.com%2F',\n },\n out: [\n [\n 'return',\n ga4Event({\n name: 'page view',\n entity: 'page',\n action: 'view',\n data: {\n id: 'https://shop.example.com/products/sku-123',\n title: 'Trail Runner Pro',\n referrer: 'https://shop.example.com/',\n },\n }),\n ],\n ],\n};\n\nexport const purchase: Flow.StepExample = {\n title: 'Purchase (canary)',\n description:\n 'A GA4 purchase hit decoded to a walkerOS order complete event with id, currency, total, tax, shipping, and coupon.',\n in: {\n url:\n 'https://www.google-analytics.com/g/collect' +\n '?v=2&tid=G-EXAMPLE&_p=p1&cid=cid-1&sid=' +\n SID +\n '&en=purchase' +\n '&ep.transaction_id=T-9001' +\n '&ep.currency=EUR' +\n '&epn.value=149.97' +\n '&epn.tax=23.97' +\n '&epn.shipping=4.95' +\n '&ep.coupon=WELCOME10',\n },\n out: [\n [\n 'return',\n ga4Event({\n name: 'order complete',\n entity: 'order',\n action: 'complete',\n data: {\n id: 'T-9001',\n currency: 'EUR',\n total: 149.97,\n tax: 23.97,\n shipping: 4.95,\n coupon: 'WELCOME10',\n },\n }),\n ],\n ],\n};\n\nexport const viewItem: Flow.StepExample = {\n title: 'View item',\n description:\n 'A GA4 view_item hit decoded to a walkerOS product view event with currency and value.',\n in: {\n url:\n 'https://www.google-analytics.com/g/collect' +\n '?v=2&tid=G-EXAMPLE&_p=p1&cid=cid-1&sid=' +\n SID +\n '&en=view_item&ep.currency=EUR&epn.value=129.99',\n },\n out: [\n [\n 'return',\n ga4Event({\n name: 'product view',\n entity: 'product',\n action: 'view',\n data: { currency: 'EUR', value: 129.99 },\n }),\n ],\n ],\n};\n\nexport const addToCart: Flow.StepExample = {\n title: 'Add to cart',\n description:\n 'A GA4 add_to_cart hit decoded to a walkerOS product add event with currency and value.',\n in: {\n url:\n 'https://www.google-analytics.com/g/collect' +\n '?v=2&tid=G-EXAMPLE&_p=p1&cid=cid-1&sid=' +\n SID +\n '&en=add_to_cart&ep.currency=EUR&epn.value=129.99',\n },\n out: [\n [\n 'return',\n ga4Event({\n name: 'product add',\n entity: 'product',\n action: 'add',\n data: { currency: 'EUR', value: 129.99 },\n }),\n ],\n ],\n};\n\nexport const beginCheckout: Flow.StepExample = {\n title: 'Begin checkout',\n description:\n 'A GA4 begin_checkout hit decoded to a walkerOS order start event with currency, value, and coupon.',\n in: {\n url:\n 'https://www.google-analytics.com/g/collect' +\n '?v=2&tid=G-EXAMPLE&_p=p1&cid=cid-1&sid=' +\n SID +\n '&en=begin_checkout' +\n '&ep.currency=EUR&epn.value=149.97&ep.coupon=WELCOME10',\n },\n out: [\n [\n 'return',\n ga4Event({\n name: 'order start',\n entity: 'order',\n action: 'start',\n data: {\n currency: 'EUR',\n value: 149.97,\n coupon: 'WELCOME10',\n },\n }),\n ],\n ],\n};\n\nexport const scroll: Flow.StepExample = {\n title: 'Scroll',\n description:\n 'A GA4 scroll hit decoded to a walkerOS page scroll event with the percent_scrolled value.',\n in: {\n url:\n 'https://www.google-analytics.com/g/collect' +\n '?v=2&tid=G-EXAMPLE&_p=p1&cid=cid-1&sid=' +\n SID +\n '&en=scroll&epn.percent_scrolled=90',\n },\n out: [\n [\n 'return',\n ga4Event({\n name: 'page scroll',\n entity: 'page',\n action: 'scroll',\n data: { percent: 90 },\n }),\n ],\n ],\n};\n\nexport const search: Flow.StepExample = {\n title: 'Search',\n description:\n 'A GA4 search hit decoded to a walkerOS search submit event carrying the search term.',\n in: {\n url:\n 'https://www.google-analytics.com/g/collect' +\n '?v=2&tid=G-EXAMPLE&_p=p1&cid=cid-1&sid=' +\n SID +\n '&en=search&ep.search_term=trail%20runner',\n },\n out: [\n [\n 'return',\n ga4Event({\n name: 'search submit',\n entity: 'search',\n action: 'submit',\n data: { term: 'trail runner' },\n }),\n ],\n ],\n};\n\nexport const login: Flow.StepExample = {\n title: 'Login',\n description:\n 'A GA4 login hit decoded to a walkerOS session login event with the auth method.',\n in: {\n url:\n 'https://www.google-analytics.com/g/collect' +\n '?v=2&tid=G-EXAMPLE&_p=p1&cid=cid-1&sid=' +\n SID +\n '&en=login&ep.method=google',\n },\n out: [\n [\n 'return',\n ga4Event({\n name: 'session login',\n entity: 'session',\n action: 'login',\n data: { method: 'google' },\n }),\n ],\n ],\n};\n\nexport const customEvent: Flow.StepExample = {\n title: 'Custom event (* fallback)',\n description:\n 'Unknown GA4 event names hit the * fallback rule and surface as a ga4 track event carrying the original name.',\n in: {\n url:\n 'https://www.google-analytics.com/g/collect' +\n '?v=2&tid=G-EXAMPLE&_p=p1&cid=cid-1&sid=' +\n SID +\n '&en=newsletter_subscribe&ep.source=footer',\n },\n out: [\n [\n 'return',\n ga4Event({\n name: 'ga4 track',\n entity: 'ga4',\n action: 'track',\n data: { event_name: 'newsletter_subscribe' },\n }),\n ],\n ],\n};\n\nexport const consentDenied: Flow.StepExample = {\n title: 'Consent denied (gcs=G100)',\n description:\n 'A page_view hit with gcs=G100 still maps, with consent.{marketing,analytics} both false on the resulting event.',\n in: {\n url:\n 'https://www.google-analytics.com/g/collect' +\n '?v=2&tid=G-EXAMPLE&_p=p1&cid=cid-1&sid=' +\n SID +\n '&gcs=G100' +\n '&en=page_view&dl=https%3A%2F%2Fx&dt=X',\n },\n out: [\n [\n 'return',\n ga4Event({\n name: 'page view',\n entity: 'page',\n action: 'view',\n data: { id: 'https://x', title: 'X' },\n consent: { marketing: false, analytics: false },\n }),\n ],\n ],\n};\n\nexport const userEngagementIgnored: Flow.StepExample = {\n title: 'user_engagement (ignored)',\n description:\n 'Auto-fired GA4 user_engagement events are dropped by default — the transformer returns false.',\n in: {\n url:\n 'https://www.google-analytics.com/g/collect' +\n '?v=2&tid=G-EXAMPLE&_p=p1&cid=cid-1&sid=' +\n SID +\n '&en=user_engagement&_et=1500',\n },\n out: [['return', false]],\n};\n\nexport const batchPost: Flow.StepExample = {\n title: 'Batched POST (fan-out)',\n description:\n 'A single POST request carrying two newline-separated events fans out into two walkerOS events.',\n in: {\n url:\n 'https://www.google-analytics.com/g/collect' +\n '?v=2&tid=G-EXAMPLE&_p=p1&cid=cid-1&sid=' +\n SID,\n body: [\n 'en=add_to_cart&ep.currency=EUR&epn.value=19.99',\n 'en=add_to_cart&ep.currency=EUR&epn.value=29.99',\n ].join('\\n'),\n },\n out: [\n [\n 'return',\n ga4Event({\n name: 'product add',\n entity: 'product',\n action: 'add',\n data: { currency: 'EUR', value: 19.99 },\n }),\n ],\n [\n 'return',\n ga4Event({\n name: 'product add',\n entity: 'product',\n action: 'add',\n data: { currency: 'EUR', value: 29.99 },\n }),\n ],\n ],\n};\n","import type { Hint } from '@walkeros/core';\n\nexport const hints: Hint.Hints = {\n wiring: {\n text: \"This is a request-decoder: it reads the raw GA4 hit from ctx.ingest (ctx.ingest.url, optional ctx.ingest.body) and decodes it into walkerOS events. Place it on a server source's before chain (source.before), NOT on source.next and NOT on a destination.before chain; it runs before the collector to turn the incoming request into events. The source populates ctx.ingest from its config.ingest, which MUST be a map operator: { map: { url: { key: 'url' }, path: { key: 'path' }, method: { key: 'method' }, body: { key: 'body' } } }. The keys are direct fields on the Express req (no req. prefix): url is the full request URL with query string (what the decoder reads), path drives the /g/collect before match, method and body carry POST batches. A bare object like { url: 'req.url' } is silently inert: with no map operator the source passes the whole req through getMappingValue, a real Express req fails the property check (it carries functions and circular refs), ctx.ingest stays empty, and the decoder skips the hit. A pre-parsed JSON body will not decode; pass the raw body text.\",\n code: [\n {\n lang: 'json',\n code: JSON.stringify(\n {\n sources: {\n http: {\n package: '@walkeros/server-source-express',\n config: {\n ingest: {\n map: {\n url: { key: 'url' },\n path: { key: 'path' },\n method: { key: 'method' },\n body: { key: 'body' },\n },\n },\n },\n before: 'ga4',\n },\n },\n transformers: {\n ga4: { package: '@walkeros/transformer-ga4' },\n },\n },\n null,\n 2,\n ),\n },\n ],\n },\n};\n"],"mappings":"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","names":["val"]}
1
+ {"version":3,"sources":["../src/dev.ts","../src/parse.ts","../src/defaults.ts","../src/map.ts","../src/id.ts","../src/schemas/index.ts","../src/schemas/settings.ts","../src/examples/index.ts","../src/examples/step.ts","../src/hints.ts"],"sourcesContent":["/**\n * Development exports for transformer-ga4.\n * Used by website documentation, step examples, and downstream tests.\n *\n * Mirrors the validator's dev.ts pattern: only primitives leak out here, the\n * transformer instance is reached via the package entry (`./index.ts`).\n */\n\nexport {\n parseRequest,\n parseQuery,\n parseBody,\n parseItem,\n parseConsent,\n} from './parse';\nexport { defaultMapping } from './defaults';\nexport { mapHitToEvents } from './map';\nexport type {\n GA4Settings,\n GA4Mapping,\n GA4Request,\n GA4Hit,\n GA4Event,\n GA4EventParams,\n GA4HitParams,\n GA4Item,\n} from './types';\n\nexport * as schemas from './schemas';\nexport * as examples from './examples';\nexport { hints } from './hints';\n","import type { WalkerOS } from '@walkeros/core';\nimport type {\n GA4Event,\n GA4EventParams,\n GA4Hit,\n GA4HitParams,\n GA4Item,\n GA4Request,\n} from './types';\n\nexport function parseQuery(url: string): Record<string, string> {\n const out: Record<string, string> = {};\n const qIdx = url.indexOf('?');\n if (qIdx === -1) return out;\n const usp = new URLSearchParams(url.slice(qIdx + 1));\n usp.forEach((value, key) => {\n out[key] = value;\n });\n return out;\n}\n\n/** Non-empty, trimmed lines of a POST body: one GA4 event per line. */\nexport function splitBodyLines(body: string): string[] {\n if (!body) return [];\n return body\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter((line) => line.length > 0);\n}\n\nexport function parseBody(body: string): Record<string, string>[] {\n return splitBodyLines(body).map((line) => {\n const out: Record<string, string> = {};\n const usp = new URLSearchParams(line);\n usp.forEach((v, k) => {\n out[k] = v;\n });\n return out;\n });\n}\n\n// Two separate dispatch maps keyed by 2-char prefix.\n// Split by type so the assignment site stays type-safe (no cast).\nconst ITEM_STRING_FIELDS: Readonly<Record<string, keyof GA4Item>> = {\n id: 'id',\n nm: 'name',\n br: 'brand',\n ca: 'category',\n c2: 'category2',\n c3: 'category3',\n c4: 'category4',\n c5: 'category5',\n va: 'variant',\n cp: 'coupon',\n ln: 'listName',\n li: 'listId',\n lo: 'locationId',\n af: 'affiliation',\n cn: 'creativeName',\n cs: 'creativeSlot',\n pi: 'promotionId',\n pn: 'promotionName',\n};\n\nconst ITEM_NUMBER_FIELDS: Readonly<Record<string, keyof GA4Item>> = {\n pr: 'price',\n qt: 'quantity',\n ds: 'discount',\n lp: 'listPosition',\n};\n\nfunction setItemString(item: GA4Item, key: keyof GA4Item, value: string): void {\n // Narrow assignment by key — these are the string-typed fields.\n switch (key) {\n case 'id':\n item.id = value;\n return;\n case 'name':\n item.name = value;\n return;\n case 'brand':\n item.brand = value;\n return;\n case 'category':\n item.category = value;\n return;\n case 'category2':\n item.category2 = value;\n return;\n case 'category3':\n item.category3 = value;\n return;\n case 'category4':\n item.category4 = value;\n return;\n case 'category5':\n item.category5 = value;\n return;\n case 'variant':\n item.variant = value;\n return;\n case 'coupon':\n item.coupon = value;\n return;\n case 'listName':\n item.listName = value;\n return;\n case 'listId':\n item.listId = value;\n return;\n case 'locationId':\n item.locationId = value;\n return;\n case 'affiliation':\n item.affiliation = value;\n return;\n case 'creativeName':\n item.creativeName = value;\n return;\n case 'creativeSlot':\n item.creativeSlot = value;\n return;\n case 'promotionId':\n item.promotionId = value;\n return;\n case 'promotionName':\n item.promotionName = value;\n return;\n }\n}\n\nfunction setItemNumber(item: GA4Item, key: keyof GA4Item, value: number): void {\n switch (key) {\n case 'price':\n item.price = value;\n return;\n case 'quantity':\n item.quantity = value;\n return;\n case 'discount':\n item.discount = value;\n return;\n case 'listPosition':\n item.listPosition = value;\n return;\n }\n}\n\nexport function parseItem(value: string): GA4Item {\n const item: GA4Item = { custom: {} };\n const customKeys = new Map<string, string>();\n const customVals = new Map<string, string>();\n\n for (const raw of value.split('~')) {\n if (raw.length === 0) continue;\n\n // Variable-length k<N>/v<N> (must match before 2-char prefix lookup\n // because k10/v10 etc are wider than 2 chars).\n const kvMatch = /^([kv])(\\d+)(.*)$/.exec(raw);\n if (kvMatch) {\n const [, kind, idx, val] = kvMatch;\n if (kind === 'k') customKeys.set(idx, val);\n else customVals.set(idx, val);\n continue;\n }\n\n if (raw.length < 2) continue;\n const prefix = raw.slice(0, 2);\n const val = raw.slice(2);\n\n const stringKey = ITEM_STRING_FIELDS[prefix];\n if (stringKey !== undefined) {\n setItemString(item, stringKey, val);\n continue;\n }\n const numberKey = ITEM_NUMBER_FIELDS[prefix];\n if (numberKey !== undefined) {\n const n = Number(val);\n if (!Number.isNaN(n)) setItemNumber(item, numberKey, n);\n continue;\n }\n }\n\n // Pair k<N> with v<N>; drop unmatched.\n for (const [idx, key] of customKeys) {\n const v = customVals.get(idx);\n if (v !== undefined) item.custom[key] = v;\n }\n return item;\n}\n\nexport function parseConsent(hit: { gcs?: string }): WalkerOS.Consent {\n const gcs = hit.gcs;\n if (!gcs || !/^G[01]{3}$/.test(gcs)) return {};\n // gcs[1] is reserved (always '1' for current consent mode v2)\n return {\n marketing: gcs[2] === '1', // ad_storage\n analytics: gcs[3] === '1', // analytics_storage\n };\n}\n\nconst HIT_PARAM_KEYS = new Set([\n 'v',\n 'tid',\n 'cid',\n 'sid',\n 'sct',\n 'seg',\n '_p',\n '_z',\n 'gtm',\n 'dl',\n 'dt',\n 'dr',\n 'ul',\n 'sr',\n 'uid',\n '_dbg',\n '_s',\n '_ss',\n '_fv',\n 'gcs',\n 'gcd',\n 'dma',\n 'dma_cps',\n 'npa',\n 'p',\n]);\n\nexport function parseRequest(req: GA4Request): GA4Hit {\n const queryParams = parseQuery(req.url);\n const hit: GA4HitParams = {};\n const queryEventParams: Record<string, string> = {};\n\n // Split URL params into hit-level vs event-level.\n for (const [k, v] of Object.entries(queryParams)) {\n if (HIT_PARAM_KEYS.has(k)) hit[k] = v;\n else queryEventParams[k] = v;\n }\n\n // GET: event params live in the URL alongside hit params.\n // POST: in body lines.\n const bodyLines = req.body ? parseBody(req.body) : [];\n const rawEvents =\n bodyLines.length > 0\n ? bodyLines\n : Object.keys(queryEventParams).length > 0\n ? [queryEventParams]\n : [];\n\n const events: GA4Event[] = rawEvents\n .filter((raw) => typeof raw.en === 'string' && raw.en.length > 0)\n .map((raw) => buildEvent(raw));\n\n return { hit, events };\n}\n\nfunction buildEvent(raw: Record<string, string>): GA4Event {\n const params: GA4EventParams = { ep: {}, epn: {}, up: {}, upn: {} };\n const itemEntries: Array<[number, string]> = [];\n\n for (const [k, v] of Object.entries(raw)) {\n if (k === 'en') continue;\n\n // pr<N> items\n const prMatch = /^pr(\\d+)$/.exec(k);\n if (prMatch) {\n itemEntries.push([Number(prMatch[1]), v]);\n continue;\n }\n\n // Dotted-key nesting\n if (k.startsWith('ep.')) {\n params.ep[k.slice(3)] = v;\n continue;\n }\n if (k.startsWith('epn.')) {\n const n = Number(v);\n if (!Number.isNaN(n)) params.epn[k.slice(4)] = n;\n continue;\n }\n if (k.startsWith('up.')) {\n params.up[k.slice(3)] = v;\n continue;\n }\n if (k.startsWith('upn.')) {\n const n = Number(v);\n if (!Number.isNaN(n)) params.upn[k.slice(4)] = n;\n continue;\n }\n\n // Standalone numeric keys\n if (k === '_et') {\n const n = Number(v);\n if (!Number.isNaN(n)) params._et = n;\n continue;\n }\n if (k === '_c') {\n params._c = v;\n continue;\n }\n // Unknown standalone keys: drop. Add to GA4EventParams type if a future\n // need surfaces.\n }\n\n itemEntries.sort((a, b) => a[0] - b[0]);\n const items = itemEntries.map(([, v]) => parseItem(v));\n\n return { en: raw.en, params, items };\n}\n","import type { GA4Mapping } from './types';\n\n/**\n * Default GA4 event-name → walkerOS mapping rules.\n * Users may override or extend these via settings.mapping at config time.\n * The `'*'` key is the fallback for unknown event names.\n *\n * Field naming for `data.map`:\n * - Monetary: `currency` from `ep.currency`, `value`/`total` from `epn.value`,\n * `tax` from `epn.tax`, `shipping` from `epn.shipping`, `coupon` from\n * `ep.coupon`.\n * - Promotions read from `firstItem` (synthetic `items[0]` reference exposed by\n * the mapper), since GA4 encodes promotion info inside item tilde strings.\n */\nexport const defaultMapping: GA4Mapping = {\n // --- page ---\n page_view: {\n name: 'page view',\n data: {\n map: {\n id: 'hit.dl',\n title: 'hit.dt',\n referrer: 'hit.dr',\n },\n },\n },\n\n // --- ecommerce ---\n purchase: {\n name: 'order complete',\n data: {\n map: {\n id: 'params.ep.transaction_id',\n currency: 'params.ep.currency',\n total: 'params.epn.value',\n tax: 'params.epn.tax',\n shipping: 'params.epn.shipping',\n coupon: 'params.ep.coupon',\n },\n },\n },\n view_item: {\n name: 'product view',\n data: {\n map: {\n currency: 'params.ep.currency',\n value: 'params.epn.value',\n },\n },\n },\n add_to_cart: {\n name: 'product add',\n data: {\n map: {\n currency: 'params.ep.currency',\n value: 'params.epn.value',\n },\n },\n },\n remove_from_cart: {\n name: 'product remove',\n data: {\n map: {\n currency: 'params.ep.currency',\n value: 'params.epn.value',\n },\n },\n },\n view_cart: {\n name: 'cart view',\n data: {\n map: {\n currency: 'params.ep.currency',\n value: 'params.epn.value',\n },\n },\n },\n begin_checkout: {\n name: 'order start',\n data: {\n map: {\n currency: 'params.ep.currency',\n value: 'params.epn.value',\n coupon: 'params.ep.coupon',\n },\n },\n },\n add_shipping_info: {\n name: 'order shipping',\n data: {\n map: {\n currency: 'params.ep.currency',\n value: 'params.epn.value',\n tier: 'params.ep.shipping_tier',\n },\n },\n },\n add_payment_info: {\n name: 'order payment',\n data: {\n map: {\n currency: 'params.ep.currency',\n value: 'params.epn.value',\n type: 'params.ep.payment_type',\n },\n },\n },\n refund: {\n name: 'order refund',\n data: {\n map: {\n id: 'params.ep.transaction_id',\n currency: 'params.ep.currency',\n total: 'params.epn.value',\n },\n },\n },\n add_to_wishlist: {\n name: 'wishlist add',\n data: {\n map: {\n currency: 'params.ep.currency',\n value: 'params.epn.value',\n },\n },\n },\n\n // --- list / promotion ---\n view_item_list: {\n name: 'list view',\n data: {\n map: {\n id: 'params.ep.item_list_id',\n name: 'params.ep.item_list_name',\n },\n },\n },\n select_item: {\n name: 'product click',\n data: {\n map: {\n list_id: 'params.ep.item_list_id',\n list_name: 'params.ep.item_list_name',\n },\n },\n },\n view_promotion: {\n name: 'promotion view',\n data: {\n map: {\n id: 'firstItem.promotionId',\n name: 'firstItem.promotionName',\n creative: 'firstItem.creativeName',\n slot: 'firstItem.creativeSlot',\n },\n },\n },\n select_promotion: {\n name: 'promotion click',\n data: {\n map: {\n id: 'firstItem.promotionId',\n name: 'firstItem.promotionName',\n creative: 'firstItem.creativeName',\n slot: 'firstItem.creativeSlot',\n },\n },\n },\n select_content: {\n name: 'content select',\n data: {\n map: {\n type: 'params.ep.content_type',\n id: 'params.ep.content_id',\n },\n },\n },\n\n // --- engagement ---\n scroll: {\n name: 'page scroll',\n data: {\n map: {\n percent: 'params.epn.percent_scrolled',\n },\n },\n },\n click: {\n name: 'link click',\n data: {\n map: {\n url: 'params.ep.link_url',\n domain: 'params.ep.link_domain',\n outbound: 'params.ep.outbound',\n },\n },\n },\n file_download: {\n name: 'file download',\n data: {\n map: {\n name: 'params.ep.file_name',\n extension: 'params.ep.file_extension',\n url: 'params.ep.link_url',\n },\n },\n },\n video_start: {\n name: 'video start',\n data: {\n map: {\n title: 'params.ep.video_title',\n duration: 'params.epn.video_duration',\n current: 'params.epn.video_current_time',\n percent: 'params.epn.video_percent',\n },\n },\n },\n video_progress: {\n name: 'video progress',\n data: {\n map: {\n title: 'params.ep.video_title',\n duration: 'params.epn.video_duration',\n current: 'params.epn.video_current_time',\n percent: 'params.epn.video_percent',\n },\n },\n },\n video_complete: {\n name: 'video complete',\n data: {\n map: {\n title: 'params.ep.video_title',\n duration: 'params.epn.video_duration',\n current: 'params.epn.video_current_time',\n percent: 'params.epn.video_percent',\n },\n },\n },\n form_start: {\n name: 'form start',\n data: {\n map: {\n id: 'params.ep.form_id',\n name: 'params.ep.form_name',\n destination: 'params.ep.form_destination',\n },\n },\n },\n form_submit: {\n name: 'form submit',\n data: {\n map: {\n id: 'params.ep.form_id',\n name: 'params.ep.form_name',\n destination: 'params.ep.form_destination',\n },\n },\n },\n search: {\n name: 'search submit',\n data: {\n map: {\n term: 'params.ep.search_term',\n },\n },\n },\n login: {\n name: 'session login',\n data: {\n map: {\n method: 'params.ep.method',\n },\n },\n },\n sign_up: {\n name: 'session signup',\n data: {\n map: {\n method: 'params.ep.method',\n },\n },\n },\n generate_lead: {\n name: 'lead generate',\n data: {\n map: {\n currency: 'params.ep.currency',\n value: 'params.epn.value',\n },\n },\n },\n share: {\n name: 'content share',\n data: {\n map: {\n method: 'params.ep.method',\n type: 'params.ep.content_type',\n id: 'params.ep.item_id',\n },\n },\n },\n\n // --- auto-fired noise: ignore by default (users can override) ---\n user_engagement: { ignore: true },\n session_start: { ignore: true },\n first_visit: { ignore: true },\n\n // --- fallback for unknown event names ---\n '*': {\n name: 'ga4 track',\n data: {\n map: {\n event_name: 'en',\n },\n },\n },\n};\n","import type { Mapping, WalkerOS } from '@walkeros/core';\nimport { getByPath, deleteByPath, isObject } from '@walkeros/core';\nimport type {\n GA4Event,\n GA4Hit,\n GA4HitParams,\n GA4Item,\n GA4Mapping,\n} from './types';\nimport { parseConsent } from './parse';\nimport { getEventId } from './id';\n\n/**\n * Lookup root for mapping path resolution. Mapping rules reference keys via\n * dotted paths: `hit.dl`, `params.ep.transaction_id`, `params.epn.value`, `items`.\n *\n * `en` exposes the GA4 event name (used by the `*` fallback so unknown events\n * can carry their original name through). `firstItem` exposes `items[0]` so\n * promotion-style mappings can resolve `firstItem.promotionId` etc. without\n * needing array-index syntax in `getByPath`.\n *\n * Typed as `Record<string, unknown> & { ... }` so `getByPath` (which accepts\n * unknown) is happy without any narrowing cast on the call site.\n */\ntype LookupRoot = Record<string, unknown> & {\n hit: GA4HitParams;\n params: GA4Event['params'];\n items: GA4Event['items'];\n en: string;\n firstItem?: GA4Item;\n};\n\n/**\n * Convert a parsed GA4 hit into zero or more walkerOS events.\n * One GA4 hit may carry several events (POST batch); each is mapped\n * independently with hit-level metadata merged in.\n */\nexport function mapHitToEvents(\n hit: GA4Hit,\n mapping: GA4Mapping,\n): WalkerOS.DeepPartialEvent[] {\n const out: WalkerOS.DeepPartialEvent[] = [];\n hit.events.forEach((event, index) => {\n const mapped = mapOneEvent(hit.hit, event, index, mapping);\n if (mapped) out.push(mapped);\n });\n return out;\n}\n\nfunction mapOneEvent(\n hitParams: GA4HitParams,\n event: GA4Event,\n index: number,\n mapping: GA4Mapping,\n): WalkerOS.DeepPartialEvent | null {\n const ruleEntry = mapping[event.en] ?? mapping['*'];\n if (!ruleEntry) return null;\n // For v1, only single-rule entries are supported (no array fan-out).\n const rule: Mapping.Rule = Array.isArray(ruleEntry)\n ? ruleEntry[0]\n : ruleEntry;\n if (!rule || rule.ignore) return null;\n\n const lookup: LookupRoot = {\n hit: hitParams,\n params: event.params,\n items: event.items,\n en: event.en,\n ...(event.items.length > 0 ? { firstItem: event.items[0] } : {}),\n };\n\n const evaluated: WalkerOS.DeepPartialEvent = {};\n\n if (rule.name) {\n const [entity, ...rest] = rule.name.split(' ');\n evaluated.name = rule.name;\n evaluated.entity = entity;\n evaluated.action = rest.join(' ');\n }\n\n if (rule.data !== undefined) {\n let data = evalValue(rule.data, lookup);\n if (rule.remove && isObject(data)) {\n for (const path of rule.remove) data = deleteByPath(data, path);\n }\n if (data !== undefined) {\n evaluated.data = data as WalkerOS.Properties;\n }\n }\n\n // Hit-level merge: user / globals / source.\n evaluated.user = {\n ...(hitParams.uid !== undefined ? { id: hitParams.uid } : {}),\n ...(hitParams.cid !== undefined ? { device: hitParams.cid } : {}),\n ...(hitParams.sid !== undefined ? { session: hitParams.sid } : {}),\n };\n evaluated.globals = {\n ...(hitParams.ul !== undefined ? { language: hitParams.ul } : {}),\n ...(hitParams.sr !== undefined ? { screen: hitParams.sr } : {}),\n };\n // source.type marks the GA4 decoder; the raw page load id (_p) and hit\n // sequence (_s) stay available for analysts next to the derived event id.\n evaluated.source = {\n type: 'ga4',\n ...(hitParams.p !== undefined ? { platform: hitParams.p } : {}),\n ...(hitParams._p !== undefined ? { pageLoadId: hitParams._p } : {}),\n ...(hitParams._s !== undefined ? { hitSequence: hitParams._s } : {}),\n };\n\n // Consent from gcs string, id derived from the hit (see getEventId),\n // timestamp from sid (epoch seconds → ms; falls back to wall-clock now),\n // timing from event._et (ms; 0 if absent), trigger hard-coded to \"ga4\" for v1.\n evaluated.consent = parseConsent(hitParams);\n evaluated.id = getEventId(hitParams, index);\n const sidNum = hitParams.sid ? Number(hitParams.sid) : NaN;\n evaluated.timestamp =\n !Number.isNaN(sidNum) && sidNum > 0 ? sidNum * 1000 : Date.now();\n evaluated.timing = event.params._et ?? 0;\n evaluated.trigger = 'ga4';\n\n if (event.items.length > 0) {\n evaluated.nested = itemsToNested(event.items);\n }\n\n return evaluated;\n}\n\n/**\n * GA4 items → walkerOS nested product entities.\n * Field naming: camelCase GA4Item keys are emitted as snake_case data keys\n * (`listName` → `list_name`, `promotionId` → `promotion_id`, etc).\n * Custom k<N>/v<N> pairs are spread as-is.\n *\n * Returns `WalkerOS.Entities` (i.e. `Array<WalkerOS.Entity>`). Note that the\n * canonical `WalkerOS.Entity` interface uses `entity: string` as the kind\n * discriminator (not `type`).\n */\nfunction itemsToNested(items: GA4Item[]): WalkerOS.Entities {\n return items.map((item): WalkerOS.Entity => {\n const data: WalkerOS.Properties = {};\n if (item.id !== undefined) data.id = item.id;\n if (item.name !== undefined) data.name = item.name;\n if (item.brand !== undefined) data.brand = item.brand;\n if (item.category !== undefined) data.category = item.category;\n if (item.category2 !== undefined) data.category2 = item.category2;\n if (item.category3 !== undefined) data.category3 = item.category3;\n if (item.category4 !== undefined) data.category4 = item.category4;\n if (item.category5 !== undefined) data.category5 = item.category5;\n if (item.variant !== undefined) data.variant = item.variant;\n if (item.price !== undefined) data.price = item.price;\n if (item.quantity !== undefined) data.quantity = item.quantity;\n if (item.coupon !== undefined) data.coupon = item.coupon;\n if (item.discount !== undefined) data.discount = item.discount;\n if (item.listName !== undefined) data.list_name = item.listName;\n if (item.listId !== undefined) data.list_id = item.listId;\n if (item.listPosition !== undefined) data.list_position = item.listPosition;\n if (item.locationId !== undefined) data.location_id = item.locationId;\n if (item.affiliation !== undefined) data.affiliation = item.affiliation;\n if (item.creativeName !== undefined) data.creative_name = item.creativeName;\n if (item.creativeSlot !== undefined) data.creative_slot = item.creativeSlot;\n if (item.promotionId !== undefined) data.promotion_id = item.promotionId;\n if (item.promotionName !== undefined)\n data.promotion_name = item.promotionName;\n for (const [k, v] of Object.entries(item.custom)) data[k] = v;\n return { entity: 'product', data, nested: [], context: {} };\n });\n}\n\n/**\n * Minimal mapping evaluator. v1 supports:\n * - string → path lookup via getByPath\n * - Array<Value> → fallback chain: first non-undefined wins\n * - { value: X } → literal\n * - { key: 'path' } → path lookup\n * - { map: {...} } → recursive object build\n *\n * Deferred to v2: condition, loop, fn, validate, set, consent, $code.\n */\nfunction evalValue(\n value: Mapping.Value | Mapping.Values,\n root: LookupRoot,\n): unknown {\n if (Array.isArray(value)) {\n for (const v of value) {\n const resolved = evalValue(v, root);\n if (resolved !== undefined && resolved !== null) return resolved;\n }\n return undefined;\n }\n if (typeof value === 'string') {\n return getByPath(root, value);\n }\n if (typeof value === 'object' && value !== null) {\n if ('value' in value && value.value !== undefined) return value.value;\n if ('key' in value && typeof value.key === 'string') {\n return getByPath(root, value.key);\n }\n if ('map' in value && value.map) {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value.map)) {\n const resolved = evalValue(v, root);\n if (resolved !== undefined) out[k] = resolved;\n }\n return out;\n }\n }\n return undefined;\n}\n","import { deriveSpanId, getSpanId } from '@walkeros/core';\nimport type { GA4HitParams } from './types';\n\n/**\n * walkerOS event id for the `index`-th event of a GA4 hit.\n *\n * Shaped like every other walkerOS event id (a W3C span id: 16 lowercase hex\n * characters), but derived from the hit instead of drawn at random, so a\n * re-delivered hit (gtag retry, proxy duplicate) decodes to the same ids and\n * dedup on `event.id` catches it. The hit key is the parent, the event's\n * position the child (the same derivation walkerOS uses for forks):\n *\n * - `_p` page load id, shared by every hit of one page load\n * - `_s` hit sequence counter within that page load\n * - index position of the event inside the hit (batched POST)\n * - `tid` and `cid` separate two properties on one page and page load\n * ids that happen to collide across devices\n *\n * Without `_p` or `_s` there is no stable per-hit key, so the id falls back\n * to a random span id: dedup then never drops such an event by mistake.\n */\nexport function getEventId(hit: GA4HitParams, index: number): string {\n const { _p: page, _s: seq } = hit;\n if (!page || !seq) return getSpanId();\n\n return deriveSpanId(\n JSON.stringify(['ga4', hit.tid ?? '', hit.cid ?? '', page, seq]),\n index,\n );\n}\n","import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\n\nexport { SettingsSchema, type Settings } from './settings';\nexport const settings = zodToSchema(SettingsSchema);\n","import { schemas, z } from '@walkeros/core/dev';\n\nexport const SettingsSchema = z\n .object({\n mapping: z\n .record(z.string(), schemas.MappingSchemas.RuleSchema)\n .optional()\n .describe(\n \"Mapping rules keyed by GA4 event name (`en`), `'*'` for unknown events. A rule replaces the matching default unless it sets `extend` or `remove`; `ignore: true` drops the event.\",\n ),\n tidPattern: z\n .string()\n .optional()\n .describe(\n 'Regex string the tracking ID (`tid`) must match, compiled once at init. Default `^G-`, which drops Ads (`AW-`) and DC (`DC-`) hits.',\n ),\n maxEvents: z\n .number()\n .int()\n .min(1)\n .optional()\n .describe(\n 'Maximum number of events (POST body lines) decoded from one request. A request above the cap is dropped whole. Default 100.',\n ),\n })\n .describe(\n 'GA4 transformer: decodes GA4 Measurement Protocol v2 requests from ctx.ingest into walkerOS events.',\n );\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","export * as step from './step';\n","import type { Flow } from '@walkeros/core';\n\n/**\n * Step examples for transformer-ga4.\n *\n * `in` is a raw `GA4Request` (`{ url, body? }`) — the shape the transformer\n * reads from `ctx.ingest`. `out` is the array of effect tuples produced by\n * pushing that request through the transformer:\n *\n * - Mapped event (single): `out: [['return', event]]`\n * - Mapped events (fan-out): `out: [['return', e1], ['return', e2], ...]`\n * - Dropped (ignore / no en): `out: [['return', false]]`\n *\n * Examples set `_p` (page load id), `_s` (hit sequence) and `sid` (becomes\n * `event.timestamp` in ms via `sid * 1000`) so the assertions are\n * deterministic. The synthetic walkerOS event shape mirrors what\n * `mapHitToEvents` produces in `map.ts`:\n * - `id` derived from `tid`, `cid`, `_p`, `_s` and the event's position in\n * the hit: 16 lowercase hex chars, unique per event, identical when the\n * same hit is delivered twice (see `id.ts`)\n * - `entity` + `action` derived from rule.name's first/rest words\n * - `user.{id,device,session}` from `uid/cid/sid`\n * - `source: { type: 'ga4', platform?, pageLoadId, hitSequence }` from\n * `p`, `_p` and `_s`\n * - `consent` from `gcs` (`G100` → all false, `G111` → all true)\n * - `timing` from event `_et` (defaults to 0 if absent)\n * - `trigger: 'ga4'` (hard-coded in v1)\n * - `nested[]` only set when items are present (POST-only example below)\n */\n\n// --- helpers (typed, no casts) -----------------------------------------------\n\nconst SID = '1700000000'; // → timestamp 1700000000000\n\nfunction ga4Event(\n hitSequence: string,\n id: string,\n overrides: Record<string, unknown>,\n): Record<string, unknown> {\n return {\n id,\n timestamp: 1700000000000,\n timing: 0,\n trigger: 'ga4',\n user: { device: 'cid-1', session: SID },\n globals: {},\n source: { type: 'ga4', pageLoadId: 'p1', hitSequence },\n consent: {},\n ...overrides,\n };\n}\n\n// --- examples ---------------------------------------------------------------\n\nexport const pageView: Flow.StepExample = {\n title: 'Page view',\n description:\n 'A standard GA4 page_view hit decoded to a walkerOS page view with id, title, and referrer.',\n in: {\n url:\n 'https://www.google-analytics.com/g/collect' +\n '?v=2&tid=G-EXAMPLE&_p=p1&_s=1&cid=cid-1&sid=' +\n SID +\n '&en=page_view' +\n '&dl=https%3A%2F%2Fshop.example.com%2Fproducts%2Fsku-123' +\n '&dt=Trail%20Runner%20Pro' +\n '&dr=https%3A%2F%2Fshop.example.com%2F',\n },\n out: [\n [\n 'return',\n ga4Event('1', '619920d96220c8f5', {\n name: 'page view',\n entity: 'page',\n action: 'view',\n data: {\n id: 'https://shop.example.com/products/sku-123',\n title: 'Trail Runner Pro',\n referrer: 'https://shop.example.com/',\n },\n }),\n ],\n ],\n};\n\nexport const purchase: Flow.StepExample = {\n title: 'Purchase (canary)',\n description:\n 'A GA4 purchase hit decoded to a walkerOS order complete event with id, currency, total, tax, shipping, and coupon.',\n in: {\n url:\n 'https://www.google-analytics.com/g/collect' +\n '?v=2&tid=G-EXAMPLE&_p=p1&_s=2&cid=cid-1&sid=' +\n SID +\n '&en=purchase' +\n '&ep.transaction_id=T-9001' +\n '&ep.currency=EUR' +\n '&epn.value=149.97' +\n '&epn.tax=23.97' +\n '&epn.shipping=4.95' +\n '&ep.coupon=WELCOME10',\n },\n out: [\n [\n 'return',\n ga4Event('2', '07590930f34326b6', {\n name: 'order complete',\n entity: 'order',\n action: 'complete',\n data: {\n id: 'T-9001',\n currency: 'EUR',\n total: 149.97,\n tax: 23.97,\n shipping: 4.95,\n coupon: 'WELCOME10',\n },\n }),\n ],\n ],\n};\n\nexport const viewItem: Flow.StepExample = {\n title: 'View item',\n description:\n 'A GA4 view_item hit decoded to a walkerOS product view event with currency and value.',\n in: {\n url:\n 'https://www.google-analytics.com/g/collect' +\n '?v=2&tid=G-EXAMPLE&_p=p1&_s=3&cid=cid-1&sid=' +\n SID +\n '&en=view_item&ep.currency=EUR&epn.value=129.99',\n },\n out: [\n [\n 'return',\n ga4Event('3', 'a6ef03f16d295aef', {\n name: 'product view',\n entity: 'product',\n action: 'view',\n data: { currency: 'EUR', value: 129.99 },\n }),\n ],\n ],\n};\n\nexport const addToCart: Flow.StepExample = {\n title: 'Add to cart',\n description:\n 'A GA4 add_to_cart hit decoded to a walkerOS product add event with currency and value.',\n in: {\n url:\n 'https://www.google-analytics.com/g/collect' +\n '?v=2&tid=G-EXAMPLE&_p=p1&_s=4&cid=cid-1&sid=' +\n SID +\n '&en=add_to_cart&ep.currency=EUR&epn.value=129.99',\n },\n out: [\n [\n 'return',\n ga4Event('4', '21854a0390595250', {\n name: 'product add',\n entity: 'product',\n action: 'add',\n data: { currency: 'EUR', value: 129.99 },\n }),\n ],\n ],\n};\n\nexport const beginCheckout: Flow.StepExample = {\n title: 'Begin checkout',\n description:\n 'A GA4 begin_checkout hit decoded to a walkerOS order start event with currency, value, and coupon.',\n in: {\n url:\n 'https://www.google-analytics.com/g/collect' +\n '?v=2&tid=G-EXAMPLE&_p=p1&_s=5&cid=cid-1&sid=' +\n SID +\n '&en=begin_checkout' +\n '&ep.currency=EUR&epn.value=149.97&ep.coupon=WELCOME10',\n },\n out: [\n [\n 'return',\n ga4Event('5', '04a3521d6259b559', {\n name: 'order start',\n entity: 'order',\n action: 'start',\n data: {\n currency: 'EUR',\n value: 149.97,\n coupon: 'WELCOME10',\n },\n }),\n ],\n ],\n};\n\nexport const scroll: Flow.StepExample = {\n title: 'Scroll',\n description:\n 'A GA4 scroll hit decoded to a walkerOS page scroll event with the percent_scrolled value.',\n in: {\n url:\n 'https://www.google-analytics.com/g/collect' +\n '?v=2&tid=G-EXAMPLE&_p=p1&_s=6&cid=cid-1&sid=' +\n SID +\n '&en=scroll&epn.percent_scrolled=90',\n },\n out: [\n [\n 'return',\n ga4Event('6', 'f4211610dcdb861a', {\n name: 'page scroll',\n entity: 'page',\n action: 'scroll',\n data: { percent: 90 },\n }),\n ],\n ],\n};\n\nexport const search: Flow.StepExample = {\n title: 'Search',\n description:\n 'A GA4 search hit decoded to a walkerOS search submit event carrying the search term.',\n in: {\n url:\n 'https://www.google-analytics.com/g/collect' +\n '?v=2&tid=G-EXAMPLE&_p=p1&_s=7&cid=cid-1&sid=' +\n SID +\n '&en=search&ep.search_term=trail%20runner',\n },\n out: [\n [\n 'return',\n ga4Event('7', '697710c0b9b403d3', {\n name: 'search submit',\n entity: 'search',\n action: 'submit',\n data: { term: 'trail runner' },\n }),\n ],\n ],\n};\n\nexport const login: Flow.StepExample = {\n title: 'Login',\n description:\n 'A GA4 login hit decoded to a walkerOS session login event with the auth method.',\n in: {\n url:\n 'https://www.google-analytics.com/g/collect' +\n '?v=2&tid=G-EXAMPLE&_p=p1&_s=8&cid=cid-1&sid=' +\n SID +\n '&en=login&ep.method=google',\n },\n out: [\n [\n 'return',\n ga4Event('8', 'e6aa65225205bcf4', {\n name: 'session login',\n entity: 'session',\n action: 'login',\n data: { method: 'google' },\n }),\n ],\n ],\n};\n\nexport const customEvent: Flow.StepExample = {\n title: 'Custom event (* fallback)',\n description:\n 'Unknown GA4 event names hit the * fallback rule and surface as a ga4 track event carrying the original name.',\n in: {\n url:\n 'https://www.google-analytics.com/g/collect' +\n '?v=2&tid=G-EXAMPLE&_p=p1&_s=9&cid=cid-1&sid=' +\n SID +\n '&en=newsletter_subscribe&ep.source=footer',\n },\n out: [\n [\n 'return',\n ga4Event('9', 'd7dff1eae9d981dd', {\n name: 'ga4 track',\n entity: 'ga4',\n action: 'track',\n data: { event_name: 'newsletter_subscribe' },\n }),\n ],\n ],\n};\n\nexport const consentDenied: Flow.StepExample = {\n title: 'Consent denied (gcs=G100)',\n description:\n 'A page_view hit with gcs=G100 still maps, with consent.{marketing,analytics} both false on the resulting event.',\n in: {\n url:\n 'https://www.google-analytics.com/g/collect' +\n '?v=2&tid=G-EXAMPLE&_p=p1&_s=10&cid=cid-1&sid=' +\n SID +\n '&gcs=G100' +\n '&en=page_view&dl=https%3A%2F%2Fx&dt=X',\n },\n out: [\n [\n 'return',\n ga4Event('10', 'eeb7b2eaa3880daf', {\n name: 'page view',\n entity: 'page',\n action: 'view',\n data: { id: 'https://x', title: 'X' },\n consent: { marketing: false, analytics: false },\n }),\n ],\n ],\n};\n\nexport const userEngagementIgnored: Flow.StepExample = {\n title: 'user_engagement (ignored)',\n description:\n 'Auto-fired GA4 user_engagement events are dropped by default — the transformer returns false.',\n in: {\n url:\n 'https://www.google-analytics.com/g/collect' +\n '?v=2&tid=G-EXAMPLE&_p=p1&_s=11&cid=cid-1&sid=' +\n SID +\n '&en=user_engagement&_et=1500',\n },\n out: [['return', false]],\n};\n\nexport const batchPost: Flow.StepExample = {\n title: 'Batched POST (fan-out)',\n description:\n 'A single POST request carrying two newline-separated events fans out into two walkerOS events, each with its own id.',\n in: {\n url:\n 'https://www.google-analytics.com/g/collect' +\n '?v=2&tid=G-EXAMPLE&_p=p1&_s=12&cid=cid-1&sid=' +\n SID,\n body: [\n 'en=add_to_cart&ep.currency=EUR&epn.value=19.99',\n 'en=add_to_cart&ep.currency=EUR&epn.value=29.99',\n ].join('\\n'),\n },\n out: [\n [\n 'return',\n ga4Event('12', 'fa7fa5554916cbb5', {\n name: 'product add',\n entity: 'product',\n action: 'add',\n data: { currency: 'EUR', value: 19.99 },\n }),\n ],\n [\n 'return',\n ga4Event('12', 'fa82615549188e00', {\n name: 'product add',\n entity: 'product',\n action: 'add',\n data: { currency: 'EUR', value: 29.99 },\n }),\n ],\n ],\n};\n","import type { Hint } from '@walkeros/core';\n\nexport const hints: Hint.Hints = {\n wiring: {\n text: \"This is a request-decoder: it reads the raw GA4 hit from ctx.ingest (ctx.ingest.url, optional ctx.ingest.body) and decodes it into walkerOS events. Place it on a server source's before chain (source.before), NOT on source.next and NOT on a destination.before chain; it runs before the collector to turn the incoming request into events. The source populates ctx.ingest from its config.ingest, which MUST be a map operator: { map: { url: { key: 'url' }, path: { key: 'path' }, method: { key: 'method' }, body: { key: 'body' } } }. The keys are direct field paths on the request scope (no req. prefix): url is the full request URL with query string (what the decoder reads), path drives the /g/collect before match, method and body carry POST batches. A bare object like { url: 'req.url' } is silently inert: without an operator no field is extracted, ctx.ingest stays empty, and the decoder skips the hit. A pre-parsed JSON body will not decode; pass the raw body text. The express source listens on /collect by default and matches paths exactly; gtag.js sends to /g/collect, so set settings.paths: ['/g/collect'] or every hit gets a 404.\",\n code: [\n {\n lang: 'json',\n code: JSON.stringify(\n {\n sources: {\n http: {\n package: '@walkeros/server-source-express',\n config: {\n settings: { paths: ['/g/collect'] },\n ingest: {\n map: {\n url: { key: 'url' },\n path: { key: 'path' },\n method: { key: 'method' },\n body: { key: 'body' },\n },\n },\n },\n before: 'ga4',\n },\n },\n transformers: {\n ga4: { package: '@walkeros/transformer-ga4' },\n },\n },\n null,\n 2,\n ),\n },\n ],\n },\n 'source-choice': {\n text: 'gtag.js sends a single event as a POST without a body (parameters in the query string) and several events as one text/plain POST body, one event per line. @walkeros/server-source-express keeps a text/plain body that is not JSON as ingest.body, so it decodes GET, body-less POST and batched POST hits alike. @walkeros/server-source-fetch and sourceCloudFunction (@walkeros/server-source-gcp) do too, with the same ingest and before config. sourceLambda (@walkeros/server-source-aws) answers a POST without a body with 400, so single-event hits sent that way are lost on Lambda.',\n },\n};\n"],"mappings":"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","names":["val","import_core","import_dev"]}