@walkeros/server-destination-datamanager 4.0.1-next-1778230564486 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -323,7 +323,8 @@ mapping:
323
323
  lastName: 'data.lastName',
324
324
  },
325
325
  userId: 'user.id',
326
- clientId: 'user.device',
326
+ clientId: 'user.device', // GA4 web stream
327
+ appInstanceId: 'user.appInstanceId', // GA4 app stream (Firebase)
327
328
  sessionAttributes: 'context.sessionAttributes',
328
329
 
329
330
  // Consent mapping (string = field name, boolean = static value)
@@ -544,6 +545,61 @@ await elb('order complete', { total: 99.99 }, {
544
545
  }
545
546
  ```
546
547
 
548
+ ### Store Sales (Google Ads, IN_STORE)
549
+
550
+ For physical store conversions, set `eventSource: 'IN_STORE'` and map a
551
+ `storeId`. The destination wraps it into the API's required
552
+ `eventLocation.storeId` shape.
553
+
554
+ ```typescript
555
+ {
556
+ settings: {
557
+ eventSource: 'IN_STORE',
558
+ destinations: [{
559
+ operatingAccount: { accountId: '123-456-7890', accountType: 'GOOGLE_ADS' },
560
+ productDestinationId: 'AW-CONVERSION-123',
561
+ }],
562
+ },
563
+ mapping: {
564
+ order: {
565
+ complete: {
566
+ name: 'purchase',
567
+ data: {
568
+ map: {
569
+ transactionId: 'data.id',
570
+ conversionValue: 'data.total',
571
+ currency: 'data.currency',
572
+ storeId: 'data.storeId',
573
+ // Optional: hashed PII still applies for in-store matching
574
+ email: 'user.email',
575
+ phone: 'data.phone',
576
+ },
577
+ },
578
+ },
579
+ },
580
+ },
581
+ }
582
+ ```
583
+
584
+ ### App Conversions (GA4 app stream)
585
+
586
+ For GA4 app event ingestion, set `eventSource: 'APP'` and provide an
587
+ `appInstanceId` (Firebase install ID). It can be set per-event via mapping or as
588
+ a Settings guided helper.
589
+
590
+ ```typescript
591
+ {
592
+ settings: {
593
+ eventSource: 'APP',
594
+ appInstanceId: 'user.appInstanceId', // Settings helper
595
+ destinations: [{
596
+ operatingAccount: { accountId: '123456789', accountType: 'GOOGLE_ANALYTICS_PROPERTY' },
597
+ productDestinationId: 'G-XXXXXXXXXX',
598
+ }],
599
+ },
600
+ }
601
+ ```
602
+
547
603
  ## Account Types
548
604
 
549
605
  ### Google Ads
@@ -617,6 +673,14 @@ Output: <SHA-256 hash of "+18005550100">
617
673
  - **Region Code**: ISO-3166-1 alpha-2, NOT hashed (e.g., "US")
618
674
  - **Postal Code**: NOT hashed
619
675
 
676
+ ### Hash encoding
677
+
678
+ Every request is sent with `encoding: 'HEX'`, which Google requires whenever the
679
+ payload contains hashed `userData`. The value is pinned because all hashing in
680
+ this destination produces lowercase hex SHA-256 digests; exposing encoding as a
681
+ setting would risk silently mismatched identifiers between the hashed value and
682
+ the declared encoding.
683
+
620
684
  ## Consent Management (DMA)
621
685
 
622
686
  ### Required for EEA/UK/Switzerland
@@ -756,40 +820,44 @@ be rejected.
756
820
 
757
821
  ### Settings
758
822
 
759
- | Property | Type | Required | Description |
760
- | -------------------------- | -------------- | -------- | -------------------------------------------- |
761
- | `credentials` | object | \* | Service account (client_email + private_key) |
762
- | `keyFilename` | string | \* | Path to service account JSON file |
763
- | `scopes` | string[] | | OAuth scopes (default: datamanager scope) |
764
- | `destinations` | Destination[] | ✓ | Array of destination accounts (max 10) |
765
- | `eventSource` | EventSource | | Default event source (WEB, APP, etc.) |
766
- | `batchSize` | number | | Max events per batch (max 2000) |
767
- | `batchInterval` | number | | Batch flush interval in ms |
768
- | `validateOnly` | boolean | | Validate without ingestion |
769
- | `url` | string | | Override API endpoint |
770
- | `consent` | Consent | | Request-level consent |
771
- | `testEventCode` | string | | Test event code for debugging |
772
- | `userData` | object | | Guided helper: User data mapping |
773
- | `userId` | string | | Guided helper: First-party user ID |
774
- | `clientId` | string | | Guided helper: GA4 client ID |
775
- | `sessionAttributes` | string | | Guided helper: Privacy-safe attribution |
776
- | `consentAdUserData` | string/boolean | | Consent mapping: Field name or static value |
777
- | `consentAdPersonalization` | string/boolean | | Consent mapping: Field name or static value |
823
+ | Property | Type | Required | Description |
824
+ | -------------------------- | -------------- | -------- | --------------------------------------------- |
825
+ | `credentials` | object | \* | Service account (client_email + private_key) |
826
+ | `keyFilename` | string | \* | Path to service account JSON file |
827
+ | `scopes` | string[] | | OAuth scopes (default: datamanager scope) |
828
+ | `destinations` | Destination[] | ✓ | Array of destination accounts (max 10) |
829
+ | `eventSource` | EventSource | | Default event source (WEB, APP, etc.) |
830
+ | `batchSize` | number | | Max events per batch (max 2000) |
831
+ | `batchInterval` | number | | Batch flush interval in ms |
832
+ | `validateOnly` | boolean | | Validate without ingestion |
833
+ | `url` | string | | Override API endpoint |
834
+ | `consent` | Consent | | Request-level consent |
835
+ | `testEventCode` | string | | Test event code for debugging |
836
+ | `userData` | object | | Guided helper: User data mapping |
837
+ | `userId` | string | | Guided helper: First-party user ID |
838
+ | `clientId` | string | | Guided helper: GA4 client ID (web stream) |
839
+ | `appInstanceId` | string | | Guided helper: GA4 app instance ID (Firebase) |
840
+ | `sessionAttributes` | string | | Guided helper: Privacy-safe attribution |
841
+ | `consentAdUserData` | string/boolean | | Consent mapping: Field name or static value |
842
+ | `consentAdPersonalization` | string/boolean | | Consent mapping: Field name or static value |
778
843
 
779
844
  **\* One of `credentials`, `keyFilename`, or ADC (automatic) required for
780
845
  authentication**
781
846
 
782
847
  ### Event Fields
783
848
 
784
- | Field | Type | Max Length | Description |
785
- | ----------------- | ------ | ---------- | -------------------------------- |
786
- | `transactionId` | string | 512 | Transaction ID for deduplication |
787
- | `clientId` | string | 255 | GA client ID |
788
- | `userId` | string | 256 | First-party user ID |
789
- | `conversionValue` | number | | Conversion value |
790
- | `currency` | string | 3 | ISO 4217 currency code |
791
- | `eventName` | string | 40 | Event name (required for GA4) |
792
- | `eventSource` | string | | WEB, APP, IN_STORE, PHONE, OTHER |
849
+ | Field | Type | Max Length | Description |
850
+ | ----------------------- | ------ | ---------- | ------------------------------------------------ |
851
+ | `transactionId` | string | 512 | Transaction ID for deduplication |
852
+ | `clientId` | string | 255 | GA client ID (web stream) |
853
+ | `appInstanceId` | string | | Firebase app instance ID (GA4 app stream) |
854
+ | `userId` | string | 256 | First-party user ID |
855
+ | `conversionValue` | number | | Conversion value |
856
+ | `currency` | string | 3 | ISO 4217 currency code |
857
+ | `eventName` | string | 40 | Event name (required for GA4) |
858
+ | `eventSource` | string | | WEB, APP, IN_STORE, PHONE, OTHER |
859
+ | `eventLocation.storeId` | string | | Physical store ID (required for IN_STORE events) |
860
+ | `thirdPartyUserData` | object | | User identifiers from a data partner (typed) |
793
861
 
794
862
  ## Type Definitions
795
863
 
package/dist/dev.js CHANGED
@@ -1 +1 @@
1
- "use strict";var e,t=Object.defineProperty,a=Object.getOwnPropertyDescriptor,n=Object.getOwnPropertyNames,i=Object.prototype.hasOwnProperty,r=(e,a)=>{for(var n in a)t(e,n,{get:a[n],enumerable:!0})},o={};r(o,{examples:()=>I,schemas:()=>s}),module.exports=(e=o,((e,r,o,s)=>{if(r&&"object"==typeof r||"function"==typeof r)for(let c of n(r))i.call(e,c)||c===o||t(e,c,{get:()=>r[c],enumerable:!(s=a(r,c))||s.enumerable});return e})(t({},"__esModule",{value:!0}),e));var s={};r(s,{mapping:()=>E,settings:()=>z});var c=require("@walkeros/core/dev"),d=c.z.enum(["GOOGLE_ADS","DISPLAY_VIDEO_ADVERTISER","DISPLAY_VIDEO_PARTNER","GOOGLE_ANALYTICS_PROPERTY"]),l=c.z.enum(["WEB","APP","IN_STORE","PHONE","OTHER"]),u=c.z.enum(["CONSENT_GRANTED","CONSENT_DENIED"]),p=c.z.object({adUserData:u.describe("Consent for data collection and use").optional(),adPersonalization:u.describe("Consent for ad personalization").optional()}),m=c.z.object({accountId:c.z.string().min(1).describe('Account ID (e.g., "123-456-7890" for Google Ads)'),accountType:d.describe("Type of account")}),v=c.z.object({operatingAccount:m.describe("Operating account details"),productDestinationId:c.z.string().min(1).describe("Product-specific destination ID (conversion action or user list)")}),g=require("@walkeros/core/dev"),b=g.z.object({client_email:g.z.string().email().describe("Service account email"),private_key:g.z.string().min(1).describe("Service account private key (PEM format)")}),f=g.z.object({credentials:b.optional().describe("Service account credentials (client_email + private_key). Recommended for serverless environments."),keyFilename:g.z.string().optional().describe("Path to service account JSON file. For local development or environments with filesystem access."),scopes:g.z.array(g.z.string()).optional().describe("OAuth scopes for Data Manager API. Defaults to datamanager scope."),destinations:g.z.array(v).min(1).max(10).describe("Array of destination accounts and conversion actions/user lists (max 10)"),eventSource:l.optional().default("WEB").describe("Event source for all events. Defaults to WEB. Values: WEB, APP, IN_STORE, PHONE, OTHER"),batchSize:g.z.number().int().min(1).max(2e3).describe("Maximum number of events to batch before sending (max 2000, like 100)").optional(),batchInterval:g.z.number().int().min(0).describe("Time in milliseconds to wait before auto-flushing batch (like 5000)").optional(),validateOnly:g.z.boolean().describe("If true, validate request without ingestion (testing mode)").optional(),url:g.z.string().url().describe("Override API endpoint for testing (like https://datamanager.googleapis.com/v1)").optional(),consent:p.describe("Request-level consent for all events").optional(),testEventCode:g.z.string().describe("Test event code for debugging (like TEST12345)").optional(),logLevel:g.z.enum(["debug","info","warn","error","none"]).describe("Log level for debugging (debug shows all API calls)").optional(),userData:g.z.record(g.z.string(),g.z.unknown()).describe("Guided helper: User data mapping for all events (like { email: 'user.id', phone: 'data.phone' })").optional(),userId:g.z.any().describe("Guided helper: First-party user ID for all events (like 'user.id')").optional(),clientId:g.z.any().describe("Guided helper: GA4 client ID for all events (like 'user.device')").optional(),sessionAttributes:g.z.any().describe("Guided helper: Privacy-safe attribution for all events (like 'context.sessionAttributes')").optional(),consentAdUserData:g.z.union([g.z.string(),g.z.boolean()]).describe("Consent mapping: Field name from event.consent (like 'marketing') or static boolean value").optional(),consentAdPersonalization:g.z.union([g.z.string(),g.z.boolean()]).describe("Consent mapping: Field name from event.consent (like 'targeting') or static boolean value").optional()}),y=require("@walkeros/core/dev").z.object({}),h=require("@walkeros/core/dev"),z=(0,h.zodToSchema)(f),E=(0,h.zodToSchema)(y),I={};r(I,{env:()=>O,step:()=>S});var O={};r(O,{push:()=>A,simulation:()=>D});var A={fetch:async function(){return{ok:!0,status:200,json:async()=>({requestId:"mock-request-id",validationErrors:[]}),text:async()=>""}},authClient:{getAccessToken:async()=>({token:"ya29.c.test_token"})}},D=["fetch"],S={};r(S,{ga4PageView:()=>R,lead:()=>N,purchase:()=>w});var k=require("@walkeros/core"),P="https://datamanager.googleapis.com/v1/events:ingest",T=[{operatingAccount:{accountId:"123-456-7890",accountType:"GOOGLE_ADS"},productDestinationId:"AW-CONVERSION-123"}],_=e=>({method:"POST",headers:{Authorization:"Bearer ya29.c.test_token","Content-Type":"application/json"},body:e}),w={title:"Purchase",description:"A completed order is posted to Google Data Manager as a purchase conversion with hashed user identifiers.",in:(0,k.getEvent)("order complete",{id:"ev-1700000900000",timestamp:17000009e5,data:{id:"ORD-600",total:149.99,currency:"EUR"},user:{id:"user-abc",email:"buyer@example.com"},source:{type:"express",platform:"server"}}),mapping:{name:"purchase",data:{map:{transactionId:"data.id",conversionValue:"data.total",currency:{key:"data.currency",value:"USD"},eventName:{value:"purchase"},userId:"user.id",email:"user.email"}}},out:[["fetch",P,_(JSON.stringify({events:[{eventTimestamp:"2023-11-14T22:28:20.000Z",transactionId:"ORD-600",userId:"user-abc",userData:{userIdentifiers:[{emailAddress:"6a6c26195c3682faa816966af789717c3bfa834eee6c599d667d2b3429c27cfd"}]},conversionValue:149.99,currency:"EUR",eventName:"purchase",eventSource:"WEB"}],destinations:T}))]]},N={title:"Lead",description:"A demo request form submission is sent to Data Manager as a generate_lead conversion with a hashed email.",in:(0,k.getEvent)("form submit",{id:"ev-1700000901000",timestamp:1700000901e3,data:{type:"demo-request"},user:{email:"prospect@example.com"},source:{type:"express",platform:"server"}}),mapping:{name:"generate_lead",data:{map:{transactionId:"id",eventName:{value:"generate_lead"},conversionValue:{value:10},currency:{value:"USD"},email:"user.email"}}},out:[["fetch",P,_(JSON.stringify({events:[{eventTimestamp:"2023-11-14T22:28:21.000Z",transactionId:"ev-1700000901000",userData:{userIdentifiers:[{emailAddress:"395ec5f334be0ab5b28568a1e7f6ed5ea80e443fb1ce3d803340586a3df46642"}]},conversionValue:10,currency:"USD",eventName:"generate_lead",eventSource:"WEB"}],destinations:T}))]]},R={title:"Page view",description:"A page view is sent to Data Manager as a page_view event tied to the walker user id.",in:(0,k.getEvent)("page view",{id:"ev-1700000902000",timestamp:1700000902e3,data:{title:"Pricing",url:"https://example.com/pricing"},user:{id:"visitor-55"},source:{type:"express",platform:"server"}}),mapping:{name:"page_view",data:{map:{transactionId:"id",eventName:{value:"page_view"},userId:"user.id"}}},out:[["fetch",P,_(JSON.stringify({events:[{eventTimestamp:"2023-11-14T22:28:22.000Z",transactionId:"ev-1700000902000",userId:"visitor-55",eventName:"page_view",eventSource:"WEB"}],destinations:T}))]]};//# sourceMappingURL=dev.js.map
1
+ "use strict";var e,t=Object.defineProperty,a=Object.getOwnPropertyDescriptor,n=Object.getOwnPropertyNames,i=Object.prototype.hasOwnProperty,r=(e,a)=>{for(var n in a)t(e,n,{get:a[n],enumerable:!0})},o={};r(o,{examples:()=>E,schemas:()=>s}),module.exports=(e=o,((e,r,o,s)=>{if(r&&"object"==typeof r||"function"==typeof r)for(let c of n(r))i.call(e,c)||c===o||t(e,c,{get:()=>r[c],enumerable:!(s=a(r,c))||s.enumerable});return e})(t({},"__esModule",{value:!0}),e));var s={};r(s,{mapping:()=>I,settings:()=>z});var c=require("@walkeros/core/dev"),d=c.z.enum(["GOOGLE_ADS","DISPLAY_VIDEO_ADVERTISER","DISPLAY_VIDEO_PARTNER","GOOGLE_ANALYTICS_PROPERTY"]),l=c.z.enum(["WEB","APP","IN_STORE","PHONE","OTHER"]),u=c.z.enum(["CONSENT_GRANTED","CONSENT_DENIED"]),p=c.z.object({adUserData:u.describe("Consent for data collection and use").optional(),adPersonalization:u.describe("Consent for ad personalization").optional()}),m=c.z.object({accountId:c.z.string().min(1).describe('Account ID (e.g., "123-456-7890" for Google Ads)'),accountType:d.describe("Type of account")}),v=c.z.object({operatingAccount:m.describe("Operating account details"),productDestinationId:c.z.string().min(1).describe("Product-specific destination ID (conversion action or user list)")}),g=require("@walkeros/core/dev"),b=g.z.object({client_email:g.z.string().email().describe("Service account email"),private_key:g.z.string().min(1).describe("Service account private key (PEM format)")}),f=g.z.object({credentials:b.optional().describe("Service account credentials (client_email + private_key). Recommended for serverless environments."),keyFilename:g.z.string().optional().describe("Path to service account JSON file. For local development or environments with filesystem access."),scopes:g.z.array(g.z.string()).optional().describe("OAuth scopes for Data Manager API. Defaults to datamanager scope."),destinations:g.z.array(v).min(1).max(10).describe("Array of destination accounts and conversion actions/user lists (max 10)"),eventSource:l.optional().default("WEB").describe("Event source for all events. Defaults to WEB. Values: WEB, APP, IN_STORE, PHONE, OTHER"),batchSize:g.z.number().int().min(1).max(2e3).describe("Maximum number of events to batch before sending (max 2000, like 100)").optional(),batchInterval:g.z.number().int().min(0).describe("Time in milliseconds to wait before auto-flushing batch (like 5000)").optional(),validateOnly:g.z.boolean().describe("If true, validate request without ingestion (testing mode)").optional(),url:g.z.string().url().describe("Override API endpoint for testing (like https://datamanager.googleapis.com/v1)").optional(),consent:p.describe("Request-level consent for all events").optional(),testEventCode:g.z.string().describe("Test event code for debugging (like TEST12345)").optional(),logLevel:g.z.enum(["debug","info","warn","error","none"]).describe("Log level for debugging (debug shows all API calls)").optional(),userData:g.z.record(g.z.string(),g.z.unknown()).describe("Guided helper: User data mapping for all events (like { email: 'user.id', phone: 'data.phone' })").optional(),userId:g.z.any().describe("Guided helper: First-party user ID for all events (like 'user.id')").optional(),clientId:g.z.any().describe("Guided helper: GA4 client ID for all events (like 'user.device')").optional(),appInstanceId:g.z.any().describe("Guided helper: GA4 app instance ID (Firebase) for all events (like 'user.appInstanceId')").optional(),sessionAttributes:g.z.any().describe("Guided helper: Privacy-safe attribution for all events (like 'context.sessionAttributes')").optional(),consentAdUserData:g.z.union([g.z.string(),g.z.boolean()]).describe("Consent mapping: Field name from event.consent (like 'marketing') or static boolean value").optional(),consentAdPersonalization:g.z.union([g.z.string(),g.z.boolean()]).describe("Consent mapping: Field name from event.consent (like 'targeting') or static boolean value").optional()}),y=require("@walkeros/core/dev").z.object({}),h=require("@walkeros/core/dev"),z=(0,h.zodToSchema)(f),I=(0,h.zodToSchema)(y),E={};r(E,{env:()=>O,step:()=>k});var O={};r(O,{push:()=>A,simulation:()=>D});var A={fetch:async function(){return{ok:!0,status:200,json:async()=>({requestId:"mock-request-id",validationErrors:[]}),text:async()=>""}},authClient:{getAccessToken:async()=>({token:"ya29.c.test_token"})}},D=["fetch"],k={};r(k,{ga4PageView:()=>R,lead:()=>N,purchase:()=>w});var S=require("@walkeros/core"),P="https://datamanager.googleapis.com/v1/events:ingest",T=[{operatingAccount:{accountId:"123-456-7890",accountType:"GOOGLE_ADS"},productDestinationId:"AW-CONVERSION-123"}],_=e=>({method:"POST",headers:{Authorization:"Bearer ya29.c.test_token","Content-Type":"application/json"},body:e}),w={title:"Purchase",description:"A completed order is posted to Google Data Manager as a purchase conversion with hashed user identifiers.",in:(0,S.getEvent)("order complete",{id:"ev-1700000900000",timestamp:17000009e5,data:{id:"ORD-600",total:149.99,currency:"EUR"},user:{id:"user-abc",email:"buyer@example.com"},source:{type:"express",platform:"server"}}),mapping:{name:"purchase",data:{map:{transactionId:"data.id",conversionValue:"data.total",currency:{key:"data.currency",value:"USD"},eventName:{value:"purchase"},userId:"user.id",email:"user.email"}}},out:[["fetch",P,_(JSON.stringify({events:[{eventTimestamp:"2023-11-14T22:28:20.000Z",transactionId:"ORD-600",userId:"user-abc",userData:{userIdentifiers:[{emailAddress:"6a6c26195c3682faa816966af789717c3bfa834eee6c599d667d2b3429c27cfd"}]},conversionValue:149.99,currency:"EUR",eventName:"purchase",eventSource:"WEB"}],destinations:T,encoding:"HEX"}))]]},N={title:"Lead",description:"A demo request form submission is sent to Data Manager as a generate_lead conversion with a hashed email.",in:(0,S.getEvent)("form submit",{id:"ev-1700000901000",timestamp:1700000901e3,data:{type:"demo-request"},user:{email:"prospect@example.com"},source:{type:"express",platform:"server"}}),mapping:{name:"generate_lead",data:{map:{transactionId:"id",eventName:{value:"generate_lead"},conversionValue:{value:10},currency:{value:"USD"},email:"user.email"}}},out:[["fetch",P,_(JSON.stringify({events:[{eventTimestamp:"2023-11-14T22:28:21.000Z",transactionId:"ev-1700000901000",userData:{userIdentifiers:[{emailAddress:"395ec5f334be0ab5b28568a1e7f6ed5ea80e443fb1ce3d803340586a3df46642"}]},conversionValue:10,currency:"USD",eventName:"generate_lead",eventSource:"WEB"}],destinations:T,encoding:"HEX"}))]]},R={title:"Page view",description:"A page view is sent to Data Manager as a page_view event tied to the walker user id.",in:(0,S.getEvent)("page view",{id:"ev-1700000902000",timestamp:1700000902e3,data:{title:"Pricing",url:"https://example.com/pricing"},user:{id:"visitor-55"},source:{type:"express",platform:"server"}}),mapping:{name:"page_view",data:{map:{transactionId:"id",eventName:{value:"page_view"},userId:"user.id"}}},out:[["fetch",P,_(JSON.stringify({events:[{eventTimestamp:"2023-11-14T22:28:22.000Z",transactionId:"ev-1700000902000",userId:"visitor-55",eventName:"page_view",eventSource:"WEB"}],destinations:T,encoding:"HEX"}))]]};//# sourceMappingURL=dev.js.map
package/dist/dev.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/dev.ts","../src/schemas.ts","../src/schemas/primitives.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/schemas/index.ts","../src/examples/index.ts","../src/examples/env.ts","../src/examples/step.ts"],"sourcesContent":["export * as schemas from './schemas';\nexport * as examples from './examples';\n","// Browser-safe schema-only exports\n// This file exports ONLY schemas without any Node.js dependencies\nexport { settings, mapping } from './schemas/index';\n","import { z } from '@walkeros/core/dev';\n\nexport const AccountTypeSchema = z.enum([\n 'GOOGLE_ADS',\n 'DISPLAY_VIDEO_ADVERTISER',\n 'DISPLAY_VIDEO_PARTNER',\n 'GOOGLE_ANALYTICS_PROPERTY',\n]);\n\nexport const EventSourceSchema = z.enum([\n 'WEB',\n 'APP',\n 'IN_STORE',\n 'PHONE',\n 'OTHER',\n]);\n\nexport const ConsentStatusSchema = z.enum([\n 'CONSENT_GRANTED',\n 'CONSENT_DENIED',\n]);\n\nexport const ConsentSchema = z.object({\n adUserData: ConsentStatusSchema.describe(\n 'Consent for data collection and use',\n ).optional(),\n adPersonalization: ConsentStatusSchema.describe(\n 'Consent for ad personalization',\n ).optional(),\n});\n\nexport const OperatingAccountSchema = z.object({\n accountId: z\n .string()\n .min(1)\n .describe('Account ID (e.g., \"123-456-7890\" for Google Ads)'),\n accountType: AccountTypeSchema.describe('Type of account'),\n});\n\nexport const DestinationSchema = z.object({\n operatingAccount: OperatingAccountSchema.describe(\n 'Operating account details',\n ),\n productDestinationId: z\n .string()\n .min(1)\n .describe(\n 'Product-specific destination ID (conversion action or user list)',\n ),\n});\n","import { z } from '@walkeros/core/dev';\nimport {\n DestinationSchema,\n EventSourceSchema,\n ConsentSchema,\n} from './primitives';\n\n/**\n * Service account credentials schema\n */\nconst CredentialsSchema = z.object({\n client_email: z.string().email().describe('Service account email'),\n private_key: z\n .string()\n .min(1)\n .describe('Service account private key (PEM format)'),\n});\n\nexport const SettingsSchema = z.object({\n credentials: CredentialsSchema.optional().describe(\n 'Service account credentials (client_email + private_key). Recommended for serverless environments.',\n ),\n keyFilename: z\n .string()\n .optional()\n .describe(\n 'Path to service account JSON file. For local development or environments with filesystem access.',\n ),\n scopes: z\n .array(z.string())\n .optional()\n .describe(\n 'OAuth scopes for Data Manager API. Defaults to datamanager scope.',\n ),\n destinations: z\n .array(DestinationSchema)\n .min(1)\n .max(10)\n .describe(\n 'Array of destination accounts and conversion actions/user lists (max 10)',\n ),\n eventSource: EventSourceSchema.optional()\n .default('WEB')\n .describe(\n 'Event source for all events. Defaults to WEB. Values: WEB, APP, IN_STORE, PHONE, OTHER',\n ),\n batchSize: z\n .number()\n .int()\n .min(1)\n .max(2000)\n .describe(\n 'Maximum number of events to batch before sending (max 2000, like 100)',\n )\n .optional(),\n batchInterval: z\n .number()\n .int()\n .min(0)\n .describe(\n 'Time in milliseconds to wait before auto-flushing batch (like 5000)',\n )\n .optional(),\n validateOnly: z\n .boolean()\n .describe('If true, validate request without ingestion (testing mode)')\n .optional(),\n url: z\n .string()\n .url()\n .describe(\n 'Override API endpoint for testing (like https://datamanager.googleapis.com/v1)',\n )\n .optional(),\n consent: ConsentSchema.describe(\n 'Request-level consent for all events',\n ).optional(),\n testEventCode: z\n .string()\n .describe('Test event code for debugging (like TEST12345)')\n .optional(),\n logLevel: z\n .enum(['debug', 'info', 'warn', 'error', 'none'])\n .describe('Log level for debugging (debug shows all API calls)')\n .optional(),\n userData: z\n .record(z.string(), z.unknown())\n .describe(\n \"Guided helper: User data mapping for all events (like { email: 'user.id', phone: 'data.phone' })\",\n )\n .optional(),\n userId: z\n .any()\n .describe(\n \"Guided helper: First-party user ID for all events (like 'user.id')\",\n )\n .optional(),\n clientId: z\n .any()\n .describe(\n \"Guided helper: GA4 client ID for all events (like 'user.device')\",\n )\n .optional(),\n sessionAttributes: z\n .any()\n .describe(\n \"Guided helper: Privacy-safe attribution for all events (like 'context.sessionAttributes')\",\n )\n .optional(),\n consentAdUserData: z\n .union([z.string(), z.boolean()])\n .describe(\n \"Consent mapping: Field name from event.consent (like 'marketing') or static boolean value\",\n )\n .optional(),\n consentAdPersonalization: z\n .union([z.string(), z.boolean()])\n .describe(\n \"Consent mapping: Field name from event.consent (like 'targeting') or static boolean value\",\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\n// Data Manager uses flexible mapping via walkerOS mapping system\n// No event-specific mapping schema needed (similar to Meta CAPI pattern)\nexport const MappingSchema = z.object({});\n\nexport type Mapping = z.infer<typeof MappingSchema>;\n","export * from './primitives';\nexport * from './settings';\nexport * from './mapping';\n\nimport { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\n","export * as env from './env';\nexport * as step from './step';\n","import type { OAuth2Client } from 'google-auth-library';\nimport type { Env } from '../types';\n\n/**\n * Example environment configurations for Google Data Manager destination.\n *\n * The destination invokes `env.fetch(url, { method, headers, body })` once\n * per push, with `Authorization: Bearer <accessToken>` obtained from\n * `env.authClient` via `getAccessToken`.\n *\n * For tests we use a stub `authClient` (jest mocks the `getAccessToken`\n * helper at module level) and a mock `fetch` returning a successful ingest\n * response.\n */\n\nasync function mockFetch(): Promise<Response> {\n return {\n ok: true,\n status: 200,\n json: async () => ({ requestId: 'mock-request-id', validationErrors: [] }),\n text: async () => '',\n } as unknown as Response;\n}\n\nconst mockAuthClient = {\n getAccessToken: async () => ({ token: 'ya29.c.test_token' }),\n} as unknown as OAuth2Client;\n\nexport const push: Env = {\n fetch: mockFetch,\n authClient: mockAuthClient,\n};\n\nexport const simulation = ['fetch'];\n","import type { Flow } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\n\n/**\n * Google Data Manager step examples.\n *\n * At push time, the destination calls\n * `env.fetch(url, { method, headers, body })` where:\n * - `url` is `${settings.url}/events:ingest` (default\n * `https://datamanager.googleapis.com/v1`)\n * - `method` is `'POST'`\n * - `headers` is `{ Authorization: 'Bearer <accessToken>', 'Content-Type': 'application/json' }`\n * - `body` is the JSON-stringified `{ events: [dataManagerEvent], destinations }` payload\n *\n * The access token is obtained from `env.authClient` via `getAccessToken`.\n * The test fixture mocks both so the captured Authorization header is stable\n * (`Bearer ya29.c.test_token`).\n *\n * Event fields are emitted in the order the destination constructs them\n * (insertion order matters for `JSON.stringify` string equality):\n * eventTimestamp, transactionId?, clientId?, userId?, userData?,\n * adIdentifiers?, conversionValue?, currency?, cartData?, eventName?,\n * [eventSource is appended last by push.ts when not already present].\n *\n * Emails are normalized (trim, lowercase, strip dots for Gmail) and hashed\n * with SHA-256.\n */\nconst ENDPOINT = 'https://datamanager.googleapis.com/v1/events:ingest';\nconst DESTINATIONS = [\n {\n operatingAccount: {\n accountId: '123-456-7890',\n accountType: 'GOOGLE_ADS',\n },\n productDestinationId: 'AW-CONVERSION-123',\n },\n];\nconst INIT_OPTIONS = (body: string) => ({\n method: 'POST',\n headers: {\n Authorization: 'Bearer ya29.c.test_token',\n 'Content-Type': 'application/json',\n },\n body,\n});\n\nexport const purchase: Flow.StepExample = {\n title: 'Purchase',\n description:\n 'A completed order is posted to Google Data Manager as a purchase conversion with hashed user identifiers.',\n in: getEvent('order complete', {\n id: 'ev-1700000900000',\n timestamp: 1700000900000,\n data: { id: 'ORD-600', total: 149.99, currency: 'EUR' },\n user: { id: 'user-abc', email: 'buyer@example.com' },\n source: { type: 'express', platform: 'server' },\n }),\n mapping: {\n name: 'purchase',\n data: {\n map: {\n transactionId: 'data.id',\n conversionValue: 'data.total',\n currency: { key: 'data.currency', value: 'USD' },\n eventName: { value: 'purchase' },\n userId: 'user.id',\n email: 'user.email',\n },\n },\n },\n out: [\n [\n 'fetch',\n ENDPOINT,\n INIT_OPTIONS(\n JSON.stringify({\n events: [\n {\n eventTimestamp: '2023-11-14T22:28:20.000Z',\n transactionId: 'ORD-600',\n userId: 'user-abc',\n userData: {\n userIdentifiers: [\n {\n // sha256('buyer@example.com')\n emailAddress:\n '6a6c26195c3682faa816966af789717c3bfa834eee6c599d667d2b3429c27cfd',\n },\n ],\n },\n conversionValue: 149.99,\n currency: 'EUR',\n eventName: 'purchase',\n eventSource: 'WEB',\n },\n ],\n destinations: DESTINATIONS,\n }),\n ),\n ],\n ],\n};\n\nexport const lead: Flow.StepExample = {\n title: 'Lead',\n description:\n 'A demo request form submission is sent to Data Manager as a generate_lead conversion with a hashed email.',\n in: getEvent('form submit', {\n id: 'ev-1700000901000',\n timestamp: 1700000901000,\n data: { type: 'demo-request' },\n user: { email: 'prospect@example.com' },\n source: { type: 'express', platform: 'server' },\n }),\n mapping: {\n name: 'generate_lead',\n data: {\n map: {\n transactionId: 'id',\n eventName: { value: 'generate_lead' },\n conversionValue: { value: 10 },\n currency: { value: 'USD' },\n email: 'user.email',\n },\n },\n },\n out: [\n [\n 'fetch',\n ENDPOINT,\n INIT_OPTIONS(\n JSON.stringify({\n events: [\n {\n eventTimestamp: '2023-11-14T22:28:21.000Z',\n transactionId: 'ev-1700000901000',\n userData: {\n userIdentifiers: [\n {\n // sha256('prospect@example.com')\n emailAddress:\n '395ec5f334be0ab5b28568a1e7f6ed5ea80e443fb1ce3d803340586a3df46642',\n },\n ],\n },\n conversionValue: 10,\n currency: 'USD',\n eventName: 'generate_lead',\n eventSource: 'WEB',\n },\n ],\n destinations: DESTINATIONS,\n }),\n ),\n ],\n ],\n};\n\nexport const ga4PageView: Flow.StepExample = {\n title: 'Page view',\n description:\n 'A page view is sent to Data Manager as a page_view event tied to the walker user id.',\n in: getEvent('page view', {\n id: 'ev-1700000902000',\n timestamp: 1700000902000,\n data: { title: 'Pricing', url: 'https://example.com/pricing' },\n user: { id: 'visitor-55' },\n source: { type: 'express', platform: 'server' },\n }),\n mapping: {\n name: 'page_view',\n data: {\n map: {\n transactionId: 'id',\n eventName: { value: 'page_view' },\n userId: 'user.id',\n },\n },\n },\n out: [\n [\n 'fetch',\n ENDPOINT,\n INIT_OPTIONS(\n JSON.stringify({\n events: [\n {\n eventTimestamp: '2023-11-14T22:28:22.000Z',\n transactionId: 'ev-1700000902000',\n userId: 'visitor-55',\n eventName: 'page_view',\n eventSource: 'WEB',\n },\n ],\n destinations: DESTINATIONS,\n }),\n ),\n ],\n ],\n};\n"],"mappings":"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","names":["import_dev","import_dev","import_dev"]}
1
+ {"version":3,"sources":["../src/dev.ts","../src/schemas.ts","../src/schemas/primitives.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/schemas/index.ts","../src/examples/index.ts","../src/examples/env.ts","../src/examples/step.ts"],"sourcesContent":["export * as schemas from './schemas';\nexport * as examples from './examples';\n","// Browser-safe schema-only exports\n// This file exports ONLY schemas without any Node.js dependencies\nexport { settings, mapping } from './schemas/index';\n","import { z } from '@walkeros/core/dev';\n\nexport const AccountTypeSchema = z.enum([\n 'GOOGLE_ADS',\n 'DISPLAY_VIDEO_ADVERTISER',\n 'DISPLAY_VIDEO_PARTNER',\n 'GOOGLE_ANALYTICS_PROPERTY',\n]);\n\nexport const EventSourceSchema = z.enum([\n 'WEB',\n 'APP',\n 'IN_STORE',\n 'PHONE',\n 'OTHER',\n]);\n\nexport const ConsentStatusSchema = z.enum([\n 'CONSENT_GRANTED',\n 'CONSENT_DENIED',\n]);\n\nexport const ConsentSchema = z.object({\n adUserData: ConsentStatusSchema.describe(\n 'Consent for data collection and use',\n ).optional(),\n adPersonalization: ConsentStatusSchema.describe(\n 'Consent for ad personalization',\n ).optional(),\n});\n\nexport const OperatingAccountSchema = z.object({\n accountId: z\n .string()\n .min(1)\n .describe('Account ID (e.g., \"123-456-7890\" for Google Ads)'),\n accountType: AccountTypeSchema.describe('Type of account'),\n});\n\nexport const DestinationSchema = z.object({\n operatingAccount: OperatingAccountSchema.describe(\n 'Operating account details',\n ),\n productDestinationId: z\n .string()\n .min(1)\n .describe(\n 'Product-specific destination ID (conversion action or user list)',\n ),\n});\n","import { z } from '@walkeros/core/dev';\nimport {\n DestinationSchema,\n EventSourceSchema,\n ConsentSchema,\n} from './primitives';\n\n/**\n * Service account credentials schema\n */\nconst CredentialsSchema = z.object({\n client_email: z.string().email().describe('Service account email'),\n private_key: z\n .string()\n .min(1)\n .describe('Service account private key (PEM format)'),\n});\n\nexport const SettingsSchema = z.object({\n credentials: CredentialsSchema.optional().describe(\n 'Service account credentials (client_email + private_key). Recommended for serverless environments.',\n ),\n keyFilename: z\n .string()\n .optional()\n .describe(\n 'Path to service account JSON file. For local development or environments with filesystem access.',\n ),\n scopes: z\n .array(z.string())\n .optional()\n .describe(\n 'OAuth scopes for Data Manager API. Defaults to datamanager scope.',\n ),\n destinations: z\n .array(DestinationSchema)\n .min(1)\n .max(10)\n .describe(\n 'Array of destination accounts and conversion actions/user lists (max 10)',\n ),\n eventSource: EventSourceSchema.optional()\n .default('WEB')\n .describe(\n 'Event source for all events. Defaults to WEB. Values: WEB, APP, IN_STORE, PHONE, OTHER',\n ),\n batchSize: z\n .number()\n .int()\n .min(1)\n .max(2000)\n .describe(\n 'Maximum number of events to batch before sending (max 2000, like 100)',\n )\n .optional(),\n batchInterval: z\n .number()\n .int()\n .min(0)\n .describe(\n 'Time in milliseconds to wait before auto-flushing batch (like 5000)',\n )\n .optional(),\n validateOnly: z\n .boolean()\n .describe('If true, validate request without ingestion (testing mode)')\n .optional(),\n url: z\n .string()\n .url()\n .describe(\n 'Override API endpoint for testing (like https://datamanager.googleapis.com/v1)',\n )\n .optional(),\n consent: ConsentSchema.describe(\n 'Request-level consent for all events',\n ).optional(),\n testEventCode: z\n .string()\n .describe('Test event code for debugging (like TEST12345)')\n .optional(),\n logLevel: z\n .enum(['debug', 'info', 'warn', 'error', 'none'])\n .describe('Log level for debugging (debug shows all API calls)')\n .optional(),\n userData: z\n .record(z.string(), z.unknown())\n .describe(\n \"Guided helper: User data mapping for all events (like { email: 'user.id', phone: 'data.phone' })\",\n )\n .optional(),\n userId: z\n .any()\n .describe(\n \"Guided helper: First-party user ID for all events (like 'user.id')\",\n )\n .optional(),\n clientId: z\n .any()\n .describe(\n \"Guided helper: GA4 client ID for all events (like 'user.device')\",\n )\n .optional(),\n appInstanceId: z\n .any()\n .describe(\n \"Guided helper: GA4 app instance ID (Firebase) for all events (like 'user.appInstanceId')\",\n )\n .optional(),\n sessionAttributes: z\n .any()\n .describe(\n \"Guided helper: Privacy-safe attribution for all events (like 'context.sessionAttributes')\",\n )\n .optional(),\n consentAdUserData: z\n .union([z.string(), z.boolean()])\n .describe(\n \"Consent mapping: Field name from event.consent (like 'marketing') or static boolean value\",\n )\n .optional(),\n consentAdPersonalization: z\n .union([z.string(), z.boolean()])\n .describe(\n \"Consent mapping: Field name from event.consent (like 'targeting') or static boolean value\",\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\n// Data Manager uses flexible mapping via walkerOS mapping system\n// No event-specific mapping schema needed (similar to Meta CAPI pattern)\nexport const MappingSchema = z.object({});\n\nexport type Mapping = z.infer<typeof MappingSchema>;\n","export * from './primitives';\nexport * from './settings';\nexport * from './mapping';\n\nimport { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\n","export * as env from './env';\nexport * as step from './step';\n","import type { OAuth2Client } from 'google-auth-library';\nimport type { Env } from '../types';\n\n/**\n * Example environment configurations for Google Data Manager destination.\n *\n * The destination invokes `env.fetch(url, { method, headers, body })` once\n * per push, with `Authorization: Bearer <accessToken>` obtained from\n * `env.authClient` via `getAccessToken`.\n *\n * For tests we use a stub `authClient` (jest mocks the `getAccessToken`\n * helper at module level) and a mock `fetch` returning a successful ingest\n * response.\n */\n\nasync function mockFetch(): Promise<Response> {\n return {\n ok: true,\n status: 200,\n json: async () => ({ requestId: 'mock-request-id', validationErrors: [] }),\n text: async () => '',\n } as unknown as Response;\n}\n\nconst mockAuthClient = {\n getAccessToken: async () => ({ token: 'ya29.c.test_token' }),\n} as unknown as OAuth2Client;\n\nexport const push: Env = {\n fetch: mockFetch,\n authClient: mockAuthClient,\n};\n\nexport const simulation = ['fetch'];\n","import type { Flow } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\n\n/**\n * Google Data Manager step examples.\n *\n * At push time, the destination calls\n * `env.fetch(url, { method, headers, body })` where:\n * - `url` is `${settings.url}/events:ingest` (default\n * `https://datamanager.googleapis.com/v1`)\n * - `method` is `'POST'`\n * - `headers` is `{ Authorization: 'Bearer <accessToken>', 'Content-Type': 'application/json' }`\n * - `body` is the JSON-stringified `{ events: [dataManagerEvent], destinations }` payload\n *\n * The access token is obtained from `env.authClient` via `getAccessToken`.\n * The test fixture mocks both so the captured Authorization header is stable\n * (`Bearer ya29.c.test_token`).\n *\n * Event fields are emitted in the order the destination constructs them\n * (insertion order matters for `JSON.stringify` string equality):\n * eventTimestamp, transactionId?, clientId?, userId?, userData?,\n * adIdentifiers?, conversionValue?, currency?, cartData?, eventName?,\n * [eventSource is appended last by push.ts when not already present].\n *\n * Emails are normalized (trim, lowercase, strip dots for Gmail) and hashed\n * with SHA-256.\n */\nconst ENDPOINT = 'https://datamanager.googleapis.com/v1/events:ingest';\nconst DESTINATIONS = [\n {\n operatingAccount: {\n accountId: '123-456-7890',\n accountType: 'GOOGLE_ADS',\n },\n productDestinationId: 'AW-CONVERSION-123',\n },\n];\nconst INIT_OPTIONS = (body: string) => ({\n method: 'POST',\n headers: {\n Authorization: 'Bearer ya29.c.test_token',\n 'Content-Type': 'application/json',\n },\n body,\n});\n\nexport const purchase: Flow.StepExample = {\n title: 'Purchase',\n description:\n 'A completed order is posted to Google Data Manager as a purchase conversion with hashed user identifiers.',\n in: getEvent('order complete', {\n id: 'ev-1700000900000',\n timestamp: 1700000900000,\n data: { id: 'ORD-600', total: 149.99, currency: 'EUR' },\n user: { id: 'user-abc', email: 'buyer@example.com' },\n source: { type: 'express', platform: 'server' },\n }),\n mapping: {\n name: 'purchase',\n data: {\n map: {\n transactionId: 'data.id',\n conversionValue: 'data.total',\n currency: { key: 'data.currency', value: 'USD' },\n eventName: { value: 'purchase' },\n userId: 'user.id',\n email: 'user.email',\n },\n },\n },\n out: [\n [\n 'fetch',\n ENDPOINT,\n INIT_OPTIONS(\n JSON.stringify({\n events: [\n {\n eventTimestamp: '2023-11-14T22:28:20.000Z',\n transactionId: 'ORD-600',\n userId: 'user-abc',\n userData: {\n userIdentifiers: [\n {\n // sha256('buyer@example.com')\n emailAddress:\n '6a6c26195c3682faa816966af789717c3bfa834eee6c599d667d2b3429c27cfd',\n },\n ],\n },\n conversionValue: 149.99,\n currency: 'EUR',\n eventName: 'purchase',\n eventSource: 'WEB',\n },\n ],\n destinations: DESTINATIONS,\n encoding: 'HEX',\n }),\n ),\n ],\n ],\n};\n\nexport const lead: Flow.StepExample = {\n title: 'Lead',\n description:\n 'A demo request form submission is sent to Data Manager as a generate_lead conversion with a hashed email.',\n in: getEvent('form submit', {\n id: 'ev-1700000901000',\n timestamp: 1700000901000,\n data: { type: 'demo-request' },\n user: { email: 'prospect@example.com' },\n source: { type: 'express', platform: 'server' },\n }),\n mapping: {\n name: 'generate_lead',\n data: {\n map: {\n transactionId: 'id',\n eventName: { value: 'generate_lead' },\n conversionValue: { value: 10 },\n currency: { value: 'USD' },\n email: 'user.email',\n },\n },\n },\n out: [\n [\n 'fetch',\n ENDPOINT,\n INIT_OPTIONS(\n JSON.stringify({\n events: [\n {\n eventTimestamp: '2023-11-14T22:28:21.000Z',\n transactionId: 'ev-1700000901000',\n userData: {\n userIdentifiers: [\n {\n // sha256('prospect@example.com')\n emailAddress:\n '395ec5f334be0ab5b28568a1e7f6ed5ea80e443fb1ce3d803340586a3df46642',\n },\n ],\n },\n conversionValue: 10,\n currency: 'USD',\n eventName: 'generate_lead',\n eventSource: 'WEB',\n },\n ],\n destinations: DESTINATIONS,\n encoding: 'HEX',\n }),\n ),\n ],\n ],\n};\n\nexport const ga4PageView: Flow.StepExample = {\n title: 'Page view',\n description:\n 'A page view is sent to Data Manager as a page_view event tied to the walker user id.',\n in: getEvent('page view', {\n id: 'ev-1700000902000',\n timestamp: 1700000902000,\n data: { title: 'Pricing', url: 'https://example.com/pricing' },\n user: { id: 'visitor-55' },\n source: { type: 'express', platform: 'server' },\n }),\n mapping: {\n name: 'page_view',\n data: {\n map: {\n transactionId: 'id',\n eventName: { value: 'page_view' },\n userId: 'user.id',\n },\n },\n },\n out: [\n [\n 'fetch',\n ENDPOINT,\n INIT_OPTIONS(\n JSON.stringify({\n events: [\n {\n eventTimestamp: '2023-11-14T22:28:22.000Z',\n transactionId: 'ev-1700000902000',\n userId: 'visitor-55',\n eventName: 'page_view',\n eventSource: 'WEB',\n },\n ],\n destinations: DESTINATIONS,\n encoding: 'HEX',\n }),\n ),\n ],\n ],\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,iBAAkB;AAEX,IAAM,oBAAoB,aAAE,KAAK;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,IAAM,oBAAoB,aAAE,KAAK;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,IAAM,sBAAsB,aAAE,KAAK;AAAA,EACxC;AAAA,EACA;AACF,CAAC;AAEM,IAAM,gBAAgB,aAAE,OAAO;AAAA,EACpC,YAAY,oBAAoB;AAAA,IAC9B;AAAA,EACF,EAAE,SAAS;AAAA,EACX,mBAAmB,oBAAoB;AAAA,IACrC;AAAA,EACF,EAAE,SAAS;AACb,CAAC;AAEM,IAAM,yBAAyB,aAAE,OAAO;AAAA,EAC7C,WAAW,aACR,OAAO,EACP,IAAI,CAAC,EACL,SAAS,kDAAkD;AAAA,EAC9D,aAAa,kBAAkB,SAAS,iBAAiB;AAC3D,CAAC;AAEM,IAAM,oBAAoB,aAAE,OAAO;AAAA,EACxC,kBAAkB,uBAAuB;AAAA,IACvC;AAAA,EACF;AAAA,EACA,sBAAsB,aACnB,OAAO,EACP,IAAI,CAAC,EACL;AAAA,IACC;AAAA,EACF;AACJ,CAAC;;;ACjDD,IAAAA,cAAkB;AAUlB,IAAM,oBAAoB,cAAE,OAAO;AAAA,EACjC,cAAc,cAAE,OAAO,EAAE,MAAM,EAAE,SAAS,uBAAuB;AAAA,EACjE,aAAa,cACV,OAAO,EACP,IAAI,CAAC,EACL,SAAS,0CAA0C;AACxD,CAAC;AAEM,IAAM,iBAAiB,cAAE,OAAO;AAAA,EACrC,aAAa,kBAAkB,SAAS,EAAE;AAAA,IACxC;AAAA,EACF;AAAA,EACA,aAAa,cACV,OAAO,EACP,SAAS,EACT;AAAA,IACC;AAAA,EACF;AAAA,EACF,QAAQ,cACL,MAAM,cAAE,OAAO,CAAC,EAChB,SAAS,EACT;AAAA,IACC;AAAA,EACF;AAAA,EACF,cAAc,cACX,MAAM,iBAAiB,EACvB,IAAI,CAAC,EACL,IAAI,EAAE,EACN;AAAA,IACC;AAAA,EACF;AAAA,EACF,aAAa,kBAAkB,SAAS,EACrC,QAAQ,KAAK,EACb;AAAA,IACC;AAAA,EACF;AAAA,EACF,WAAW,cACR,OAAO,EACP,IAAI,EACJ,IAAI,CAAC,EACL,IAAI,GAAI,EACR;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,eAAe,cACZ,OAAO,EACP,IAAI,EACJ,IAAI,CAAC,EACL;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,cAAc,cACX,QAAQ,EACR,SAAS,4DAA4D,EACrE,SAAS;AAAA,EACZ,KAAK,cACF,OAAO,EACP,IAAI,EACJ;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,SAAS,cAAc;AAAA,IACrB;AAAA,EACF,EAAE,SAAS;AAAA,EACX,eAAe,cACZ,OAAO,EACP,SAAS,gDAAgD,EACzD,SAAS;AAAA,EACZ,UAAU,cACP,KAAK,CAAC,SAAS,QAAQ,QAAQ,SAAS,MAAM,CAAC,EAC/C,SAAS,qDAAqD,EAC9D,SAAS;AAAA,EACZ,UAAU,cACP,OAAO,cAAE,OAAO,GAAG,cAAE,QAAQ,CAAC,EAC9B;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,QAAQ,cACL,IAAI,EACJ;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,UAAU,cACP,IAAI,EACJ;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,eAAe,cACZ,IAAI,EACJ;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,mBAAmB,cAChB,IAAI,EACJ;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,mBAAmB,cAChB,MAAM,CAAC,cAAE,OAAO,GAAG,cAAE,QAAQ,CAAC,CAAC,EAC/B;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EACZ,0BAA0B,cACvB,MAAM,CAAC,cAAE,OAAO,GAAG,cAAE,QAAQ,CAAC,CAAC,EAC/B;AAAA,IACC;AAAA,EACF,EACC,SAAS;AACd,CAAC;;;AC/HD,IAAAC,cAAkB;AAIX,IAAM,gBAAgB,cAAE,OAAO,CAAC,CAAC;;;ACAxC,IAAAC,cAA4B;AAIrB,IAAM,eAAW,yBAAY,cAAc;AAC3C,IAAM,cAAU,yBAAY,aAAa;;;ACThD;AAAA;AAAA;AAAA;AAAA;;;ACAA;AAAA;AAAA;AAAA;AAAA;AAeA,eAAe,YAA+B;AAC5C,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,QAAQ;AAAA,IACR,MAAM,aAAa,EAAE,WAAW,mBAAmB,kBAAkB,CAAC,EAAE;AAAA,IACxE,MAAM,YAAY;AAAA,EACpB;AACF;AAEA,IAAM,iBAAiB;AAAA,EACrB,gBAAgB,aAAa,EAAE,OAAO,oBAAoB;AAC5D;AAEO,IAAM,OAAY;AAAA,EACvB,OAAO;AAAA,EACP,YAAY;AACd;AAEO,IAAM,aAAa,CAAC,OAAO;;;ACjClC;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,kBAAyB;AA0BzB,IAAM,WAAW;AACjB,IAAM,eAAe;AAAA,EACnB;AAAA,IACE,kBAAkB;AAAA,MAChB,WAAW;AAAA,MACX,aAAa;AAAA,IACf;AAAA,IACA,sBAAsB;AAAA,EACxB;AACF;AACA,IAAM,eAAe,CAAC,UAAkB;AAAA,EACtC,QAAQ;AAAA,EACR,SAAS;AAAA,IACP,eAAe;AAAA,IACf,gBAAgB;AAAA,EAClB;AAAA,EACA;AACF;AAEO,IAAM,WAA6B;AAAA,EACxC,OAAO;AAAA,EACP,aACE;AAAA,EACF,QAAI,sBAAS,kBAAkB;AAAA,IAC7B,IAAI;AAAA,IACJ,WAAW;AAAA,IACX,MAAM,EAAE,IAAI,WAAW,OAAO,QAAQ,UAAU,MAAM;AAAA,IACtD,MAAM,EAAE,IAAI,YAAY,OAAO,oBAAoB;AAAA,IACnD,QAAQ,EAAE,MAAM,WAAW,UAAU,SAAS;AAAA,EAChD,CAAC;AAAA,EACD,SAAS;AAAA,IACP,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,KAAK;AAAA,QACH,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,UAAU,EAAE,KAAK,iBAAiB,OAAO,MAAM;AAAA,QAC/C,WAAW,EAAE,OAAO,WAAW;AAAA,QAC/B,QAAQ;AAAA,QACR,OAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAAA,EACA,KAAK;AAAA,IACH;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,QACE,KAAK,UAAU;AAAA,UACb,QAAQ;AAAA,YACN;AAAA,cACE,gBAAgB;AAAA,cAChB,eAAe;AAAA,cACf,QAAQ;AAAA,cACR,UAAU;AAAA,gBACR,iBAAiB;AAAA,kBACf;AAAA;AAAA,oBAEE,cACE;AAAA,kBACJ;AAAA,gBACF;AAAA,cACF;AAAA,cACA,iBAAiB;AAAA,cACjB,UAAU;AAAA,cACV,WAAW;AAAA,cACX,aAAa;AAAA,YACf;AAAA,UACF;AAAA,UACA,cAAc;AAAA,UACd,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;AAEO,IAAM,OAAyB;AAAA,EACpC,OAAO;AAAA,EACP,aACE;AAAA,EACF,QAAI,sBAAS,eAAe;AAAA,IAC1B,IAAI;AAAA,IACJ,WAAW;AAAA,IACX,MAAM,EAAE,MAAM,eAAe;AAAA,IAC7B,MAAM,EAAE,OAAO,uBAAuB;AAAA,IACtC,QAAQ,EAAE,MAAM,WAAW,UAAU,SAAS;AAAA,EAChD,CAAC;AAAA,EACD,SAAS;AAAA,IACP,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,KAAK;AAAA,QACH,eAAe;AAAA,QACf,WAAW,EAAE,OAAO,gBAAgB;AAAA,QACpC,iBAAiB,EAAE,OAAO,GAAG;AAAA,QAC7B,UAAU,EAAE,OAAO,MAAM;AAAA,QACzB,OAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAAA,EACA,KAAK;AAAA,IACH;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,QACE,KAAK,UAAU;AAAA,UACb,QAAQ;AAAA,YACN;AAAA,cACE,gBAAgB;AAAA,cAChB,eAAe;AAAA,cACf,UAAU;AAAA,gBACR,iBAAiB;AAAA,kBACf;AAAA;AAAA,oBAEE,cACE;AAAA,kBACJ;AAAA,gBACF;AAAA,cACF;AAAA,cACA,iBAAiB;AAAA,cACjB,UAAU;AAAA,cACV,WAAW;AAAA,cACX,aAAa;AAAA,YACf;AAAA,UACF;AAAA,UACA,cAAc;AAAA,UACd,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;AAEO,IAAM,cAAgC;AAAA,EAC3C,OAAO;AAAA,EACP,aACE;AAAA,EACF,QAAI,sBAAS,aAAa;AAAA,IACxB,IAAI;AAAA,IACJ,WAAW;AAAA,IACX,MAAM,EAAE,OAAO,WAAW,KAAK,8BAA8B;AAAA,IAC7D,MAAM,EAAE,IAAI,aAAa;AAAA,IACzB,QAAQ,EAAE,MAAM,WAAW,UAAU,SAAS;AAAA,EAChD,CAAC;AAAA,EACD,SAAS;AAAA,IACP,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,KAAK;AAAA,QACH,eAAe;AAAA,QACf,WAAW,EAAE,OAAO,YAAY;AAAA,QAChC,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAAA,EACA,KAAK;AAAA,IACH;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,QACE,KAAK,UAAU;AAAA,UACb,QAAQ;AAAA,YACN;AAAA,cACE,gBAAgB;AAAA,cAChB,eAAe;AAAA,cACf,QAAQ;AAAA,cACR,WAAW;AAAA,cACX,aAAa;AAAA,YACf;AAAA,UACF;AAAA,UACA,cAAc;AAAA,UACd,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;","names":["import_dev","import_dev","import_dev"]}
package/dist/dev.mjs CHANGED
@@ -1 +1 @@
1
- var e=Object.defineProperty,t=(t,a)=>{for(var i in a)e(t,i,{get:a[i],enumerable:!0})},a={};t(a,{mapping:()=>f,settings:()=>b});import{z as i}from"@walkeros/core/dev";var n=i.enum(["GOOGLE_ADS","DISPLAY_VIDEO_ADVERTISER","DISPLAY_VIDEO_PARTNER","GOOGLE_ANALYTICS_PROPERTY"]),r=i.enum(["WEB","APP","IN_STORE","PHONE","OTHER"]),o=i.enum(["CONSENT_GRANTED","CONSENT_DENIED"]),s=i.object({adUserData:o.describe("Consent for data collection and use").optional(),adPersonalization:o.describe("Consent for ad personalization").optional()}),c=i.object({accountId:i.string().min(1).describe('Account ID (e.g., "123-456-7890" for Google Ads)'),accountType:n.describe("Type of account")}),d=i.object({operatingAccount:c.describe("Operating account details"),productDestinationId:i.string().min(1).describe("Product-specific destination ID (conversion action or user list)")});import{z as l}from"@walkeros/core/dev";var u=l.object({client_email:l.string().email().describe("Service account email"),private_key:l.string().min(1).describe("Service account private key (PEM format)")}),m=l.object({credentials:u.optional().describe("Service account credentials (client_email + private_key). Recommended for serverless environments."),keyFilename:l.string().optional().describe("Path to service account JSON file. For local development or environments with filesystem access."),scopes:l.array(l.string()).optional().describe("OAuth scopes for Data Manager API. Defaults to datamanager scope."),destinations:l.array(d).min(1).max(10).describe("Array of destination accounts and conversion actions/user lists (max 10)"),eventSource:r.optional().default("WEB").describe("Event source for all events. Defaults to WEB. Values: WEB, APP, IN_STORE, PHONE, OTHER"),batchSize:l.number().int().min(1).max(2e3).describe("Maximum number of events to batch before sending (max 2000, like 100)").optional(),batchInterval:l.number().int().min(0).describe("Time in milliseconds to wait before auto-flushing batch (like 5000)").optional(),validateOnly:l.boolean().describe("If true, validate request without ingestion (testing mode)").optional(),url:l.string().url().describe("Override API endpoint for testing (like https://datamanager.googleapis.com/v1)").optional(),consent:s.describe("Request-level consent for all events").optional(),testEventCode:l.string().describe("Test event code for debugging (like TEST12345)").optional(),logLevel:l.enum(["debug","info","warn","error","none"]).describe("Log level for debugging (debug shows all API calls)").optional(),userData:l.record(l.string(),l.unknown()).describe("Guided helper: User data mapping for all events (like { email: 'user.id', phone: 'data.phone' })").optional(),userId:l.any().describe("Guided helper: First-party user ID for all events (like 'user.id')").optional(),clientId:l.any().describe("Guided helper: GA4 client ID for all events (like 'user.device')").optional(),sessionAttributes:l.any().describe("Guided helper: Privacy-safe attribution for all events (like 'context.sessionAttributes')").optional(),consentAdUserData:l.union([l.string(),l.boolean()]).describe("Consent mapping: Field name from event.consent (like 'marketing') or static boolean value").optional(),consentAdPersonalization:l.union([l.string(),l.boolean()]).describe("Consent mapping: Field name from event.consent (like 'targeting') or static boolean value").optional()});import{z as p}from"@walkeros/core/dev";var v=p.object({});import{zodToSchema as g}from"@walkeros/core/dev";var b=g(m),f=g(v),h={};t(h,{env:()=>y,step:()=>A});var y={};t(y,{push:()=>I,simulation:()=>E});var I={fetch:async function(){return{ok:!0,status:200,json:async()=>({requestId:"mock-request-id",validationErrors:[]}),text:async()=>""}},authClient:{getAccessToken:async()=>({token:"ya29.c.test_token"})}},E=["fetch"],A={};t(A,{ga4PageView:()=>_,lead:()=>P,purchase:()=>T});import{getEvent as D}from"@walkeros/core";var O="https://datamanager.googleapis.com/v1/events:ingest",k=[{operatingAccount:{accountId:"123-456-7890",accountType:"GOOGLE_ADS"},productDestinationId:"AW-CONVERSION-123"}],S=e=>({method:"POST",headers:{Authorization:"Bearer ya29.c.test_token","Content-Type":"application/json"},body:e}),T={title:"Purchase",description:"A completed order is posted to Google Data Manager as a purchase conversion with hashed user identifiers.",in:D("order complete",{id:"ev-1700000900000",timestamp:17000009e5,data:{id:"ORD-600",total:149.99,currency:"EUR"},user:{id:"user-abc",email:"buyer@example.com"},source:{type:"express",platform:"server"}}),mapping:{name:"purchase",data:{map:{transactionId:"data.id",conversionValue:"data.total",currency:{key:"data.currency",value:"USD"},eventName:{value:"purchase"},userId:"user.id",email:"user.email"}}},out:[["fetch",O,S(JSON.stringify({events:[{eventTimestamp:"2023-11-14T22:28:20.000Z",transactionId:"ORD-600",userId:"user-abc",userData:{userIdentifiers:[{emailAddress:"6a6c26195c3682faa816966af789717c3bfa834eee6c599d667d2b3429c27cfd"}]},conversionValue:149.99,currency:"EUR",eventName:"purchase",eventSource:"WEB"}],destinations:k}))]]},P={title:"Lead",description:"A demo request form submission is sent to Data Manager as a generate_lead conversion with a hashed email.",in:D("form submit",{id:"ev-1700000901000",timestamp:1700000901e3,data:{type:"demo-request"},user:{email:"prospect@example.com"},source:{type:"express",platform:"server"}}),mapping:{name:"generate_lead",data:{map:{transactionId:"id",eventName:{value:"generate_lead"},conversionValue:{value:10},currency:{value:"USD"},email:"user.email"}}},out:[["fetch",O,S(JSON.stringify({events:[{eventTimestamp:"2023-11-14T22:28:21.000Z",transactionId:"ev-1700000901000",userData:{userIdentifiers:[{emailAddress:"395ec5f334be0ab5b28568a1e7f6ed5ea80e443fb1ce3d803340586a3df46642"}]},conversionValue:10,currency:"USD",eventName:"generate_lead",eventSource:"WEB"}],destinations:k}))]]},_={title:"Page view",description:"A page view is sent to Data Manager as a page_view event tied to the walker user id.",in:D("page view",{id:"ev-1700000902000",timestamp:1700000902e3,data:{title:"Pricing",url:"https://example.com/pricing"},user:{id:"visitor-55"},source:{type:"express",platform:"server"}}),mapping:{name:"page_view",data:{map:{transactionId:"id",eventName:{value:"page_view"},userId:"user.id"}}},out:[["fetch",O,S(JSON.stringify({events:[{eventTimestamp:"2023-11-14T22:28:22.000Z",transactionId:"ev-1700000902000",userId:"visitor-55",eventName:"page_view",eventSource:"WEB"}],destinations:k}))]]};export{h as examples,a as schemas};//# sourceMappingURL=dev.mjs.map
1
+ var e=Object.defineProperty,a=(a,t)=>{for(var n in t)e(a,n,{get:t[n],enumerable:!0})},t={};a(t,{mapping:()=>f,settings:()=>b});import{z as n}from"@walkeros/core/dev";var i=n.enum(["GOOGLE_ADS","DISPLAY_VIDEO_ADVERTISER","DISPLAY_VIDEO_PARTNER","GOOGLE_ANALYTICS_PROPERTY"]),r=n.enum(["WEB","APP","IN_STORE","PHONE","OTHER"]),o=n.enum(["CONSENT_GRANTED","CONSENT_DENIED"]),s=n.object({adUserData:o.describe("Consent for data collection and use").optional(),adPersonalization:o.describe("Consent for ad personalization").optional()}),c=n.object({accountId:n.string().min(1).describe('Account ID (e.g., "123-456-7890" for Google Ads)'),accountType:i.describe("Type of account")}),d=n.object({operatingAccount:c.describe("Operating account details"),productDestinationId:n.string().min(1).describe("Product-specific destination ID (conversion action or user list)")});import{z as l}from"@walkeros/core/dev";var u=l.object({client_email:l.string().email().describe("Service account email"),private_key:l.string().min(1).describe("Service account private key (PEM format)")}),p=l.object({credentials:u.optional().describe("Service account credentials (client_email + private_key). Recommended for serverless environments."),keyFilename:l.string().optional().describe("Path to service account JSON file. For local development or environments with filesystem access."),scopes:l.array(l.string()).optional().describe("OAuth scopes for Data Manager API. Defaults to datamanager scope."),destinations:l.array(d).min(1).max(10).describe("Array of destination accounts and conversion actions/user lists (max 10)"),eventSource:r.optional().default("WEB").describe("Event source for all events. Defaults to WEB. Values: WEB, APP, IN_STORE, PHONE, OTHER"),batchSize:l.number().int().min(1).max(2e3).describe("Maximum number of events to batch before sending (max 2000, like 100)").optional(),batchInterval:l.number().int().min(0).describe("Time in milliseconds to wait before auto-flushing batch (like 5000)").optional(),validateOnly:l.boolean().describe("If true, validate request without ingestion (testing mode)").optional(),url:l.string().url().describe("Override API endpoint for testing (like https://datamanager.googleapis.com/v1)").optional(),consent:s.describe("Request-level consent for all events").optional(),testEventCode:l.string().describe("Test event code for debugging (like TEST12345)").optional(),logLevel:l.enum(["debug","info","warn","error","none"]).describe("Log level for debugging (debug shows all API calls)").optional(),userData:l.record(l.string(),l.unknown()).describe("Guided helper: User data mapping for all events (like { email: 'user.id', phone: 'data.phone' })").optional(),userId:l.any().describe("Guided helper: First-party user ID for all events (like 'user.id')").optional(),clientId:l.any().describe("Guided helper: GA4 client ID for all events (like 'user.device')").optional(),appInstanceId:l.any().describe("Guided helper: GA4 app instance ID (Firebase) for all events (like 'user.appInstanceId')").optional(),sessionAttributes:l.any().describe("Guided helper: Privacy-safe attribution for all events (like 'context.sessionAttributes')").optional(),consentAdUserData:l.union([l.string(),l.boolean()]).describe("Consent mapping: Field name from event.consent (like 'marketing') or static boolean value").optional(),consentAdPersonalization:l.union([l.string(),l.boolean()]).describe("Consent mapping: Field name from event.consent (like 'targeting') or static boolean value").optional()});import{z as m}from"@walkeros/core/dev";var v=m.object({});import{zodToSchema as g}from"@walkeros/core/dev";var b=g(p),f=g(v),h={};a(h,{env:()=>I,step:()=>A});var I={};a(I,{push:()=>y,simulation:()=>E});var y={fetch:async function(){return{ok:!0,status:200,json:async()=>({requestId:"mock-request-id",validationErrors:[]}),text:async()=>""}},authClient:{getAccessToken:async()=>({token:"ya29.c.test_token"})}},E=["fetch"],A={};a(A,{ga4PageView:()=>_,lead:()=>P,purchase:()=>T});import{getEvent as D}from"@walkeros/core";var O="https://datamanager.googleapis.com/v1/events:ingest",k=[{operatingAccount:{accountId:"123-456-7890",accountType:"GOOGLE_ADS"},productDestinationId:"AW-CONVERSION-123"}],S=e=>({method:"POST",headers:{Authorization:"Bearer ya29.c.test_token","Content-Type":"application/json"},body:e}),T={title:"Purchase",description:"A completed order is posted to Google Data Manager as a purchase conversion with hashed user identifiers.",in:D("order complete",{id:"ev-1700000900000",timestamp:17000009e5,data:{id:"ORD-600",total:149.99,currency:"EUR"},user:{id:"user-abc",email:"buyer@example.com"},source:{type:"express",platform:"server"}}),mapping:{name:"purchase",data:{map:{transactionId:"data.id",conversionValue:"data.total",currency:{key:"data.currency",value:"USD"},eventName:{value:"purchase"},userId:"user.id",email:"user.email"}}},out:[["fetch",O,S(JSON.stringify({events:[{eventTimestamp:"2023-11-14T22:28:20.000Z",transactionId:"ORD-600",userId:"user-abc",userData:{userIdentifiers:[{emailAddress:"6a6c26195c3682faa816966af789717c3bfa834eee6c599d667d2b3429c27cfd"}]},conversionValue:149.99,currency:"EUR",eventName:"purchase",eventSource:"WEB"}],destinations:k,encoding:"HEX"}))]]},P={title:"Lead",description:"A demo request form submission is sent to Data Manager as a generate_lead conversion with a hashed email.",in:D("form submit",{id:"ev-1700000901000",timestamp:1700000901e3,data:{type:"demo-request"},user:{email:"prospect@example.com"},source:{type:"express",platform:"server"}}),mapping:{name:"generate_lead",data:{map:{transactionId:"id",eventName:{value:"generate_lead"},conversionValue:{value:10},currency:{value:"USD"},email:"user.email"}}},out:[["fetch",O,S(JSON.stringify({events:[{eventTimestamp:"2023-11-14T22:28:21.000Z",transactionId:"ev-1700000901000",userData:{userIdentifiers:[{emailAddress:"395ec5f334be0ab5b28568a1e7f6ed5ea80e443fb1ce3d803340586a3df46642"}]},conversionValue:10,currency:"USD",eventName:"generate_lead",eventSource:"WEB"}],destinations:k,encoding:"HEX"}))]]},_={title:"Page view",description:"A page view is sent to Data Manager as a page_view event tied to the walker user id.",in:D("page view",{id:"ev-1700000902000",timestamp:1700000902e3,data:{title:"Pricing",url:"https://example.com/pricing"},user:{id:"visitor-55"},source:{type:"express",platform:"server"}}),mapping:{name:"page_view",data:{map:{transactionId:"id",eventName:{value:"page_view"},userId:"user.id"}}},out:[["fetch",O,S(JSON.stringify({events:[{eventTimestamp:"2023-11-14T22:28:22.000Z",transactionId:"ev-1700000902000",userId:"visitor-55",eventName:"page_view",eventSource:"WEB"}],destinations:k,encoding:"HEX"}))]]};export{h as examples,t as schemas};//# sourceMappingURL=dev.mjs.map
package/dist/dev.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/schemas.ts","../src/schemas/primitives.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/schemas/index.ts","../src/examples/index.ts","../src/examples/env.ts","../src/examples/step.ts"],"sourcesContent":["// Browser-safe schema-only exports\n// This file exports ONLY schemas without any Node.js dependencies\nexport { settings, mapping } from './schemas/index';\n","import { z } from '@walkeros/core/dev';\n\nexport const AccountTypeSchema = z.enum([\n 'GOOGLE_ADS',\n 'DISPLAY_VIDEO_ADVERTISER',\n 'DISPLAY_VIDEO_PARTNER',\n 'GOOGLE_ANALYTICS_PROPERTY',\n]);\n\nexport const EventSourceSchema = z.enum([\n 'WEB',\n 'APP',\n 'IN_STORE',\n 'PHONE',\n 'OTHER',\n]);\n\nexport const ConsentStatusSchema = z.enum([\n 'CONSENT_GRANTED',\n 'CONSENT_DENIED',\n]);\n\nexport const ConsentSchema = z.object({\n adUserData: ConsentStatusSchema.describe(\n 'Consent for data collection and use',\n ).optional(),\n adPersonalization: ConsentStatusSchema.describe(\n 'Consent for ad personalization',\n ).optional(),\n});\n\nexport const OperatingAccountSchema = z.object({\n accountId: z\n .string()\n .min(1)\n .describe('Account ID (e.g., \"123-456-7890\" for Google Ads)'),\n accountType: AccountTypeSchema.describe('Type of account'),\n});\n\nexport const DestinationSchema = z.object({\n operatingAccount: OperatingAccountSchema.describe(\n 'Operating account details',\n ),\n productDestinationId: z\n .string()\n .min(1)\n .describe(\n 'Product-specific destination ID (conversion action or user list)',\n ),\n});\n","import { z } from '@walkeros/core/dev';\nimport {\n DestinationSchema,\n EventSourceSchema,\n ConsentSchema,\n} from './primitives';\n\n/**\n * Service account credentials schema\n */\nconst CredentialsSchema = z.object({\n client_email: z.string().email().describe('Service account email'),\n private_key: z\n .string()\n .min(1)\n .describe('Service account private key (PEM format)'),\n});\n\nexport const SettingsSchema = z.object({\n credentials: CredentialsSchema.optional().describe(\n 'Service account credentials (client_email + private_key). Recommended for serverless environments.',\n ),\n keyFilename: z\n .string()\n .optional()\n .describe(\n 'Path to service account JSON file. For local development or environments with filesystem access.',\n ),\n scopes: z\n .array(z.string())\n .optional()\n .describe(\n 'OAuth scopes for Data Manager API. Defaults to datamanager scope.',\n ),\n destinations: z\n .array(DestinationSchema)\n .min(1)\n .max(10)\n .describe(\n 'Array of destination accounts and conversion actions/user lists (max 10)',\n ),\n eventSource: EventSourceSchema.optional()\n .default('WEB')\n .describe(\n 'Event source for all events. Defaults to WEB. Values: WEB, APP, IN_STORE, PHONE, OTHER',\n ),\n batchSize: z\n .number()\n .int()\n .min(1)\n .max(2000)\n .describe(\n 'Maximum number of events to batch before sending (max 2000, like 100)',\n )\n .optional(),\n batchInterval: z\n .number()\n .int()\n .min(0)\n .describe(\n 'Time in milliseconds to wait before auto-flushing batch (like 5000)',\n )\n .optional(),\n validateOnly: z\n .boolean()\n .describe('If true, validate request without ingestion (testing mode)')\n .optional(),\n url: z\n .string()\n .url()\n .describe(\n 'Override API endpoint for testing (like https://datamanager.googleapis.com/v1)',\n )\n .optional(),\n consent: ConsentSchema.describe(\n 'Request-level consent for all events',\n ).optional(),\n testEventCode: z\n .string()\n .describe('Test event code for debugging (like TEST12345)')\n .optional(),\n logLevel: z\n .enum(['debug', 'info', 'warn', 'error', 'none'])\n .describe('Log level for debugging (debug shows all API calls)')\n .optional(),\n userData: z\n .record(z.string(), z.unknown())\n .describe(\n \"Guided helper: User data mapping for all events (like { email: 'user.id', phone: 'data.phone' })\",\n )\n .optional(),\n userId: z\n .any()\n .describe(\n \"Guided helper: First-party user ID for all events (like 'user.id')\",\n )\n .optional(),\n clientId: z\n .any()\n .describe(\n \"Guided helper: GA4 client ID for all events (like 'user.device')\",\n )\n .optional(),\n sessionAttributes: z\n .any()\n .describe(\n \"Guided helper: Privacy-safe attribution for all events (like 'context.sessionAttributes')\",\n )\n .optional(),\n consentAdUserData: z\n .union([z.string(), z.boolean()])\n .describe(\n \"Consent mapping: Field name from event.consent (like 'marketing') or static boolean value\",\n )\n .optional(),\n consentAdPersonalization: z\n .union([z.string(), z.boolean()])\n .describe(\n \"Consent mapping: Field name from event.consent (like 'targeting') or static boolean value\",\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\n// Data Manager uses flexible mapping via walkerOS mapping system\n// No event-specific mapping schema needed (similar to Meta CAPI pattern)\nexport const MappingSchema = z.object({});\n\nexport type Mapping = z.infer<typeof MappingSchema>;\n","export * from './primitives';\nexport * from './settings';\nexport * from './mapping';\n\nimport { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\n","export * as env from './env';\nexport * as step from './step';\n","import type { OAuth2Client } from 'google-auth-library';\nimport type { Env } from '../types';\n\n/**\n * Example environment configurations for Google Data Manager destination.\n *\n * The destination invokes `env.fetch(url, { method, headers, body })` once\n * per push, with `Authorization: Bearer <accessToken>` obtained from\n * `env.authClient` via `getAccessToken`.\n *\n * For tests we use a stub `authClient` (jest mocks the `getAccessToken`\n * helper at module level) and a mock `fetch` returning a successful ingest\n * response.\n */\n\nasync function mockFetch(): Promise<Response> {\n return {\n ok: true,\n status: 200,\n json: async () => ({ requestId: 'mock-request-id', validationErrors: [] }),\n text: async () => '',\n } as unknown as Response;\n}\n\nconst mockAuthClient = {\n getAccessToken: async () => ({ token: 'ya29.c.test_token' }),\n} as unknown as OAuth2Client;\n\nexport const push: Env = {\n fetch: mockFetch,\n authClient: mockAuthClient,\n};\n\nexport const simulation = ['fetch'];\n","import type { Flow } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\n\n/**\n * Google Data Manager step examples.\n *\n * At push time, the destination calls\n * `env.fetch(url, { method, headers, body })` where:\n * - `url` is `${settings.url}/events:ingest` (default\n * `https://datamanager.googleapis.com/v1`)\n * - `method` is `'POST'`\n * - `headers` is `{ Authorization: 'Bearer <accessToken>', 'Content-Type': 'application/json' }`\n * - `body` is the JSON-stringified `{ events: [dataManagerEvent], destinations }` payload\n *\n * The access token is obtained from `env.authClient` via `getAccessToken`.\n * The test fixture mocks both so the captured Authorization header is stable\n * (`Bearer ya29.c.test_token`).\n *\n * Event fields are emitted in the order the destination constructs them\n * (insertion order matters for `JSON.stringify` string equality):\n * eventTimestamp, transactionId?, clientId?, userId?, userData?,\n * adIdentifiers?, conversionValue?, currency?, cartData?, eventName?,\n * [eventSource is appended last by push.ts when not already present].\n *\n * Emails are normalized (trim, lowercase, strip dots for Gmail) and hashed\n * with SHA-256.\n */\nconst ENDPOINT = 'https://datamanager.googleapis.com/v1/events:ingest';\nconst DESTINATIONS = [\n {\n operatingAccount: {\n accountId: '123-456-7890',\n accountType: 'GOOGLE_ADS',\n },\n productDestinationId: 'AW-CONVERSION-123',\n },\n];\nconst INIT_OPTIONS = (body: string) => ({\n method: 'POST',\n headers: {\n Authorization: 'Bearer ya29.c.test_token',\n 'Content-Type': 'application/json',\n },\n body,\n});\n\nexport const purchase: Flow.StepExample = {\n title: 'Purchase',\n description:\n 'A completed order is posted to Google Data Manager as a purchase conversion with hashed user identifiers.',\n in: getEvent('order complete', {\n id: 'ev-1700000900000',\n timestamp: 1700000900000,\n data: { id: 'ORD-600', total: 149.99, currency: 'EUR' },\n user: { id: 'user-abc', email: 'buyer@example.com' },\n source: { type: 'express', platform: 'server' },\n }),\n mapping: {\n name: 'purchase',\n data: {\n map: {\n transactionId: 'data.id',\n conversionValue: 'data.total',\n currency: { key: 'data.currency', value: 'USD' },\n eventName: { value: 'purchase' },\n userId: 'user.id',\n email: 'user.email',\n },\n },\n },\n out: [\n [\n 'fetch',\n ENDPOINT,\n INIT_OPTIONS(\n JSON.stringify({\n events: [\n {\n eventTimestamp: '2023-11-14T22:28:20.000Z',\n transactionId: 'ORD-600',\n userId: 'user-abc',\n userData: {\n userIdentifiers: [\n {\n // sha256('buyer@example.com')\n emailAddress:\n '6a6c26195c3682faa816966af789717c3bfa834eee6c599d667d2b3429c27cfd',\n },\n ],\n },\n conversionValue: 149.99,\n currency: 'EUR',\n eventName: 'purchase',\n eventSource: 'WEB',\n },\n ],\n destinations: DESTINATIONS,\n }),\n ),\n ],\n ],\n};\n\nexport const lead: Flow.StepExample = {\n title: 'Lead',\n description:\n 'A demo request form submission is sent to Data Manager as a generate_lead conversion with a hashed email.',\n in: getEvent('form submit', {\n id: 'ev-1700000901000',\n timestamp: 1700000901000,\n data: { type: 'demo-request' },\n user: { email: 'prospect@example.com' },\n source: { type: 'express', platform: 'server' },\n }),\n mapping: {\n name: 'generate_lead',\n data: {\n map: {\n transactionId: 'id',\n eventName: { value: 'generate_lead' },\n conversionValue: { value: 10 },\n currency: { value: 'USD' },\n email: 'user.email',\n },\n },\n },\n out: [\n [\n 'fetch',\n ENDPOINT,\n INIT_OPTIONS(\n JSON.stringify({\n events: [\n {\n eventTimestamp: '2023-11-14T22:28:21.000Z',\n transactionId: 'ev-1700000901000',\n userData: {\n userIdentifiers: [\n {\n // sha256('prospect@example.com')\n emailAddress:\n '395ec5f334be0ab5b28568a1e7f6ed5ea80e443fb1ce3d803340586a3df46642',\n },\n ],\n },\n conversionValue: 10,\n currency: 'USD',\n eventName: 'generate_lead',\n eventSource: 'WEB',\n },\n ],\n destinations: DESTINATIONS,\n }),\n ),\n ],\n ],\n};\n\nexport const ga4PageView: Flow.StepExample = {\n title: 'Page view',\n description:\n 'A page view is sent to Data Manager as a page_view event tied to the walker user id.',\n in: getEvent('page view', {\n id: 'ev-1700000902000',\n timestamp: 1700000902000,\n data: { title: 'Pricing', url: 'https://example.com/pricing' },\n user: { id: 'visitor-55' },\n source: { type: 'express', platform: 'server' },\n }),\n mapping: {\n name: 'page_view',\n data: {\n map: {\n transactionId: 'id',\n eventName: { value: 'page_view' },\n userId: 'user.id',\n },\n },\n },\n out: [\n [\n 'fetch',\n ENDPOINT,\n INIT_OPTIONS(\n JSON.stringify({\n events: [\n {\n eventTimestamp: '2023-11-14T22:28:22.000Z',\n transactionId: 'ev-1700000902000',\n userId: 'visitor-55',\n eventName: 'page_view',\n eventSource: 'WEB',\n },\n ],\n destinations: DESTINATIONS,\n }),\n ),\n ],\n ],\n};\n"],"mappings":"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","names":["z","z","z"]}
1
+ {"version":3,"sources":["../src/schemas.ts","../src/schemas/primitives.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/schemas/index.ts","../src/examples/index.ts","../src/examples/env.ts","../src/examples/step.ts"],"sourcesContent":["// Browser-safe schema-only exports\n// This file exports ONLY schemas without any Node.js dependencies\nexport { settings, mapping } from './schemas/index';\n","import { z } from '@walkeros/core/dev';\n\nexport const AccountTypeSchema = z.enum([\n 'GOOGLE_ADS',\n 'DISPLAY_VIDEO_ADVERTISER',\n 'DISPLAY_VIDEO_PARTNER',\n 'GOOGLE_ANALYTICS_PROPERTY',\n]);\n\nexport const EventSourceSchema = z.enum([\n 'WEB',\n 'APP',\n 'IN_STORE',\n 'PHONE',\n 'OTHER',\n]);\n\nexport const ConsentStatusSchema = z.enum([\n 'CONSENT_GRANTED',\n 'CONSENT_DENIED',\n]);\n\nexport const ConsentSchema = z.object({\n adUserData: ConsentStatusSchema.describe(\n 'Consent for data collection and use',\n ).optional(),\n adPersonalization: ConsentStatusSchema.describe(\n 'Consent for ad personalization',\n ).optional(),\n});\n\nexport const OperatingAccountSchema = z.object({\n accountId: z\n .string()\n .min(1)\n .describe('Account ID (e.g., \"123-456-7890\" for Google Ads)'),\n accountType: AccountTypeSchema.describe('Type of account'),\n});\n\nexport const DestinationSchema = z.object({\n operatingAccount: OperatingAccountSchema.describe(\n 'Operating account details',\n ),\n productDestinationId: z\n .string()\n .min(1)\n .describe(\n 'Product-specific destination ID (conversion action or user list)',\n ),\n});\n","import { z } from '@walkeros/core/dev';\nimport {\n DestinationSchema,\n EventSourceSchema,\n ConsentSchema,\n} from './primitives';\n\n/**\n * Service account credentials schema\n */\nconst CredentialsSchema = z.object({\n client_email: z.string().email().describe('Service account email'),\n private_key: z\n .string()\n .min(1)\n .describe('Service account private key (PEM format)'),\n});\n\nexport const SettingsSchema = z.object({\n credentials: CredentialsSchema.optional().describe(\n 'Service account credentials (client_email + private_key). Recommended for serverless environments.',\n ),\n keyFilename: z\n .string()\n .optional()\n .describe(\n 'Path to service account JSON file. For local development or environments with filesystem access.',\n ),\n scopes: z\n .array(z.string())\n .optional()\n .describe(\n 'OAuth scopes for Data Manager API. Defaults to datamanager scope.',\n ),\n destinations: z\n .array(DestinationSchema)\n .min(1)\n .max(10)\n .describe(\n 'Array of destination accounts and conversion actions/user lists (max 10)',\n ),\n eventSource: EventSourceSchema.optional()\n .default('WEB')\n .describe(\n 'Event source for all events. Defaults to WEB. Values: WEB, APP, IN_STORE, PHONE, OTHER',\n ),\n batchSize: z\n .number()\n .int()\n .min(1)\n .max(2000)\n .describe(\n 'Maximum number of events to batch before sending (max 2000, like 100)',\n )\n .optional(),\n batchInterval: z\n .number()\n .int()\n .min(0)\n .describe(\n 'Time in milliseconds to wait before auto-flushing batch (like 5000)',\n )\n .optional(),\n validateOnly: z\n .boolean()\n .describe('If true, validate request without ingestion (testing mode)')\n .optional(),\n url: z\n .string()\n .url()\n .describe(\n 'Override API endpoint for testing (like https://datamanager.googleapis.com/v1)',\n )\n .optional(),\n consent: ConsentSchema.describe(\n 'Request-level consent for all events',\n ).optional(),\n testEventCode: z\n .string()\n .describe('Test event code for debugging (like TEST12345)')\n .optional(),\n logLevel: z\n .enum(['debug', 'info', 'warn', 'error', 'none'])\n .describe('Log level for debugging (debug shows all API calls)')\n .optional(),\n userData: z\n .record(z.string(), z.unknown())\n .describe(\n \"Guided helper: User data mapping for all events (like { email: 'user.id', phone: 'data.phone' })\",\n )\n .optional(),\n userId: z\n .any()\n .describe(\n \"Guided helper: First-party user ID for all events (like 'user.id')\",\n )\n .optional(),\n clientId: z\n .any()\n .describe(\n \"Guided helper: GA4 client ID for all events (like 'user.device')\",\n )\n .optional(),\n appInstanceId: z\n .any()\n .describe(\n \"Guided helper: GA4 app instance ID (Firebase) for all events (like 'user.appInstanceId')\",\n )\n .optional(),\n sessionAttributes: z\n .any()\n .describe(\n \"Guided helper: Privacy-safe attribution for all events (like 'context.sessionAttributes')\",\n )\n .optional(),\n consentAdUserData: z\n .union([z.string(), z.boolean()])\n .describe(\n \"Consent mapping: Field name from event.consent (like 'marketing') or static boolean value\",\n )\n .optional(),\n consentAdPersonalization: z\n .union([z.string(), z.boolean()])\n .describe(\n \"Consent mapping: Field name from event.consent (like 'targeting') or static boolean value\",\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\n// Data Manager uses flexible mapping via walkerOS mapping system\n// No event-specific mapping schema needed (similar to Meta CAPI pattern)\nexport const MappingSchema = z.object({});\n\nexport type Mapping = z.infer<typeof MappingSchema>;\n","export * from './primitives';\nexport * from './settings';\nexport * from './mapping';\n\nimport { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\n","export * as env from './env';\nexport * as step from './step';\n","import type { OAuth2Client } from 'google-auth-library';\nimport type { Env } from '../types';\n\n/**\n * Example environment configurations for Google Data Manager destination.\n *\n * The destination invokes `env.fetch(url, { method, headers, body })` once\n * per push, with `Authorization: Bearer <accessToken>` obtained from\n * `env.authClient` via `getAccessToken`.\n *\n * For tests we use a stub `authClient` (jest mocks the `getAccessToken`\n * helper at module level) and a mock `fetch` returning a successful ingest\n * response.\n */\n\nasync function mockFetch(): Promise<Response> {\n return {\n ok: true,\n status: 200,\n json: async () => ({ requestId: 'mock-request-id', validationErrors: [] }),\n text: async () => '',\n } as unknown as Response;\n}\n\nconst mockAuthClient = {\n getAccessToken: async () => ({ token: 'ya29.c.test_token' }),\n} as unknown as OAuth2Client;\n\nexport const push: Env = {\n fetch: mockFetch,\n authClient: mockAuthClient,\n};\n\nexport const simulation = ['fetch'];\n","import type { Flow } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\n\n/**\n * Google Data Manager step examples.\n *\n * At push time, the destination calls\n * `env.fetch(url, { method, headers, body })` where:\n * - `url` is `${settings.url}/events:ingest` (default\n * `https://datamanager.googleapis.com/v1`)\n * - `method` is `'POST'`\n * - `headers` is `{ Authorization: 'Bearer <accessToken>', 'Content-Type': 'application/json' }`\n * - `body` is the JSON-stringified `{ events: [dataManagerEvent], destinations }` payload\n *\n * The access token is obtained from `env.authClient` via `getAccessToken`.\n * The test fixture mocks both so the captured Authorization header is stable\n * (`Bearer ya29.c.test_token`).\n *\n * Event fields are emitted in the order the destination constructs them\n * (insertion order matters for `JSON.stringify` string equality):\n * eventTimestamp, transactionId?, clientId?, userId?, userData?,\n * adIdentifiers?, conversionValue?, currency?, cartData?, eventName?,\n * [eventSource is appended last by push.ts when not already present].\n *\n * Emails are normalized (trim, lowercase, strip dots for Gmail) and hashed\n * with SHA-256.\n */\nconst ENDPOINT = 'https://datamanager.googleapis.com/v1/events:ingest';\nconst DESTINATIONS = [\n {\n operatingAccount: {\n accountId: '123-456-7890',\n accountType: 'GOOGLE_ADS',\n },\n productDestinationId: 'AW-CONVERSION-123',\n },\n];\nconst INIT_OPTIONS = (body: string) => ({\n method: 'POST',\n headers: {\n Authorization: 'Bearer ya29.c.test_token',\n 'Content-Type': 'application/json',\n },\n body,\n});\n\nexport const purchase: Flow.StepExample = {\n title: 'Purchase',\n description:\n 'A completed order is posted to Google Data Manager as a purchase conversion with hashed user identifiers.',\n in: getEvent('order complete', {\n id: 'ev-1700000900000',\n timestamp: 1700000900000,\n data: { id: 'ORD-600', total: 149.99, currency: 'EUR' },\n user: { id: 'user-abc', email: 'buyer@example.com' },\n source: { type: 'express', platform: 'server' },\n }),\n mapping: {\n name: 'purchase',\n data: {\n map: {\n transactionId: 'data.id',\n conversionValue: 'data.total',\n currency: { key: 'data.currency', value: 'USD' },\n eventName: { value: 'purchase' },\n userId: 'user.id',\n email: 'user.email',\n },\n },\n },\n out: [\n [\n 'fetch',\n ENDPOINT,\n INIT_OPTIONS(\n JSON.stringify({\n events: [\n {\n eventTimestamp: '2023-11-14T22:28:20.000Z',\n transactionId: 'ORD-600',\n userId: 'user-abc',\n userData: {\n userIdentifiers: [\n {\n // sha256('buyer@example.com')\n emailAddress:\n '6a6c26195c3682faa816966af789717c3bfa834eee6c599d667d2b3429c27cfd',\n },\n ],\n },\n conversionValue: 149.99,\n currency: 'EUR',\n eventName: 'purchase',\n eventSource: 'WEB',\n },\n ],\n destinations: DESTINATIONS,\n encoding: 'HEX',\n }),\n ),\n ],\n ],\n};\n\nexport const lead: Flow.StepExample = {\n title: 'Lead',\n description:\n 'A demo request form submission is sent to Data Manager as a generate_lead conversion with a hashed email.',\n in: getEvent('form submit', {\n id: 'ev-1700000901000',\n timestamp: 1700000901000,\n data: { type: 'demo-request' },\n user: { email: 'prospect@example.com' },\n source: { type: 'express', platform: 'server' },\n }),\n mapping: {\n name: 'generate_lead',\n data: {\n map: {\n transactionId: 'id',\n eventName: { value: 'generate_lead' },\n conversionValue: { value: 10 },\n currency: { value: 'USD' },\n email: 'user.email',\n },\n },\n },\n out: [\n [\n 'fetch',\n ENDPOINT,\n INIT_OPTIONS(\n JSON.stringify({\n events: [\n {\n eventTimestamp: '2023-11-14T22:28:21.000Z',\n transactionId: 'ev-1700000901000',\n userData: {\n userIdentifiers: [\n {\n // sha256('prospect@example.com')\n emailAddress:\n '395ec5f334be0ab5b28568a1e7f6ed5ea80e443fb1ce3d803340586a3df46642',\n },\n ],\n },\n conversionValue: 10,\n currency: 'USD',\n eventName: 'generate_lead',\n eventSource: 'WEB',\n },\n ],\n destinations: DESTINATIONS,\n encoding: 'HEX',\n }),\n ),\n ],\n ],\n};\n\nexport const ga4PageView: Flow.StepExample = {\n title: 'Page view',\n description:\n 'A page view is sent to Data Manager as a page_view event tied to the walker user id.',\n in: getEvent('page view', {\n id: 'ev-1700000902000',\n timestamp: 1700000902000,\n data: { title: 'Pricing', url: 'https://example.com/pricing' },\n user: { id: 'visitor-55' },\n source: { type: 'express', platform: 'server' },\n }),\n mapping: {\n name: 'page_view',\n data: {\n map: {\n transactionId: 'id',\n eventName: { value: 'page_view' },\n userId: 'user.id',\n },\n },\n },\n out: [\n [\n 'fetch',\n ENDPOINT,\n INIT_OPTIONS(\n JSON.stringify({\n events: [\n {\n eventTimestamp: '2023-11-14T22:28:22.000Z',\n transactionId: 'ev-1700000902000',\n userId: 'visitor-55',\n eventName: 'page_view',\n eventSource: 'WEB',\n },\n ],\n destinations: DESTINATIONS,\n encoding: 'HEX',\n }),\n ),\n ],\n ],\n};\n"],"mappings":"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","names":["z","z","z"]}
@@ -122,7 +122,8 @@ var purchase = {
122
122
  eventSource: "WEB"
123
123
  }
124
124
  ],
125
- destinations: DESTINATIONS
125
+ destinations: DESTINATIONS,
126
+ encoding: "HEX"
126
127
  })
