@walkeros/server-destination-datamanager 0.3.1 → 0.4.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/dist/index.d.ts CHANGED
@@ -1,11 +1,28 @@
1
- import { Destination as Destination$1, Mapping as Mapping$1, JSONSchema } from '@walkeros/core';
1
+ import { Destination as Destination$1, Mapping as Mapping$1 } from '@walkeros/core';
2
2
  import { DestinationServer } from '@walkeros/server-core';
3
+ import { OAuth2Client } from 'google-auth-library';
3
4
 
4
5
  type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'none';
5
6
 
6
7
  interface Settings {
7
- /** OAuth 2.0 access token with datamanager scope */
8
- accessToken: string;
8
+ /**
9
+ * Service account credentials (client_email + private_key)
10
+ * Recommended for serverless environments (AWS Lambda, Docker, etc.)
11
+ */
12
+ credentials?: {
13
+ client_email: string;
14
+ private_key: string;
15
+ };
16
+ /**
17
+ * Path to service account JSON file
18
+ * For local development or environments with filesystem access
19
+ */
20
+ keyFilename?: string;
21
+ /**
22
+ * OAuth scopes for Data Manager API
23
+ * @default ['https://www.googleapis.com/auth/datamanager']
24
+ */
25
+ scopes?: string[];
9
26
  /** Array of destination accounts and conversion actions/user lists */
10
27
  destinations: Destination[];
11
28
  /** Default event source if not specified per event */
@@ -45,8 +62,10 @@ interface Mapping {
45
62
  }
46
63
  interface Env extends DestinationServer.Env {
47
64
  fetch?: typeof fetch;
65
+ authClient?: OAuth2Client | null;
48
66
  }
49
- type Types = Destination$1.Types<Settings, Mapping, Env>;
67
+ type InitSettings = Partial<Settings>;
68
+ type Types = Destination$1.Types<Settings, Mapping, Env, InitSettings>;
50
69
  interface DestinationInterface extends DestinationServer.Destination<Types> {
51
70
  init: DestinationServer.InitFn<Types>;
52
71
  }
@@ -64,21 +83,27 @@ type Rules = Mapping$1.Rules<Rule>;
64
83
  * https://developers.google.com/data-manager/api/reference/rest/v1/Destination
65
84
  */
66
85
  interface Destination {
67
- /** Operating account details */
68
- operatingAccount: OperatingAccount;
86
+ /** Reference identifier for this destination */
87
+ reference?: string;
88
+ /** Login account (account initiating the request) */
89
+ loginAccount?: ProductAccount;
90
+ /** Linked account (child account linked to login account) */
91
+ linkedAccount?: ProductAccount;
92
+ /** Operating account (account where data is sent) */
93
+ operatingAccount?: ProductAccount;
69
94
  /** Product-specific destination ID (conversion action or user list) */
70
- productDestinationId: string;
95
+ productDestinationId?: string;
71
96
  }
72
97
  /**
73
- * Operating account information
98
+ * Product account information
74
99
  */
75
- interface OperatingAccount {
100
+ interface ProductAccount {
76
101
  /** Account ID (e.g., "123-456-7890" for Google Ads) */
77
102
  accountId: string;
78
103
  /** Type of account */
79
104
  accountType: AccountType;
80
105
  }
81
- type AccountType = 'GOOGLE_ADS' | 'DISPLAY_VIDEO_ADVERTISER' | 'DISPLAY_VIDEO_PARTNER' | 'GOOGLE_ANALYTICS_PROPERTY';
106
+ type AccountType = 'ACCOUNT_TYPE_UNSPECIFIED' | 'GOOGLE_ADS' | 'DISPLAY_VIDEO_ADVERTISER' | 'DISPLAY_VIDEO_PARTNER' | 'GOOGLE_ANALYTICS_PROPERTY' | 'DATA_PARTNER';
82
107
  type EventSource = 'WEB' | 'APP' | 'IN_STORE' | 'PHONE' | 'OTHER';
83
108
  /**
84
109
  * Consent for Digital Markets Act (DMA) compliance
@@ -96,12 +121,10 @@ type ConsentStatus = 'CONSENT_GRANTED' | 'CONSENT_DENIED';
96
121
  * https://developers.google.com/data-manager/api/reference/rest/v1/events/ingest
97
122
  */
98
123
  interface IngestEventsRequest {
99
- /** OAuth 2.0 access token */
100
- access_token?: string;
101
- /** Array of events to ingest (max 2000) */
102
- events: Event[];
103
124
  /** Array of destinations for these events (max 10) */
104
125
  destinations: Destination[];
126
+ /** Array of events to ingest (max 2000) */
127
+ events: Event[];
105
128
  /** Request-level consent (overridden by event-level) */
106
129
  consent?: Consent;
107
130
  /** If true, validate without ingestion */
@@ -114,30 +137,85 @@ interface IngestEventsRequest {
114
137
  * https://developers.google.com/data-manager/api/reference/rest/v1/Event
115
138
  */
116
139
  interface Event {
117
- /** Event timestamp in RFC 3339 format */
118
- eventTimestamp: string;
140
+ /** Destination references for routing */
141
+ destinationReferences?: string[];
119
142
  /** Transaction ID for deduplication (max 512 chars) */
120
143
  transactionId?: string;
121
- /** Google Analytics client ID (max 255 chars) */
122
- clientId?: string;
123
- /** First-party user ID (max 256 chars) */
124
- userId?: string;
144
+ /** Event timestamp in RFC 3339 format */
145
+ eventTimestamp?: string;
146
+ /** Last updated timestamp in RFC 3339 format */
147
+ lastUpdatedTimestamp?: string;
125
148
  /** User data with identifiers (max 10 identifiers) */
126
149
  userData?: UserData;
150
+ /** Event-level consent (overrides request-level) */
151
+ consent?: Consent;
127
152
  /** Attribution identifiers */
128
153
  adIdentifiers?: AdIdentifiers;
129
- /** Conversion value */
130
- conversionValue?: number;
131
154
  /** Currency code (ISO 4217, 3 chars) */
132
155
  currency?: string;
156
+ /** Conversion value */
157
+ conversionValue?: number;
158
+ /** Source of the event */
159
+ eventSource?: EventSource;
160
+ /** Device information for the event */
161
+ eventDeviceInfo?: DeviceInfo;
133
162
  /** Shopping cart data */
134
163
  cartData?: CartData;
164
+ /** Custom variables for the event */
165
+ customVariables?: CustomVariable[];
166
+ /** Experimental fields (subject to change) */
167
+ experimentalFields?: ExperimentalField[];
168
+ /** User properties */
169
+ userProperties?: UserProperties;
135
170
  /** Event name for GA4 (max 40 chars, required for GA4) */
136
171
  eventName?: string;
137
- /** Source of the event */
138
- eventSource?: EventSource;
139
- /** Event-level consent (overrides request-level) */
140
- consent?: Consent;
172
+ /** Google Analytics client ID (max 255 chars) */
173
+ clientId?: string;
174
+ /** First-party user ID (max 256 chars) */
175
+ userId?: string;
176
+ /** Additional event parameters */
177
+ additionalEventParameters?: EventParameter[];
178
+ }
179
+ /**
180
+ * Device information
181
+ */
182
+ interface DeviceInfo {
183
+ /** User agent string */
184
+ userAgent?: string;
185
+ }
186
+ /**
187
+ * Custom variable
188
+ */
189
+ interface CustomVariable {
190
+ /** Variable name */
191
+ name?: string;
192
+ /** Variable value */
193
+ value?: string;
194
+ }
195
+ /**
196
+ * Experimental field
197
+ */
198
+ interface ExperimentalField {
199
+ /** Field name */
200
+ name?: string;
201
+ /** Field value */
202
+ value?: string;
203
+ }
204
+ /**
205
+ * User properties
206
+ */
207
+ interface UserProperties {
208
+ /** Property values */
209
+ [key: string]: string | number | boolean | undefined;
210
+ }
211
+ /**
212
+ * Event parameter
213
+ */
214
+ interface EventParameter {
215
+ /** Parameter name */
216
+ name?: string;
217
+ /** Parameter value */
218
+ value?: string | number;
141
219
  }
142
220
  /**
143
221
  * User data with identifiers
@@ -176,14 +254,16 @@ interface Address {
176
254
  * https://developers.google.com/data-manager/api/reference/rest/v1/AdIdentifiers
177
255
  */
178
256
  interface AdIdentifiers {
257
+ /** Session attributes (privacy-safe attribution) */
258
+ sessionAttributes?: string;
179
259
  /** Google Click ID (primary attribution) */
180
260
  gclid?: string;
181
261
  /** iOS attribution identifier (post-ATT) */
182
262
  gbraid?: string;
183
263
  /** Web-to-app attribution identifier */
184
264
  wbraid?: string;
185
- /** Session attributes (privacy-safe attribution) */
186
- sessionAttributes?: string;
265
+ /** Device information for landing page */
266
+ landingPageDeviceInfo?: DeviceInfo;
187
267
  }
188
268
  /**
189
269
  * Shopping cart data
@@ -255,118 +335,47 @@ interface RequestError {
255
335
  eventCount?: number;
256
336
  }
257
337
 
258
- type index$1_AccountType = AccountType;
259
- type index$1_AdIdentifiers = AdIdentifiers;
260
- type index$1_Address = Address;
261
- type index$1_CartData = CartData;
262
- type index$1_CartItem = CartItem;
263
- type index$1_Config = Config;
264
- type index$1_Consent = Consent;
265
- type index$1_ConsentStatus = ConsentStatus;
266
- type index$1_Destination = Destination;
267
- type index$1_DestinationInterface = DestinationInterface;
268
- type index$1_Env = Env;
269
- type index$1_Event = Event;
270
- type index$1_EventSource = EventSource;
271
- type index$1_IngestEventsRequest = IngestEventsRequest;
272
- type index$1_IngestEventsResponse = IngestEventsResponse;
273
- type index$1_InitFn = InitFn;
274
- type index$1_Mapping = Mapping;
275
- type index$1_OperatingAccount = OperatingAccount;
276
- type index$1_PartialConfig = PartialConfig;
277
- type index$1_PushEvents = PushEvents;
278
- type index$1_PushFn = PushFn;
279
- type index$1_RequestError = RequestError;
280
- type index$1_RequestState = RequestState;
281
- type index$1_RequestStatusResponse = RequestStatusResponse;
282
- type index$1_Rule = Rule;
283
- type index$1_Rules = Rules;
284
- type index$1_Settings = Settings;
285
- type index$1_Types = Types;
286
- type index$1_UserData = UserData;
287
- type index$1_UserIdentifier = UserIdentifier;
288
- type index$1_ValidationError = ValidationError;
289
- declare namespace index$1 {
290
- export type { index$1_AccountType as AccountType, index$1_AdIdentifiers as AdIdentifiers, index$1_Address as Address, index$1_CartData as CartData, index$1_CartItem as CartItem, index$1_Config as Config, index$1_Consent as Consent, index$1_ConsentStatus as ConsentStatus, index$1_Destination as Destination, index$1_DestinationInterface as DestinationInterface, index$1_Env as Env, index$1_Event as Event, index$1_EventSource as EventSource, index$1_IngestEventsRequest as IngestEventsRequest, index$1_IngestEventsResponse as IngestEventsResponse, index$1_InitFn as InitFn, index$1_Mapping as Mapping, index$1_OperatingAccount as OperatingAccount, index$1_PartialConfig as PartialConfig, index$1_PushEvents as PushEvents, index$1_PushFn as PushFn, index$1_RequestError as RequestError, index$1_RequestState as RequestState, index$1_RequestStatusResponse as RequestStatusResponse, index$1_Rule as Rule, index$1_Rules as Rules, index$1_Settings as Settings, index$1_Types as Types, index$1_UserData as UserData, index$1_UserIdentifier as UserIdentifier, index$1_ValidationError as ValidationError };
291
- }
292
-
293
- /**
294
- * Purchase event mapping for Google Ads conversion
295
- */
296
- declare const Purchase: Rule;
297
- /**
298
- * Lead event mapping
299
- */
300
- declare const Lead: Rule;
301
- /**
302
- * Page view mapping for GA4
303
- */
304
- declare const PageView: Rule;
305
- /**
306
- * Complete mapping configuration
307
- */
308
- declare const mapping: {
309
- order: {
310
- complete: Rule;
311
- };
312
- lead: {
313
- submit: Rule;
314
- };
315
- page: {
316
- view: Rule;
317
- };
318
- };
319
- /**
320
- * User data mapping configuration
321
- * Maps walkerOS user properties to Data Manager user identifiers
322
- */
323
- declare const userDataMapping: Config;
324
-
325
- declare const mapping$1_Lead: typeof Lead;
326
- declare const mapping$1_PageView: typeof PageView;
327
- declare const mapping$1_Purchase: typeof Purchase;
328
- declare const mapping$1_mapping: typeof mapping;
329
- declare const mapping$1_userDataMapping: typeof userDataMapping;
330
- declare namespace mapping$1 {
331
- export { mapping$1_Lead as Lead, mapping$1_PageView as PageView, mapping$1_Purchase as Purchase, mapping$1_mapping as mapping, mapping$1_userDataMapping as userDataMapping };
332
- }
333
-
334
- /**
335
- * Minimal configuration for Google Data Manager
336
- */
337
- declare const minimal: Config;
338
- /**
339
- * Complete configuration with all options
340
- */
341
- declare const complete: Config;
342
- /**
343
- * GA4-specific configuration
344
- */
345
- declare const ga4: Config;
346
- /**
347
- * Debug configuration with logging enabled
348
- */
349
- declare const debug: Config;
350
-
351
- declare const basic_complete: typeof complete;
352
- declare const basic_debug: typeof debug;
353
- declare const basic_ga4: typeof ga4;
354
- declare const basic_minimal: typeof minimal;
355
- declare namespace basic {
356
- export { basic_complete as complete, basic_debug as debug, basic_ga4 as ga4, basic_minimal as minimal };
357
- }
358
-
359
- declare const index_basic: typeof basic;
338
+ type index_AccountType = AccountType;
339
+ type index_AdIdentifiers = AdIdentifiers;
340
+ type index_Address = Address;
341
+ type index_CartData = CartData;
342
+ type index_CartItem = CartItem;
343
+ type index_Config = Config;
344
+ type index_Consent = Consent;
345
+ type index_ConsentStatus = ConsentStatus;
346
+ type index_CustomVariable = CustomVariable;
347
+ type index_Destination = Destination;
348
+ type index_DestinationInterface = DestinationInterface;
349
+ type index_DeviceInfo = DeviceInfo;
350
+ type index_Env = Env;
351
+ type index_Event = Event;
352
+ type index_EventParameter = EventParameter;
353
+ type index_EventSource = EventSource;
354
+ type index_ExperimentalField = ExperimentalField;
355
+ type index_IngestEventsRequest = IngestEventsRequest;
356
+ type index_IngestEventsResponse = IngestEventsResponse;
357
+ type index_InitFn = InitFn;
358
+ type index_InitSettings = InitSettings;
359
+ type index_Mapping = Mapping;
360
+ type index_PartialConfig = PartialConfig;
361
+ type index_ProductAccount = ProductAccount;
362
+ type index_PushEvents = PushEvents;
363
+ type index_PushFn = PushFn;
364
+ type index_RequestError = RequestError;
365
+ type index_RequestState = RequestState;
366
+ type index_RequestStatusResponse = RequestStatusResponse;
367
+ type index_Rule = Rule;
368
+ type index_Rules = Rules;
369
+ type index_Settings = Settings;
370
+ type index_Types = Types;
371
+ type index_UserData = UserData;
372
+ type index_UserIdentifier = UserIdentifier;
373
+ type index_UserProperties = UserProperties;
374
+ type index_ValidationError = ValidationError;
360
375
  declare namespace index {
361
- export { index_basic as basic, mapping$1 as mapping };
362
- }
363
-
364
- declare const schemas$1: Record<string, JSONSchema>;
365
-
366
- declare namespace schemas {
367
- export { schemas$1 as schemas };
376
+ 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_ValidationError as ValidationError };
368
377
  }
369
378
 
370
379
  declare const destinationDataManager: DestinationInterface;
371
380
 
372
- export { index$1 as DestinationDataManager, destinationDataManager as default, destinationDataManager, index as examples, schemas };
381
+ export { index as DestinationDataManager, destinationDataManager as default, destinationDataManager };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";var e,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,a=Object.getOwnPropertyNames,i=Object.prototype.hasOwnProperty,o=(e,n)=>{for(var a in n)t(e,a,{get:n[a],enumerable:!0})},s={};o(s,{DestinationDataManager:()=>b,default:()=>U,destinationDataManager:()=>W,examples:()=>f,schemas:()=>k}),module.exports=(e=s,((e,o,s,r)=>{if(o&&"object"==typeof o||"function"==typeof o)for(let c of a(o))i.call(e,c)||c===s||t(e,c,{get:()=>o[c],enumerable:!(r=n(o,c))||r.enumerable});return e})(t({},"__esModule",{value:!0}),e));var r=require("@walkeros/core");var c=require("@walkeros/core"),d=require("@walkeros/core"),l=require("@walkeros/core"),u=require("@walkeros/server-core");async function g(e,t="given"){if(!(0,l.isString)(e)||!e)return"";let n=e.trim().toLowerCase();if("given"===t){const e=["mr.","mrs.","ms.","miss.","dr.","prof."];for(const t of e)if(n.startsWith(t)){n=n.substring(t.length).trim();break}}if("family"===t){const e=["jr.","sr.","iii","ii","iv","v"];for(const t of e){const e=` ${t}`;if(n.endsWith(e)){n=n.substring(0,n.length-e.length).trim();break}if(n.endsWith(t)){n=n.substring(0,n.length-t.length).trim();break}}}return(0,u.getHashServer)(n)}async function p(e){const t=[];if((0,d.isString)(e.email)&&e.email){const n=await async function(e){if(!(0,l.isString)(e)||!e)return"";let t=e.trim().toLowerCase();if(t.endsWith("@gmail.com")||t.endsWith("@googlemail.com")){const[e,n]=t.split("@");t=`${e.replace(/\./g,"")}@${n}`}return(0,u.getHashServer)(t)}(e.email);n&&t.push({emailAddress:n})}if((0,d.isString)(e.phone)&&e.phone){const n=await async function(e){if(!(0,l.isString)(e)||!e)return"";let t=e.trim();const n=t.startsWith("+");return t=t.replace(/\D/g,""),t=n||t.length>10?`+${t}`:`+1${t}`,(0,u.getHashServer)(t)}(e.phone);n&&t.push({phoneNumber:n})}if(e.firstName||e.lastName||e.regionCode||e.postalCode){const n={};(0,d.isString)(e.firstName)&&e.firstName&&(n.givenName=await g(e.firstName,"given")),(0,d.isString)(e.lastName)&&e.lastName&&(n.familyName=await g(e.lastName,"family")),(0,d.isString)(e.regionCode)&&e.regionCode&&(n.regionCode=e.regionCode.toUpperCase()),(0,d.isString)(e.postalCode)&&e.postalCode&&(n.postalCode=e.postalCode),Object.keys(n).length>0&&t.push({address:n})}if(0!==t.length)return{userIdentifiers:t.slice(0,10)}}async function m(e,t){const n={eventTimestamp:(a=e.timestamp,new Date(a).toISOString())};var a;const i=t||{};(0,d.isString)(i.transactionId)&&i.transactionId&&(n.transactionId=i.transactionId.substring(0,512)),(0,d.isString)(i.clientId)&&i.clientId&&(n.clientId=i.clientId.substring(0,255)),(0,d.isString)(i.userId)&&i.userId&&(n.userId=i.userId.substring(0,256));const o=await p(i);o&&(n.userData=o);const s=function(e){const t={};return(0,d.isString)(e.gclid)&&e.gclid&&(t.gclid=e.gclid),(0,d.isString)(e.gbraid)&&e.gbraid&&(t.gbraid=e.gbraid),(0,d.isString)(e.wbraid)&&e.wbraid&&(t.wbraid=e.wbraid),(0,d.isString)(e.sessionAttributes)&&e.sessionAttributes&&(t.sessionAttributes=e.sessionAttributes),Object.keys(t).length>0?t:void 0}(i);s&&(n.adIdentifiers=s),"number"==typeof i.conversionValue&&(n.conversionValue=i.conversionValue),(0,d.isString)(i.currency)&&i.currency&&(n.currency=i.currency.substring(0,3).toUpperCase()),i.cartData&&"object"==typeof i.cartData&&(n.cartData=i.cartData),(0,d.isString)(i.eventName)&&i.eventName&&(n.eventName=i.eventName.substring(0,40)),(0,d.isString)(i.eventSource)&&i.eventSource&&(n.eventSource=i.eventSource);const r={};if("boolean"==typeof i.adUserData&&(r.adUserData=i.adUserData?"CONSENT_GRANTED":"CONSENT_DENIED"),"boolean"==typeof i.adPersonalization&&(r.adPersonalization=i.adPersonalization?"CONSENT_GRANTED":"CONSENT_DENIED"),0===Object.keys(r).length){const t=function(e){if(!e)return;const t={};return(0,d.isDefined)(e.marketing)&&(t.adUserData=e.marketing?"CONSENT_GRANTED":"CONSENT_DENIED"),(0,d.isDefined)(e.personalization)&&(t.adPersonalization=e.personalization?"CONSENT_GRANTED":"CONSENT_DENIED"),Object.keys(t).length>0?t:void 0}(e.consent);t&&(n.consent=t)}else n.consent=r;return n}var v=async function(e,{config:t,mapping:n,data:a,collector:i,env:o}){const{accessToken:s,destinations:r,eventSource:d,validateOnly:l=!1,url:u="https://datamanager.googleapis.com/v1",consent:g,testEventCode:p,logLevel:v="none",userData:b,userId:f,clientId:N,sessionAttributes:y,consentAdUserData:I,consentAdPersonalization:D}=t.settings,S=function(e="none"){const t={debug:0,info:1,warn:2,error:3,none:4}[e];return{debug:(e,n)=>{t<=0&&console.log(`[DataManager] ${e}`,n||"")},info:(e,n)=>{t<=1&&console.log(`[DataManager] ${e}`,n||"")},warn:(e,n)=>{t<=2&&console.warn(`[DataManager] ${e}`,n||"")},error:(e,n)=>{t<=3&&console.error(`[DataManager] ${e}`,n||"")}}}(v),h=b?await(0,c.getMappingValue)(e,{map:b}):{},O=f?await(0,c.getMappingValue)(e,f):void 0,E=N?await(0,c.getMappingValue)(e,N):void 0,A=y?await(0,c.getMappingValue)(e,y):void 0,w="boolean"==typeof I?I:"string"==typeof I&&e.consent?e.consent[I]:void 0,T="boolean"==typeof D?D:"string"==typeof D&&e.consent?e.consent[D]:void 0,z={};(0,c.isObject)(h)&&Object.assign(z,h),void 0!==O&&(z.userId=O),void 0!==E&&(z.clientId=E),void 0!==A&&(z.sessionAttributes=A),void 0!==w&&(z.adUserData=w),void 0!==T&&(z.adPersonalization=T);const k=t.data?await(0,c.getMappingValue)(e,t.data):{},C=(0,c.isObject)(a)?a:{},P={...z,...(0,c.isObject)(k)?k:{},...C},_=await m(e,P);S.debug("Processing event",{name:e.name,id:e.id,timestamp:e.timestamp}),!_.eventSource&&d&&(_.eventSource=d),!_.consent&&g&&(_.consent=g);const x={events:[_],destinations:r};g&&(x.consent=g),l&&(x.validateOnly=!0),p&&(x.testEventCode=p);const G=(null==o?void 0:o.fetch)||fetch,R=`${u}/events:ingest`;S.debug("Sending to Data Manager API",{endpoint:R,eventCount:x.events.length,destinations:r.length,validateOnly:l});const j=await G(R,{method:"POST",headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json"},body:JSON.stringify(x)});if(!j.ok){const e=await j.text();throw S.error("API request failed",{status:j.status,error:e}),new Error(`Data Manager API error (${j.status}): ${e}`)}const L=await j.json();if(S.debug("API response",{status:j.status,requestId:L.requestId}),L.validationErrors&&L.validationErrors.length>0)throw S.error("Validation errors",{errors:L.validationErrors}),new Error(`Validation errors: ${JSON.stringify(L.validationErrors)}`);S.info("Event processed successfully",{requestId:L.requestId})},b={},f={};o(f,{basic:()=>E,mapping:()=>N});var N={};o(N,{Lead:()=>D,PageView:()=>S,Purchase:()=>I,mapping:()=>h,userDataMapping:()=>O});var y=require("@walkeros/core"),I={name:"purchase",data:{map:{transactionId:"data.id",conversionValue:"data.total",currency:{key:"data.currency",value:"USD"},eventName:{value:"purchase"},userId:"user.id",email:"user.id",gclid:"context.gclid",gbraid:"context.gbraid",wbraid:"context.wbraid",cartData:{map:{items:{loop:["nested",{condition:e=>(0,y.isObject)(e)&&"product"===e.entity,map:{merchantProductId:"data.id",price:"data.price",quantity:{key:"data.quantity",value:1}}}]}}}}}},D={name:"generate_lead",data:{map:{eventName:{value:"generate_lead"},conversionValue:{value:10},currency:{value:"USD"}}}},S={name:"page_view",data:{map:{eventName:{value:"page_view"}}}},h={order:{complete:I},lead:{submit:D},page:{view:S}},O={settings:{accessToken:"ya29.c.xxx",destinations:[{operatingAccount:{accountId:"123-456-7890",accountType:"GOOGLE_ADS"},productDestinationId:"AW-CONVERSION-123"}]},data:{map:{email:"user.id",phone:"data.phone",firstName:"data.firstName",lastName:"data.lastName",regionCode:"data.country",postalCode:"data.zip"}},mapping:h},E={};o(E,{complete:()=>w,debug:()=>z,ga4:()=>T,minimal:()=>A});var A={settings:{accessToken:"ya29.c.xxx",destinations:[{operatingAccount:{accountId:"123-456-7890",accountType:"GOOGLE_ADS"},productDestinationId:"AW-CONVERSION-123"}]}},w={settings:{accessToken:"ya29.c.xxx",destinations:[{operatingAccount:{accountId:"123-456-7890",accountType:"GOOGLE_ADS"},productDestinationId:"AW-CONVERSION-123"},{operatingAccount:{accountId:"987654321",accountType:"GOOGLE_ANALYTICS_PROPERTY"},productDestinationId:"G-XXXXXXXXXX"}],eventSource:"WEB",batchSize:100,batchInterval:5e3,validateOnly:!1,consent:{adUserData:"CONSENT_GRANTED",adPersonalization:"CONSENT_GRANTED"},userData:{email:"user.id",phone:"data.phone",firstName:"data.firstName",lastName:"data.lastName"},userId:"user.id",clientId:"user.device",sessionAttributes:"context.sessionAttributes"},data:{map:{eventSource:{value:"WEB"}}}},T={settings:{accessToken:"ya29.c.xxx",destinations:[{operatingAccount:{accountId:"123456789",accountType:"GOOGLE_ANALYTICS_PROPERTY"},productDestinationId:"G-XXXXXXXXXX"}],eventSource:"WEB"}},z={settings:{accessToken:"ya29.c.xxx",destinations:[{operatingAccount:{accountId:"123-456-7890",accountType:"GOOGLE_ADS"},productDestinationId:"AW-CONVERSION-123"}],logLevel:"debug"}},k={};o(k,{schemas:()=>M});var C=require("@walkeros/core"),P=C.z.enum(["GOOGLE_ADS","DISPLAY_VIDEO_ADVERTISER","DISPLAY_VIDEO_PARTNER","GOOGLE_ANALYTICS_PROPERTY"]),_=C.z.enum(["WEB","APP","IN_STORE","PHONE","OTHER"]),x=C.z.enum(["CONSENT_GRANTED","CONSENT_DENIED"]),G=C.z.object({adUserData:x.describe("Consent for data collection and use").optional(),adPersonalization:x.describe("Consent for ad personalization").optional()}),R=C.z.object({accountId:C.z.string().min(1).describe('Account ID (e.g., "123-456-7890" for Google Ads)'),accountType:P.describe("Type of account")}),j=C.z.object({operatingAccount:R.describe("Operating account details"),productDestinationId:C.z.string().min(1).describe("Product-specific destination ID (conversion action or user list)")}),L=require("@walkeros/core"),V=L.z.object({accessToken:L.z.string().min(1).describe("OAuth 2.0 access token with datamanager scope (like ya29.c.xxx)"),destinations:L.z.array(j).min(1).max(10).describe("Array of destination accounts and conversion actions/user lists (max 10)"),eventSource:_.describe("Default event source if not specified per event (like WEB)").optional(),batchSize:L.z.number().int().min(1).max(2e3).describe("Maximum number of events to batch before sending (max 2000, like 100)").optional(),batchInterval:L.z.number().int().min(0).describe("Time in milliseconds to wait before auto-flushing batch (like 5000)").optional(),validateOnly:L.z.boolean().describe("If true, validate request without ingestion (testing mode)").optional(),url:L.z.string().url().describe("Override API endpoint for testing (like https://datamanager.googleapis.com/v1)").optional(),consent:G.describe("Request-level consent for all events").optional(),testEventCode:L.z.string().describe("Test event code for debugging (like TEST12345)").optional(),logLevel:L.z.enum(["debug","info","warn","error","none"]).describe("Log level for debugging (debug shows all API calls)").optional(),userData:L.z.record(L.z.string(),L.z.unknown()).describe("Guided helper: User data mapping for all events (like { email: 'user.id', phone: 'data.phone' })").optional(),userId:L.z.any().describe("Guided helper: First-party user ID for all events (like 'user.id')").optional(),clientId:L.z.any().describe("Guided helper: GA4 client ID for all events (like 'user.device')").optional(),sessionAttributes:L.z.any().describe("Guided helper: Privacy-safe attribution for all events (like 'context.sessionAttributes')").optional(),consentAdUserData:L.z.union([L.z.string(),L.z.boolean()]).describe("Consent mapping: Field name from event.consent (like 'marketing') or static boolean value").optional(),consentAdPersonalization:L.z.union([L.z.string(),L.z.boolean()]).describe("Consent mapping: Field name from event.consent (like 'targeting') or static boolean value").optional()}),X=require("@walkeros/core").z.object({}),q=require("@walkeros/core"),M={settings:(0,q.zodToSchema)(V),mapping:(0,q.zodToSchema)(X)},W={type:"datamanager",config:{},async init({config:e}){const t=function(e={}){const t=e.settings||{},{accessToken:n,destinations:a}=t;n||(0,r.throwError)("Config settings accessToken missing"),a&&0!==a.length||(0,r.throwError)("Config settings destinations missing or empty");const i={...t,accessToken:n,destinations:a};return{...e,settings:i}}(e);return t},push:async(e,{config:t,mapping:n,data:a,collector:i,env:o})=>await v(e,{config:t,mapping:n,data:a,collector:i,env:o})},U=W;//# sourceMappingURL=index.js.map
1
+ "use strict";var e,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.prototype.hasOwnProperty,a={};((e,n)=>{for(var r in n)t(e,r,{get:n[r],enumerable:!0})})(a,{DestinationDataManager:()=>w,default:()=>y,destinationDataManager:()=>b}),module.exports=(e=a,((e,a,s,o)=>{if(a&&"object"==typeof a||"function"==typeof a)for(let c of r(a))i.call(e,c)||c===s||t(e,c,{get:()=>a[c],enumerable:!(o=n(a,c))||o.enumerable});return e})(t({},"__esModule",{value:!0}),e));var s=require("@walkeros/core");var o=require("@walkeros/core"),c=require("@walkeros/core"),l=require("@walkeros/core"),g=require("@walkeros/server-core");async function d(e,t="given"){if(!(0,l.isString)(e)||!e)return"";let n=e.trim().toLowerCase();if("given"===t){const e=["mr.","mrs.","ms.","miss.","dr.","prof."];for(const t of e)if(n.startsWith(t)){n=n.substring(t.length).trim();break}}if("family"===t){const e=["jr.","sr.","iii","ii","iv","v"];for(const t of e){const e=` ${t}`;if(n.endsWith(e)){n=n.substring(0,n.length-e.length).trim();break}if(n.endsWith(t)){n=n.substring(0,n.length-t.length).trim();break}}}return(0,g.getHashServer)(n)}async function u(e){const t=[];if((0,c.isString)(e.email)&&e.email){const n=await async function(e){if(!(0,l.isString)(e)||!e)return"";let t=e.trim().toLowerCase();if(t.endsWith("@gmail.com")||t.endsWith("@googlemail.com")){const[e,n]=t.split("@");t=`${e.replace(/\./g,"")}@${n}`}return(0,g.getHashServer)(t)}(e.email);n&&t.push({emailAddress:n})}if((0,c.isString)(e.phone)&&e.phone){const n=await async function(e){if(!(0,l.isString)(e)||!e)return"";let t=e.trim();const n=t.startsWith("+");return t=t.replace(/\D/g,""),t=n||t.length>10?`+${t}`:`+1${t}`,(0,g.getHashServer)(t)}(e.phone);n&&t.push({phoneNumber:n})}if(e.firstName||e.lastName||e.regionCode||e.postalCode){const n={};(0,c.isString)(e.firstName)&&e.firstName&&(n.givenName=await d(e.firstName,"given")),(0,c.isString)(e.lastName)&&e.lastName&&(n.familyName=await d(e.lastName,"family")),(0,c.isString)(e.regionCode)&&e.regionCode&&(n.regionCode=e.regionCode.toUpperCase()),(0,c.isString)(e.postalCode)&&e.postalCode&&(n.postalCode=e.postalCode),Object.keys(n).length>0&&t.push({address:n})}if(0!==t.length)return{userIdentifiers:t.slice(0,10)}}async function f(e,t){const n={eventTimestamp:(r=e.timestamp,new Date(r).toISOString())};var r;const i=t||{};(0,c.isString)(i.transactionId)&&i.transactionId&&(n.transactionId=i.transactionId.substring(0,512)),(0,c.isString)(i.clientId)&&i.clientId&&(n.clientId=i.clientId.substring(0,255)),(0,c.isString)(i.userId)&&i.userId&&(n.userId=i.userId.substring(0,256));const a=await u(i);a&&(n.userData=a);const s=function(e){const t={};return(0,c.isString)(e.gclid)&&e.gclid&&(t.gclid=e.gclid),(0,c.isString)(e.gbraid)&&e.gbraid&&(t.gbraid=e.gbraid),(0,c.isString)(e.wbraid)&&e.wbraid&&(t.wbraid=e.wbraid),(0,c.isString)(e.sessionAttributes)&&e.sessionAttributes&&(t.sessionAttributes=e.sessionAttributes),Object.keys(t).length>0?t:void 0}(i);s&&(n.adIdentifiers=s),"number"==typeof i.conversionValue&&(n.conversionValue=i.conversionValue),(0,c.isString)(i.currency)&&i.currency&&(n.currency=i.currency.substring(0,3).toUpperCase()),i.cartData&&"object"==typeof i.cartData&&(n.cartData=i.cartData),(0,c.isString)(i.eventName)&&i.eventName&&(n.eventName=i.eventName.substring(0,40)),(0,c.isString)(i.eventSource)&&i.eventSource&&(n.eventSource=i.eventSource);const o={};if("boolean"==typeof i.adUserData&&(o.adUserData=i.adUserData?"CONSENT_GRANTED":"CONSENT_DENIED"),"boolean"==typeof i.adPersonalization&&(o.adPersonalization=i.adPersonalization?"CONSENT_GRANTED":"CONSENT_DENIED"),0===Object.keys(o).length){const t=function(e){if(!e)return;const t={};return(0,c.isDefined)(e.marketing)&&(t.adUserData=e.marketing?"CONSENT_GRANTED":"CONSENT_DENIED"),(0,c.isDefined)(e.personalization)&&(t.adPersonalization=e.personalization?"CONSENT_GRANTED":"CONSENT_DENIED"),Object.keys(t).length>0?t:void 0}(e.consent);t&&(n.consent=t)}else n.consent=o;return n}var p=require("google-auth-library"),h=["https://www.googleapis.com/auth/datamanager"],m=class extends Error{constructor(e,t){super(e),this.cause=t,this.name="DataManagerAuthError"}};var v=async function(e,{config:t,mapping:n,data:r,collector:i,env:a}){const{destinations:s,eventSource:c,validateOnly:l=!1,url:g="https://datamanager.googleapis.com/v1",consent:d,testEventCode:u,logLevel:p="none",userData:h,userId:v,clientId:w,sessionAttributes:b,consentAdUserData:y,consentAdPersonalization:S}=t.settings,E=function(e="none"){const t={debug:0,info:1,warn:2,error:3,none:4}[e];return{debug:(e,n)=>{t<=0&&console.log(`[DataManager] ${e}`,n||"")},info:(e,n)=>{t<=1&&console.log(`[DataManager] ${e}`,n||"")},warn:(e,n)=>{t<=2&&console.warn(`[DataManager] ${e}`,n||"")},error:(e,n)=>{t<=3&&console.error(`[DataManager] ${e}`,n||"")}}}(p),N=h?await(0,o.getMappingValue)(e,{map:h}):{},D=v?await(0,o.getMappingValue)(e,v):void 0,C=w?await(0,o.getMappingValue)(e,w):void 0,I=b?await(0,o.getMappingValue)(e,b):void 0,O="boolean"==typeof y?y:"string"==typeof y&&e.consent?e.consent[y]:void 0,A="boolean"==typeof S?S:"string"==typeof S&&e.consent?e.consent[S]:void 0,k={};(0,o.isObject)(N)&&Object.assign(k,N),void 0!==D&&(k.userId=D),void 0!==C&&(k.clientId=C),void 0!==I&&(k.sessionAttributes=I),void 0!==O&&(k.adUserData=O),void 0!==A&&(k.adPersonalization=A);const P=t.data?await(0,o.getMappingValue)(e,t.data):{},T=(0,o.isObject)(r)?r:{},j={...k,...(0,o.isObject)(P)?P:{},...T},M=await f(e,j);if(E.debug("Processing event",{name:e.name,id:e.id,timestamp:e.timestamp}),!M.eventSource&&c&&(M.eventSource=c),!M.consent&&d&&(M.consent=d),!s||0===s.length)throw new Error("Destinations are required");const $={events:[M],destinations:s};d&&($.consent=d),l&&($.validateOnly=!0),u&&($.testEventCode=u);const q=null==a?void 0:a.authClient;if(!q)throw new Error("Auth client not initialized. Ensure init() was called successfully.");let _;try{_=await async function(e){try{const t=await e.getAccessToken();if(!t.token)throw new m("Auth client returned empty token");return t.token}catch(e){throw new m("Failed to obtain access token",e instanceof Error?e:void 0)}}(q)}catch(e){throw E.error("Authentication failed",{error:e}),e}const z=(null==a?void 0:a.fetch)||fetch,V=`${g}/events:ingest`;E.debug("Sending to Data Manager API",{endpoint:V,eventCount:$.events.length,destinations:s.length,validateOnly:l});const G=await z(V,{method:"POST",headers:{Authorization:`Bearer ${_}`,"Content-Type":"application/json"},body:JSON.stringify($)});if(!G.ok){const e=await G.text();throw E.error("API request failed",{status:G.status,error:e}),new Error(`Data Manager API error (${G.status}): ${e}`)}const U=await G.json();if(E.debug("API response",{status:G.status,requestId:U.requestId}),U.validationErrors&&U.validationErrors.length>0)throw E.error("Validation errors",{errors:U.validationErrors}),new Error(`Validation errors: ${JSON.stringify(U.validationErrors)}`);E.info("Event processed successfully",{requestId:U.requestId})},w={},b={type:"datamanager",config:{},async init({config:e,env:t}){const n=function(e={}){const t=e.settings||{},{destinations:n}=t;n&&0!==n.length||(0,s.throwError)("Config settings destinations missing or empty");const r={...t,destinations:n};return{...e,settings:r}}(e);if(!n.settings)throw new Error("Settings required for Data Manager destination");if(!n.settings.destinations||0===n.settings.destinations.length)throw new Error("At least one destination required in settings");try{const e=await async function(e){const{credentials:t,keyFilename:n,scopes:r=h}=e;try{if(t){const e=new p.GoogleAuth({credentials:t,scopes:r});return await e.getClient()}if(n){const e=new p.GoogleAuth({keyFilename:n,scopes:r});return await e.getClient()}const e=new p.GoogleAuth({scopes:r});return await e.getClient()}catch(e){throw new m("Failed to create auth client. Check credentials configuration or ensure GOOGLE_APPLICATION_CREDENTIALS is set.",e instanceof Error?e:void 0)}}(n.settings);return{...n,env:{...t,authClient:e}}}catch(e){throw new Error(`Data Manager authentication failed: ${e instanceof Error?e.message:"Unknown error"}`)}},push:async(e,{config:t,mapping:n,data:r,collector:i,env:a})=>await v(e,{config:t,mapping:n,data:r,collector:i,env:a})},y=b;//# sourceMappingURL=index.js.map