127
128
  )
128
129
  ]
@@ -174,7 +175,8 @@ var lead = {
174
175
  eventSource: "WEB"
175
176
  }
176
177
  ],
177
- destinations: DESTINATIONS
178
+ destinations: DESTINATIONS,
179
+ encoding: "HEX"
178
180
  })
179
181
  )
180
182
  ]
@@ -215,7 +217,8 @@ var ga4PageView = {
215
217
  eventSource: "WEB"
216
218
  }
217
219
  ],
218
- destinations: DESTINATIONS
220
+ destinations: DESTINATIONS,
221
+ encoding: "HEX"
219
222
  })
220
223
  )
221
224
  ]
@@ -101,7 +101,8 @@ var purchase = {
101
101
  eventSource: "WEB"
102
102
  }
103
103
  ],
104
- destinations: DESTINATIONS
104
+ destinations: DESTINATIONS,
105
+ encoding: "HEX"
105
106
  })
106
107
  )
107
108
  ]
@@ -153,7 +154,8 @@ var lead = {
153
154
  eventSource: "WEB"
154
155
  }
155
156
  ],
156
- destinations: DESTINATIONS
157
+ destinations: DESTINATIONS,
158
+ encoding: "HEX"
157
159
  })
158
160
  )
159
161
  ]
@@ -194,7 +196,8 @@ var ga4PageView = {
194
196
  eventSource: "WEB"
195
197
  }
196
198
  ],
197
- destinations: DESTINATIONS
199
+ destinations: DESTINATIONS,
200
+ encoding: "HEX"
198
201
  })
199
202
  )
200
203
  ]
package/dist/index.d.mts CHANGED
@@ -43,6 +43,8 @@ interface Settings {
43
43
  userId?: Mapping$1.Value;
44
44
  /** Guided helper: GA4 client ID */
45
45
  clientId?: Mapping$1.Value;
46
+ /** Guided helper: GA4 app instance ID (Firebase) */
47
+ appInstanceId?: Mapping$1.Value;
46
48
  /** Guided helper: Privacy-safe attribution (Google's sessionAttributes) */
47
49
  sessionAttributes?: Mapping$1.Value;
48
50
  /** Consent mapping: Map consent field to adUserData (string = field name, boolean = static value) */
@@ -111,6 +113,11 @@ interface ProductAccount {
111
113
  }
112
114
  type AccountType = 'ACCOUNT_TYPE_UNSPECIFIED' | 'GOOGLE_ADS' | 'DISPLAY_VIDEO_ADVERTISER' | 'DISPLAY_VIDEO_PARTNER' | 'GOOGLE_ANALYTICS_PROPERTY' | 'DATA_PARTNER';
113
115
  type EventSource = 'WEB' | 'APP' | 'IN_STORE' | 'PHONE' | 'OTHER';
116
+ /**
117
+ * Hash encoding for user identifiers (required for UserData uploads)
118
+ * https://developers.google.com/data-manager/api/reference/rest/v1/Encoding
119
+ */
120
+ type Encoding = 'HEX' | 'BASE64';
114
121
  /**
115
122
  * Consent for Digital Markets Act (DMA) compliance
116
123
  * https://developers.google.com/data-manager/api/devguides/concepts/dma
@@ -137,6 +144,8 @@ interface IngestEventsRequest {
137
144
  validateOnly?: boolean;
138
145
  /** Test event code for debugging */
139
146
  testEventCode?: string;
147
+ /** Hash encoding for user identifiers. Required for UserData uploads. */
148
+ encoding?: Encoding;
140
149
  }
141
150
  /**
142
151
  * Single event for ingestion
@@ -181,6 +190,20 @@ interface Event {
181
190
  userId?: string;
182
191
  /** Additional event parameters */
183
192
  additionalEventParameters?: EventParameter[];
193
+ /** GA4 app instance ID (Firebase) */
194
+ appInstanceId?: string;
195
+ /** Third-party user data (e.g. data partner identifiers) */
196
+ thirdPartyUserData?: UserData;
197
+ /** Event location (required for Store Sales / IN_STORE events) */
198
+ eventLocation?: EventLocation;
199
+ }
200
+ /**
201
+ * Event location data
202
+ * https://developers.google.com/data-manager/api/reference/rest/v1/EventLocation
203
+ */
204
+ interface EventLocation {
205
+ /** Required for Store Sales. Identifier of the physical store where the event happened. */
206
+ storeId?: string;
184
207
  }
185
208
  /**
186
209
  * Device information
@@ -353,8 +376,10 @@ type index_CustomVariable = CustomVariable;
353
376
  type index_Destination = Destination;
354
377
  type index_DestinationInterface = DestinationInterface;
355
378
  type index_DeviceInfo = DeviceInfo;
379
+ type index_Encoding = Encoding;
356
380
  type index_Env = Env;
357
381
  type index_Event = Event;
382
+ type index_EventLocation = EventLocation;
358
383
  type index_EventParameter = EventParameter;
359
384
  type index_EventSource = EventSource;
360
385
  type index_ExperimentalField = ExperimentalField;
@@ -380,7 +405,7 @@ type index_UserProperties = UserProperties;
380
405
  type index_ValidatedConfig = ValidatedConfig;
381
406
  type index_ValidationError = ValidationError;
382
407
  declare namespace index {
383
- export type { index_AccountType as AccountType, index_AdIdentifiers as AdIdentifiers, index_Address as Address, index_CartData as CartData, index_CartItem as CartItem, index_Config as Config, index_Consent as Consent, index_ConsentStatus as ConsentStatus, index_CustomVariable as CustomVariable, index_Destination as Destination, index_DestinationInterface as DestinationInterface, index_DeviceInfo as DeviceInfo, index_Env as Env, index_Event as Event, index_EventParameter as EventParameter, index_EventSource as EventSource, index_ExperimentalField as ExperimentalField, index_IngestEventsRequest as IngestEventsRequest, index_IngestEventsResponse as IngestEventsResponse, index_InitFn as InitFn, index_InitSettings as InitSettings, index_Mapping as Mapping, index_PartialConfig as PartialConfig, index_ProductAccount as ProductAccount, index_PushEvents as PushEvents, index_PushFn as PushFn, index_RequestError as RequestError, index_RequestState as RequestState, index_RequestStatusResponse as RequestStatusResponse, index_Rule as Rule, index_Rules as Rules, index_Settings as Settings, index_Types as Types, index_UserData as UserData, index_UserIdentifier as UserIdentifier, index_UserProperties as UserProperties, index_ValidatedConfig as ValidatedConfig, index_ValidationError as ValidationError };
408
+ export type { index_AccountType as AccountType, index_AdIdentifiers as AdIdentifiers, index_Address as Address, index_CartData as CartData, index_CartItem as CartItem, index_Config as Config, index_Consent as Consent, index_ConsentStatus as ConsentStatus, index_CustomVariable as CustomVariable, index_Destination as Destination, index_DestinationInterface as DestinationInterface, index_DeviceInfo as DeviceInfo, index_Encoding as Encoding, index_Env as Env, index_Event as Event, index_EventLocation as EventLocation, index_EventParameter as EventParameter, index_EventSource as EventSource, index_ExperimentalField as ExperimentalField, index_IngestEventsRequest as IngestEventsRequest, index_IngestEventsResponse as IngestEventsResponse, index_InitFn as InitFn, index_InitSettings as InitSettings, index_Mapping as Mapping, index_PartialConfig as PartialConfig, index_ProductAccount as ProductAccount, index_PushEvents as PushEvents, index_PushFn as PushFn, index_RequestError as RequestError, index_RequestState as RequestState, index_RequestStatusResponse as RequestStatusResponse, index_Rule as Rule, index_Rules as Rules, index_Settings as Settings, index_Types as Types, index_UserData as UserData, index_UserIdentifier as UserIdentifier, index_UserProperties as UserProperties, index_ValidatedConfig as ValidatedConfig, index_ValidationError as ValidationError };
384
409
  }
385
410
 
386
411
  declare const destinationDataManager: DestinationInterface;