@walkeros/server-destination-criteo 4.7.0-next-1790245733116 → 4.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,24 +1,38 @@
1
1
  # @walkeros/server-destination-criteo
2
2
 
3
- ## 4.7.0-next-1790245733116
3
+ ## 4.7.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 74821ed: New `ip` and `userAgent` settings on the Meta, Pinterest, Snapchat,
8
+ TikTok, Reddit, X (Twitter), Bing, Criteo and Google Data Manager server
9
+ destinations. Requests now send the client IP and user agent in each vendor's
10
+ field by default, read from `ingest.ip`/`ingest.userAgent` or
11
+ `user.ip`/`user.userAgent`. A mapped value still wins; set either setting to
12
+ `false` to opt out.
4
13
 
5
14
  ### Patch Changes
6
15
 
7
- - Updated dependencies [57788bc]
16
+ - Updated dependencies [74821ed]
8
17
  - Updated dependencies [06b498a]
9
- - Updated dependencies [f5a1cfd]
10
- - Updated dependencies [ef02916]
18
+ - Updated dependencies [74821ed]
19
+ - Updated dependencies [64b06de]
20
+ - Updated dependencies [4b4937f]
21
+ - Updated dependencies [74821ed]
22
+ - Updated dependencies [74821ed]
23
+ - Updated dependencies [74821ed]
11
24
  - Updated dependencies [06b498a]
12
- - Updated dependencies [ef02916]
13
- - Updated dependencies [2aebc53]
14
- - Updated dependencies [f5a1cfd]
15
- - Updated dependencies [f5a1cfd]
16
- - Updated dependencies [2aebc53]
17
- - Updated dependencies [8f8aea6]
18
- - Updated dependencies [2aebc53]
19
- - Updated dependencies [2aebc53]
20
- - @walkeros/core@4.7.0-next-1790245733116
21
- - @walkeros/server-core@4.7.0-next-1790245733116
25
+ - Updated dependencies [74821ed]
26
+ - Updated dependencies [74821ed]
27
+ - Updated dependencies [74821ed]
28
+ - Updated dependencies [74821ed]
29
+ - Updated dependencies [74821ed]
30
+ - Updated dependencies [e860006]
31
+ - Updated dependencies [74821ed]
32
+ - Updated dependencies [74821ed]
33
+ - Updated dependencies [4f89234]
34
+ - @walkeros/core@4.7.0
35
+ - @walkeros/server-core@4.7.0
22
36
 
23
37
  ## 4.6.1
24
38
 
package/dist/dev.d.mts CHANGED
@@ -32,6 +32,8 @@ declare const SettingsSchema: z.ZodObject<{
32
32
  language: z.ZodOptional<z.ZodString>;
33
33
  url: z.ZodOptional<z.ZodString>;
34
34
  user_data: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
35
+ ip: z.ZodOptional<z.ZodUnion<readonly [z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, z.ZodLiteral<false>]>>;
36
+ userAgent: z.ZodOptional<z.ZodUnion<readonly [z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, z.ZodLiteral<false>]>>;
35
37
  }, z.core.$strip>;
36
38
  type Settings = z.infer<typeof SettingsSchema>;
37
39
 
package/dist/dev.d.ts CHANGED
@@ -32,6 +32,8 @@ declare const SettingsSchema: z.ZodObject<{
32
32
  language: z.ZodOptional<z.ZodString>;
33
33
  url: z.ZodOptional<z.ZodString>;
34
34
  user_data: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
35
+ ip: z.ZodOptional<z.ZodUnion<readonly [z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, z.ZodLiteral<false>]>>;
36
+ userAgent: z.ZodOptional<z.ZodUnion<readonly [z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, z.ZodLiteral<false>]>>;
35
37
  }, z.core.$strip>;
36
38
  type Settings = z.infer<typeof SettingsSchema>;
37
39
 
package/dist/dev.js CHANGED
@@ -1 +1 @@
1
- "use strict";var e,t=Object.defineProperty,i=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,a=Object.prototype.hasOwnProperty,o=(e,i)=>{for(var r in i)t(e,r,{get:i[r],enumerable:!0})},n={};o(n,{examples:()=>y,schemas:()=>s}),module.exports=(e=n,((e,o,n,s)=>{if(o&&"object"==typeof o||"function"==typeof o)for(let p of r(o))a.call(e,p)||p===n||t(e,p,{get:()=>o[p],enumerable:!(s=i(o,p))||s.enumerable});return e})(t({},"__esModule",{value:!0}),e));var s={};o(s,{CriteoEventNameSchema:()=>l,MappingSchema:()=>m,SettingsSchema:()=>c,mapping:()=>g,settings:()=>v});var p=require("@walkeros/core/dev"),d=require("@walkeros/core/dev"),c=d.z.object({partnerId:d.z.string().min(1).describe("Criteo Partner ID (numeric string, provided by Criteo)"),callerId:d.z.string().min(1).describe("Caller ID for user mapping (provided by Criteo)"),siteType:d.z.enum(["d","m","t"]).describe("Site type: d (desktop), m (mobile web), t (tablet)").optional(),country:d.z.string().length(2).describe("ISO 3166-1 alpha-2 country code").optional(),language:d.z.string().length(2).describe("2-letter language code").optional(),url:d.z.string().url().describe("Custom Events API endpoint (default https://widget.criteo.com/m/event?version=s2s_v0)").optional(),user_data:d.z.record(d.z.string(),d.z.string()).describe("Mapping for identity fields (like { email: 'user.email', mapped_user_id: 'user.id' })").optional()}),m=require("@walkeros/core/dev").z.object({}),u=require("@walkeros/core/dev"),l=u.z.union([u.z.enum(["viewHome","viewPage","viewItem","viewList","addToCart","viewBasket","beginCheckout","trackTransaction","addPaymentInfo","login"]),u.z.string()]),v=(0,p.zodToSchema)(c),g=(0,p.zodToSchema)(m),y={};o(y,{env:()=>h,step:()=>_});var h={};o(h,{push:()=>w,simulation:()=>b});var w={sendServer:async()=>({ok:!0,data:"OK"})},b=["sendServer"],_={};o(_,{addToCart:()=>C,pageView:()=>T,purchase:()=>S,viewItem:()=>I});var f=require("@walkeros/core"),k="https://widget.criteo.com/m/event?version=s2s_v0",S={title:"Purchase",description:"A completed order is posted to the Criteo Events API as a trackTransaction event with items.",in:(0,f.getEvent)("order complete",{timestamp:17000009e5,data:{id:"ORD-300",total:249.99,currency:"EUR"},nested:[{entity:"product",data:{id:"SKU-A1",name:"Widget Pro",price:124.99,quantity:2}}],user:{id:"user-123",device:"device-456"},source:{type:"browser",platform:"web",url:"https://shop.example.com/checkout/complete",referrer:"https://shop.example.com/cart"}}),mapping:{name:"trackTransaction",data:{map:{id:"data.id",item:{loop:["nested",{condition:e=>(0,f.isObject)(e)&&"product"===e.entity,map:{id:"data.id",price:"data.price",quantity:{key:"data.quantity",value:1}}}]}}}},out:[["sendServer",k,JSON.stringify({version:"walkeros_criteo_1.0.0",site_type:"d",account:"PARTNER_ID",id:{mapping_key:"CALLER_ID"},events:[{event:"trackTransaction",timestamp:"2023-11-14T22:28:20.000Z",id:"ORD-300",item:[{id:"SKU-A1",price:124.99,quantity:2}]}],full_url:"https://shop.example.com/checkout/complete",previous_url:"https://shop.example.com/cart"})]]},C={title:"Add to cart",description:"A product add becomes a Criteo addToCart event with the item id, price, and quantity.",in:(0,f.getEvent)("product add",{timestamp:1700000901e3,data:{id:"SKU-B2",name:"Running Shoes",price:89.99},nested:[{entity:"product",data:{id:"SKU-B2",name:"Running Shoes",price:89.99,quantity:1}}],source:{type:"browser",platform:"web",url:"https://shop.example.com/products/running-shoes"}}),mapping:{name:"addToCart",data:{map:{item:{loop:["nested",{condition:e=>(0,f.isObject)(e)&&"product"===e.entity,map:{id:"data.id",price:"data.price",quantity:{key:"data.quantity",value:1}}}]}}}},out:[["sendServer",k,JSON.stringify({version:"walkeros_criteo_1.0.0",site_type:"d",account:"PARTNER_ID",id:{mapping_key:"CALLER_ID"},events:[{event:"addToCart",timestamp:"2023-11-14T22:28:21.000Z",item:[{id:"SKU-B2",price:89.99,quantity:1}]}],full_url:"https://shop.example.com/products/running-shoes"})]]},I={title:"View item",description:"A product view becomes a Criteo viewItem event with the viewed product id.",in:(0,f.getEvent)("product view",{timestamp:1700000902e3,data:{id:"SKU-C3",name:"Coffee Maker"},nested:[{entity:"product",data:{id:"SKU-C3"}}],source:{type:"browser",platform:"web",url:"https://shop.example.com/products/coffee-maker"}}),mapping:{name:"viewItem",data:{map:{item:{loop:["nested",{condition:e=>(0,f.isObject)(e)&&"product"===e.entity,map:{id:"data.id"}}]}}}},out:[["sendServer",k,JSON.stringify({version:"walkeros_criteo_1.0.0",site_type:"d",account:"PARTNER_ID",id:{mapping_key:"CALLER_ID"},events:[{event:"viewItem",timestamp:"2023-11-14T22:28:22.000Z",item:[{id:"SKU-C3"}]}],full_url:"https://shop.example.com/products/coffee-maker"})]]},T={title:"Page view",description:"A page view becomes a Criteo viewHome event used for home page impression tracking.",in:(0,f.getEvent)("page view",{timestamp:1700000903e3,source:{type:"browser",platform:"web",url:"https://example.com/"}}),mapping:{name:"viewHome"},out:[["sendServer",k,JSON.stringify({version:"walkeros_criteo_1.0.0",site_type:"d",account:"PARTNER_ID",id:{mapping_key:"CALLER_ID"},events:[{event:"viewHome",timestamp:"2023-11-14T22:28:23.000Z"}],full_url:"https://example.com/"})]]};//# sourceMappingURL=dev.js.map
1
+ "use strict";var e,t=Object.defineProperty,i=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,a=Object.prototype.hasOwnProperty,o=(e,i)=>{for(var r in i)t(e,r,{get:i[r],enumerable:!0})},n={};o(n,{examples:()=>w,schemas:()=>s}),module.exports=(e=n,((e,o,n,s)=>{if(o&&"object"==typeof o||"function"==typeof o)for(let p of r(o))a.call(e,p)||p===n||t(e,p,{get:()=>o[p],enumerable:!(s=i(o,p))||s.enumerable});return e})(t({},"__esModule",{value:!0}),e));var s={};o(s,{CriteoEventNameSchema:()=>v,MappingSchema:()=>u,SettingsSchema:()=>m,mapping:()=>h,settings:()=>g});var p=require("@walkeros/core/dev"),d=require("@walkeros/core/dev"),c=d.z.union([d.schemas.MappingSchemas.ValueSchema,d.z.literal(!1)]),m=d.z.object({partnerId:d.z.string().min(1).describe("Criteo Partner ID (numeric string, provided by Criteo)"),callerId:d.z.string().min(1).describe("Caller ID for user mapping (provided by Criteo)"),siteType:d.z.enum(["d","m","t"]).describe("Site type: d (desktop), m (mobile web), t (tablet)").optional(),country:d.z.string().length(2).describe("ISO 3166-1 alpha-2 country code").optional(),language:d.z.string().length(2).describe("2-letter language code").optional(),url:d.z.string().url().describe("Custom Events API endpoint (default https://widget.criteo.com/m/event?version=s2s_v0)").optional(),user_data:d.z.record(d.z.string(),d.z.string()).describe("Mapping for identity fields (like { email: 'user.email', mapped_user_id: 'user.id' })").optional(),ip:c.describe('Client IP, sent as ip. Resolves against { ingest, event }. Default: ["ingest.ip", "event.user.ip"]. false switches it off. A mapped user_data.ip wins.').optional(),userAgent:c.describe('Client user agent, sent as useragent. Resolves against { ingest, event }. Default: ["ingest.userAgent", "event.user.userAgent"]. false switches it off. A mapped user_data.useragent wins.').optional()}),u=require("@walkeros/core/dev").z.object({}),l=require("@walkeros/core/dev"),v=l.z.union([l.z.enum(["viewHome","viewPage","viewItem","viewList","addToCart","viewBasket","beginCheckout","trackTransaction","addPaymentInfo","login"]),l.z.string()]),g=(0,p.zodToSchema)(m),h=(0,p.zodToSchema)(u),w={};o(w,{env:()=>y,step:()=>_});var y={};o(y,{push:()=>f,simulation:()=>b});var f={sendServer:async()=>({ok:!0,data:"OK"})},b=["sendServer"],_={};o(_,{addToCart:()=>A,pageView:()=>T,purchase:()=>C,viewItem:()=>I});var k=require("@walkeros/core"),S="https://widget.criteo.com/m/event?version=s2s_v0",C={title:"Purchase",description:"A completed order is posted to the Criteo Events API as a trackTransaction event with items.",in:(0,k.getEvent)("order complete",{timestamp:17000009e5,data:{id:"ORD-300",total:249.99,currency:"EUR"},nested:[{entity:"product",data:{id:"SKU-A1",name:"Widget Pro",price:124.99,quantity:2}}],user:{id:"user-123",device:"device-456"},source:{type:"browser",platform:"web",url:"https://shop.example.com/checkout/complete",referrer:"https://shop.example.com/cart"}}),mapping:{name:"trackTransaction",data:{map:{id:"data.id",item:{loop:["nested",{condition:e=>(0,k.isObject)(e)&&"product"===e.entity,map:{id:"data.id",price:"data.price",quantity:{key:"data.quantity",value:1}}}]}}}},out:[["sendServer",S,JSON.stringify({version:"walkeros_criteo_1.0.0",site_type:"d",account:"PARTNER_ID",id:{mapping_key:"CALLER_ID"},events:[{event:"trackTransaction",timestamp:"2023-11-14T22:28:20.000Z",id:"ORD-300",item:[{id:"SKU-A1",price:124.99,quantity:2}]}],full_url:"https://shop.example.com/checkout/complete",previous_url:"https://shop.example.com/cart"})]]},A={title:"Add to cart",description:"A product add becomes a Criteo addToCart event with the item id, price, and quantity.",in:(0,k.getEvent)("product add",{timestamp:1700000901e3,data:{id:"SKU-B2",name:"Running Shoes",price:89.99},nested:[{entity:"product",data:{id:"SKU-B2",name:"Running Shoes",price:89.99,quantity:1}}],source:{type:"browser",platform:"web",url:"https://shop.example.com/products/running-shoes"}}),mapping:{name:"addToCart",data:{map:{item:{loop:["nested",{condition:e=>(0,k.isObject)(e)&&"product"===e.entity,map:{id:"data.id",price:"data.price",quantity:{key:"data.quantity",value:1}}}]}}}},out:[["sendServer",S,JSON.stringify({version:"walkeros_criteo_1.0.0",site_type:"d",account:"PARTNER_ID",id:{mapping_key:"CALLER_ID"},events:[{event:"addToCart",timestamp:"2023-11-14T22:28:21.000Z",item:[{id:"SKU-B2",price:89.99,quantity:1}]}],full_url:"https://shop.example.com/products/running-shoes"})]]},I={title:"View item",description:"A product view becomes a Criteo viewItem event with the viewed product id.",in:(0,k.getEvent)("product view",{timestamp:1700000902e3,data:{id:"SKU-C3",name:"Coffee Maker"},nested:[{entity:"product",data:{id:"SKU-C3"}}],source:{type:"browser",platform:"web",url:"https://shop.example.com/products/coffee-maker"}}),mapping:{name:"viewItem",data:{map:{item:{loop:["nested",{condition:e=>(0,k.isObject)(e)&&"product"===e.entity,map:{id:"data.id"}}]}}}},out:[["sendServer",S,JSON.stringify({version:"walkeros_criteo_1.0.0",site_type:"d",account:"PARTNER_ID",id:{mapping_key:"CALLER_ID"},events:[{event:"viewItem",timestamp:"2023-11-14T22:28:22.000Z",item:[{id:"SKU-C3"}]}],full_url:"https://shop.example.com/products/coffee-maker"})]]},T={title:"Page view",description:"A page view becomes a Criteo viewHome event used for home page impression tracking.",in:(0,k.getEvent)("page view",{timestamp:1700000903e3,source:{type:"browser",platform:"web",url:"https://example.com/"}}),mapping:{name:"viewHome"},out:[["sendServer",S,JSON.stringify({version:"walkeros_criteo_1.0.0",site_type:"d",account:"PARTNER_ID",id:{mapping_key:"CALLER_ID"},events:[{event:"viewHome",timestamp:"2023-11-14T22:28:23.000Z"}],full_url:"https://example.com/"})]]};//# sourceMappingURL=dev.js.map
package/dist/dev.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/dev.ts","../src/schemas/index.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/schemas/primitives.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","import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nexport * from './primitives';\n\nexport { SettingsSchema, type Settings } from './settings';\nexport { MappingSchema, type Mapping } from './mapping';\n\n// JSON Schema\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\n","import { z } from '@walkeros/core/dev';\n\nexport const SettingsSchema = z.object({\n partnerId: z\n .string()\n .min(1)\n .describe('Criteo Partner ID (numeric string, provided by Criteo)'),\n callerId: z\n .string()\n .min(1)\n .describe('Caller ID for user mapping (provided by Criteo)'),\n siteType: z\n .enum(['d', 'm', 't'])\n .describe('Site type: d (desktop), m (mobile web), t (tablet)')\n .optional(),\n country: z\n .string()\n .length(2)\n .describe('ISO 3166-1 alpha-2 country code')\n .optional(),\n language: z.string().length(2).describe('2-letter language code').optional(),\n url: z\n .string()\n .url()\n .describe(\n 'Custom Events API endpoint (default https://widget.criteo.com/m/event?version=s2s_v0)',\n )\n .optional(),\n user_data: z\n .record(z.string(), z.string())\n .describe(\n \"Mapping for identity fields (like { email: 'user.email', mapped_user_id: 'user.id' })\",\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Criteo Events API Mapping Schema\n * Criteo has no event-level mapping configuration beyond name + data\n */\nexport const MappingSchema = z.object({});\n\n/**\n * Type inference from MappingSchema\n */\nexport type Mapping = z.infer<typeof MappingSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Standard Criteo Events API event names.\n * https://guides.criteotilt.com/events-api/\n */\nexport const CriteoEventNameSchema = z.union([\n z.enum([\n 'viewHome',\n 'viewPage',\n 'viewItem',\n 'viewList',\n 'addToCart',\n 'viewBasket',\n 'beginCheckout',\n 'trackTransaction',\n 'addPaymentInfo',\n 'login',\n ]),\n z.string(), // Allow custom event names\n]);\n","export * as env from './env';\nexport * as step from './step';\n","import type { SendDataValue, SendResponse } from '@walkeros/core';\nimport type { SendServerOptions } from '@walkeros/server-core';\nimport type { Env } from '../types';\n\n/**\n * Example environment configurations for Criteo Events API destination.\n *\n * These environments provide standardized mock structures for testing\n * and development without requiring actual HTTP requests.\n */\n\ntype MockSendServer = (\n url: string,\n data?: SendDataValue,\n options?: SendServerOptions,\n) => Promise<SendResponse>;\n\nconst mockSendServer: MockSendServer = async () => ({\n ok: true,\n data: 'OK',\n});\n\n/**\n * Standard mock environment for push operations.\n *\n * Use this for testing Criteo Events API pushes without making\n * actual HTTP requests to Criteo's servers.\n */\nexport const push: Env = {\n sendServer: mockSendServer,\n};\n\nexport const simulation = ['sendServer'];\n","import type { Flow } from '@walkeros/core';\nimport { getEvent, isObject } from '@walkeros/core';\n\n/**\n * Criteo Events API step examples.\n *\n * At push time, the destination calls `env.sendServer(url, body)` where\n * `url` is the configured Criteo endpoint (default:\n * `https://widget.criteo.com/m/event?version=s2s_v0`) and `body` is the\n * JSON-stringified request payload.\n *\n * Test fixture pins `partnerId = 'PARTNER_ID'` and `callerId = 'CALLER_ID'`,\n * so every call targets the default URL above.\n *\n * Body is emitted with keys in the order the destination assembles them:\n * 1. version\n * 2. site_type\n * 3. account\n * 4. id (identity block)\n * 5. events (always a single-element array)\n * 6. full_url (only when event.source.url is set)\n * 7. previous_url (only when event.source.referrer is set)\n */\nconst ENDPOINT = 'https://widget.criteo.com/m/event?version=s2s_v0';\n\nexport const purchase: Flow.StepExample = {\n title: 'Purchase',\n description:\n 'A completed order is posted to the Criteo Events API as a trackTransaction event with items.',\n in: getEvent('order complete', {\n timestamp: 1700000900000,\n data: { id: 'ORD-300', total: 249.99, currency: 'EUR' },\n nested: [\n {\n entity: 'product',\n data: { id: 'SKU-A1', name: 'Widget Pro', price: 124.99, quantity: 2 },\n },\n ],\n user: { id: 'user-123', device: 'device-456' },\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://shop.example.com/checkout/complete',\n referrer: 'https://shop.example.com/cart',\n },\n }),\n mapping: {\n name: 'trackTransaction',\n data: {\n map: {\n id: 'data.id',\n item: {\n loop: [\n 'nested',\n {\n condition: (entity: unknown) =>\n isObject(entity) && entity.entity === 'product',\n map: {\n id: 'data.id',\n price: 'data.price',\n quantity: { key: 'data.quantity', value: 1 },\n },\n },\n ],\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n version: 'walkeros_criteo_1.0.0',\n site_type: 'd',\n account: 'PARTNER_ID',\n id: {\n mapping_key: 'CALLER_ID',\n },\n events: [\n {\n event: 'trackTransaction',\n timestamp: '2023-11-14T22:28:20.000Z',\n id: 'ORD-300',\n item: [\n {\n id: 'SKU-A1',\n price: 124.99,\n quantity: 2,\n },\n ],\n },\n ],\n full_url: 'https://shop.example.com/checkout/complete',\n previous_url: 'https://shop.example.com/cart',\n }),\n ],\n ],\n};\n\nexport const addToCart: Flow.StepExample = {\n title: 'Add to cart',\n description:\n 'A product add becomes a Criteo addToCart event with the item id, price, and quantity.',\n in: getEvent('product add', {\n timestamp: 1700000901000,\n data: {\n id: 'SKU-B2',\n name: 'Running Shoes',\n price: 89.99,\n },\n nested: [\n {\n entity: 'product',\n data: {\n id: 'SKU-B2',\n name: 'Running Shoes',\n price: 89.99,\n quantity: 1,\n },\n },\n ],\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://shop.example.com/products/running-shoes',\n },\n }),\n mapping: {\n name: 'addToCart',\n data: {\n map: {\n item: {\n loop: [\n 'nested',\n {\n condition: (entity: unknown) =>\n isObject(entity) && entity.entity === 'product',\n map: {\n id: 'data.id',\n price: 'data.price',\n quantity: { key: 'data.quantity', value: 1 },\n },\n },\n ],\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n version: 'walkeros_criteo_1.0.0',\n site_type: 'd',\n account: 'PARTNER_ID',\n id: {\n mapping_key: 'CALLER_ID',\n },\n events: [\n {\n event: 'addToCart',\n timestamp: '2023-11-14T22:28:21.000Z',\n item: [\n {\n id: 'SKU-B2',\n price: 89.99,\n quantity: 1,\n },\n ],\n },\n ],\n full_url: 'https://shop.example.com/products/running-shoes',\n }),\n ],\n ],\n};\n\nexport const viewItem: Flow.StepExample = {\n title: 'View item',\n description:\n 'A product view becomes a Criteo viewItem event with the viewed product id.',\n in: getEvent('product view', {\n timestamp: 1700000902000,\n data: { id: 'SKU-C3', name: 'Coffee Maker' },\n nested: [\n {\n entity: 'product',\n data: { id: 'SKU-C3' },\n },\n ],\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://shop.example.com/products/coffee-maker',\n },\n }),\n mapping: {\n name: 'viewItem',\n data: {\n map: {\n item: {\n loop: [\n 'nested',\n {\n condition: (entity: unknown) =>\n isObject(entity) && entity.entity === 'product',\n map: {\n id: 'data.id',\n },\n },\n ],\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n version: 'walkeros_criteo_1.0.0',\n site_type: 'd',\n account: 'PARTNER_ID',\n id: {\n mapping_key: 'CALLER_ID',\n },\n events: [\n {\n event: 'viewItem',\n timestamp: '2023-11-14T22:28:22.000Z',\n item: [\n {\n id: 'SKU-C3',\n },\n ],\n },\n ],\n full_url: 'https://shop.example.com/products/coffee-maker',\n }),\n ],\n ],\n};\n\nexport const pageView: Flow.StepExample = {\n title: 'Page view',\n description:\n 'A page view becomes a Criteo viewHome event used for home page impression tracking.',\n in: getEvent('page view', {\n timestamp: 1700000903000,\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://example.com/',\n },\n }),\n mapping: {\n name: 'viewHome',\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n version: 'walkeros_criteo_1.0.0',\n site_type: 'd',\n account: 'PARTNER_ID',\n id: {\n mapping_key: 'CALLER_ID',\n },\n events: [\n {\n event: 'viewHome',\n timestamp: '2023-11-14T22:28:23.000Z',\n },\n ],\n full_url: 'https://example.com/',\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/index.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/schemas/primitives.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","import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nexport * from './primitives';\n\nexport { SettingsSchema, type Settings } from './settings';\nexport { MappingSchema, type Mapping } from './mapping';\n\n// JSON Schema\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\n","import { schemas, z } from '@walkeros/core/dev';\n\nconst InputSchema = z.union([\n schemas.MappingSchemas.ValueSchema,\n z.literal(false),\n]);\n\nexport const SettingsSchema = z.object({\n partnerId: z\n .string()\n .min(1)\n .describe('Criteo Partner ID (numeric string, provided by Criteo)'),\n callerId: z\n .string()\n .min(1)\n .describe('Caller ID for user mapping (provided by Criteo)'),\n siteType: z\n .enum(['d', 'm', 't'])\n .describe('Site type: d (desktop), m (mobile web), t (tablet)')\n .optional(),\n country: z\n .string()\n .length(2)\n .describe('ISO 3166-1 alpha-2 country code')\n .optional(),\n language: z.string().length(2).describe('2-letter language code').optional(),\n url: z\n .string()\n .url()\n .describe(\n 'Custom Events API endpoint (default https://widget.criteo.com/m/event?version=s2s_v0)',\n )\n .optional(),\n user_data: z\n .record(z.string(), z.string())\n .describe(\n \"Mapping for identity fields (like { email: 'user.email', mapped_user_id: 'user.id' })\",\n )\n .optional(),\n ip: InputSchema.describe(\n 'Client IP, sent as ip. Resolves against { ingest, event }. Default: [\"ingest.ip\", \"event.user.ip\"]. false switches it off. A mapped user_data.ip wins.',\n ).optional(),\n userAgent: InputSchema.describe(\n 'Client user agent, sent as useragent. Resolves against { ingest, event }. Default: [\"ingest.userAgent\", \"event.user.userAgent\"]. false switches it off. A mapped user_data.useragent wins.',\n ).optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Criteo Events API Mapping Schema\n * Criteo has no event-level mapping configuration beyond name + data\n */\nexport const MappingSchema = z.object({});\n\n/**\n * Type inference from MappingSchema\n */\nexport type Mapping = z.infer<typeof MappingSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Standard Criteo Events API event names.\n * https://guides.criteotilt.com/events-api/\n */\nexport const CriteoEventNameSchema = z.union([\n z.enum([\n 'viewHome',\n 'viewPage',\n 'viewItem',\n 'viewList',\n 'addToCart',\n 'viewBasket',\n 'beginCheckout',\n 'trackTransaction',\n 'addPaymentInfo',\n 'login',\n ]),\n z.string(), // Allow custom event names\n]);\n","export * as env from './env';\nexport * as step from './step';\n","import type { SendDataValue, SendResponse } from '@walkeros/core';\nimport type { SendServerOptions } from '@walkeros/server-core';\nimport type { Env } from '../types';\n\n/**\n * Example environment configurations for Criteo Events API destination.\n *\n * These environments provide standardized mock structures for testing\n * and development without requiring actual HTTP requests.\n */\n\ntype MockSendServer = (\n url: string,\n data?: SendDataValue,\n options?: SendServerOptions,\n) => Promise<SendResponse>;\n\nconst mockSendServer: MockSendServer = async () => ({\n ok: true,\n data: 'OK',\n});\n\n/**\n * Standard mock environment for push operations.\n *\n * Use this for testing Criteo Events API pushes without making\n * actual HTTP requests to Criteo's servers.\n */\nexport const push: Env = {\n sendServer: mockSendServer,\n};\n\nexport const simulation = ['sendServer'];\n","import type { Flow } from '@walkeros/core';\nimport { getEvent, isObject } from '@walkeros/core';\n\n/**\n * Criteo Events API step examples.\n *\n * At push time, the destination calls `env.sendServer(url, body)` where\n * `url` is the configured Criteo endpoint (default:\n * `https://widget.criteo.com/m/event?version=s2s_v0`) and `body` is the\n * JSON-stringified request payload.\n *\n * Test fixture pins `partnerId = 'PARTNER_ID'` and `callerId = 'CALLER_ID'`,\n * so every call targets the default URL above.\n *\n * Body is emitted with keys in the order the destination assembles them:\n * 1. version\n * 2. site_type\n * 3. account\n * 4. id (identity block)\n * 5. events (always a single-element array)\n * 6. full_url (only when event.source.url is set)\n * 7. previous_url (only when event.source.referrer is set)\n */\nconst ENDPOINT = 'https://widget.criteo.com/m/event?version=s2s_v0';\n\nexport const purchase: Flow.StepExample = {\n title: 'Purchase',\n description:\n 'A completed order is posted to the Criteo Events API as a trackTransaction event with items.',\n in: getEvent('order complete', {\n timestamp: 1700000900000,\n data: { id: 'ORD-300', total: 249.99, currency: 'EUR' },\n nested: [\n {\n entity: 'product',\n data: { id: 'SKU-A1', name: 'Widget Pro', price: 124.99, quantity: 2 },\n },\n ],\n user: { id: 'user-123', device: 'device-456' },\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://shop.example.com/checkout/complete',\n referrer: 'https://shop.example.com/cart',\n },\n }),\n mapping: {\n name: 'trackTransaction',\n data: {\n map: {\n id: 'data.id',\n item: {\n loop: [\n 'nested',\n {\n condition: (entity: unknown) =>\n isObject(entity) && entity.entity === 'product',\n map: {\n id: 'data.id',\n price: 'data.price',\n quantity: { key: 'data.quantity', value: 1 },\n },\n },\n ],\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n version: 'walkeros_criteo_1.0.0',\n site_type: 'd',\n account: 'PARTNER_ID',\n id: {\n mapping_key: 'CALLER_ID',\n },\n events: [\n {\n event: 'trackTransaction',\n timestamp: '2023-11-14T22:28:20.000Z',\n id: 'ORD-300',\n item: [\n {\n id: 'SKU-A1',\n price: 124.99,\n quantity: 2,\n },\n ],\n },\n ],\n full_url: 'https://shop.example.com/checkout/complete',\n previous_url: 'https://shop.example.com/cart',\n }),\n ],\n ],\n};\n\nexport const addToCart: Flow.StepExample = {\n title: 'Add to cart',\n description:\n 'A product add becomes a Criteo addToCart event with the item id, price, and quantity.',\n in: getEvent('product add', {\n timestamp: 1700000901000,\n data: {\n id: 'SKU-B2',\n name: 'Running Shoes',\n price: 89.99,\n },\n nested: [\n {\n entity: 'product',\n data: {\n id: 'SKU-B2',\n name: 'Running Shoes',\n price: 89.99,\n quantity: 1,\n },\n },\n ],\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://shop.example.com/products/running-shoes',\n },\n }),\n mapping: {\n name: 'addToCart',\n data: {\n map: {\n item: {\n loop: [\n 'nested',\n {\n condition: (entity: unknown) =>\n isObject(entity) && entity.entity === 'product',\n map: {\n id: 'data.id',\n price: 'data.price',\n quantity: { key: 'data.quantity', value: 1 },\n },\n },\n ],\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n version: 'walkeros_criteo_1.0.0',\n site_type: 'd',\n account: 'PARTNER_ID',\n id: {\n mapping_key: 'CALLER_ID',\n },\n events: [\n {\n event: 'addToCart',\n timestamp: '2023-11-14T22:28:21.000Z',\n item: [\n {\n id: 'SKU-B2',\n price: 89.99,\n quantity: 1,\n },\n ],\n },\n ],\n full_url: 'https://shop.example.com/products/running-shoes',\n }),\n ],\n ],\n};\n\nexport const viewItem: Flow.StepExample = {\n title: 'View item',\n description:\n 'A product view becomes a Criteo viewItem event with the viewed product id.',\n in: getEvent('product view', {\n timestamp: 1700000902000,\n data: { id: 'SKU-C3', name: 'Coffee Maker' },\n nested: [\n {\n entity: 'product',\n data: { id: 'SKU-C3' },\n },\n ],\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://shop.example.com/products/coffee-maker',\n },\n }),\n mapping: {\n name: 'viewItem',\n data: {\n map: {\n item: {\n loop: [\n 'nested',\n {\n condition: (entity: unknown) =>\n isObject(entity) && entity.entity === 'product',\n map: {\n id: 'data.id',\n },\n },\n ],\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n version: 'walkeros_criteo_1.0.0',\n site_type: 'd',\n account: 'PARTNER_ID',\n id: {\n mapping_key: 'CALLER_ID',\n },\n events: [\n {\n event: 'viewItem',\n timestamp: '2023-11-14T22:28:22.000Z',\n item: [\n {\n id: 'SKU-C3',\n },\n ],\n },\n ],\n full_url: 'https://shop.example.com/products/coffee-maker',\n }),\n ],\n ],\n};\n\nexport const pageView: Flow.StepExample = {\n title: 'Page view',\n description:\n 'A page view becomes a Criteo viewHome event used for home page impression tracking.',\n in: getEvent('page view', {\n timestamp: 1700000903000,\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://example.com/',\n },\n }),\n mapping: {\n name: 'viewHome',\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n version: 'walkeros_criteo_1.0.0',\n site_type: 'd',\n account: 'PARTNER_ID',\n id: {\n mapping_key: 'CALLER_ID',\n },\n events: [\n {\n event: 'viewHome',\n timestamp: '2023-11-14T22:28:23.000Z',\n },\n ],\n full_url: 'https://example.com/',\n }),\n ],\n ],\n};\n"],"mappings":"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","names":["import_dev","import_dev","import_dev"]}
package/dist/dev.mjs CHANGED
@@ -1 +1 @@
1
- var e=Object.defineProperty,t=(t,i)=>{for(var r in i)e(t,r,{get:i[r],enumerable:!0})},i={};t(i,{CriteoEventNameSchema:()=>d,MappingSchema:()=>s,SettingsSchema:()=>o,mapping:()=>c,settings:()=>m});import{zodToSchema as r}from"@walkeros/core/dev";import{z as a}from"@walkeros/core/dev";var o=a.object({partnerId:a.string().min(1).describe("Criteo Partner ID (numeric string, provided by Criteo)"),callerId:a.string().min(1).describe("Caller ID for user mapping (provided by Criteo)"),siteType:a.enum(["d","m","t"]).describe("Site type: d (desktop), m (mobile web), t (tablet)").optional(),country:a.string().length(2).describe("ISO 3166-1 alpha-2 country code").optional(),language:a.string().length(2).describe("2-letter language code").optional(),url:a.string().url().describe("Custom Events API endpoint (default https://widget.criteo.com/m/event?version=s2s_v0)").optional(),user_data:a.record(a.string(),a.string()).describe("Mapping for identity fields (like { email: 'user.email', mapped_user_id: 'user.id' })").optional()});import{z as n}from"@walkeros/core/dev";var s=n.object({});import{z as p}from"@walkeros/core/dev";var d=p.union([p.enum(["viewHome","viewPage","viewItem","viewList","addToCart","viewBasket","beginCheckout","trackTransaction","addPaymentInfo","login"]),p.string()]),m=r(o),c=r(s),u={};t(u,{env:()=>l,step:()=>h});var l={};t(l,{push:()=>v,simulation:()=>g});var v={sendServer:async()=>({ok:!0,data:"OK"})},g=["sendServer"],h={};t(h,{addToCart:()=>k,pageView:()=>S,purchase:()=>f,viewItem:()=>b});import{getEvent as y,isObject as w}from"@walkeros/core";var _="https://widget.criteo.com/m/event?version=s2s_v0",f={title:"Purchase",description:"A completed order is posted to the Criteo Events API as a trackTransaction event with items.",in:y("order complete",{timestamp:17000009e5,data:{id:"ORD-300",total:249.99,currency:"EUR"},nested:[{entity:"product",data:{id:"SKU-A1",name:"Widget Pro",price:124.99,quantity:2}}],user:{id:"user-123",device:"device-456"},source:{type:"browser",platform:"web",url:"https://shop.example.com/checkout/complete",referrer:"https://shop.example.com/cart"}}),mapping:{name:"trackTransaction",data:{map:{id:"data.id",item:{loop:["nested",{condition:e=>w(e)&&"product"===e.entity,map:{id:"data.id",price:"data.price",quantity:{key:"data.quantity",value:1}}}]}}}},out:[["sendServer",_,JSON.stringify({version:"walkeros_criteo_1.0.0",site_type:"d",account:"PARTNER_ID",id:{mapping_key:"CALLER_ID"},events:[{event:"trackTransaction",timestamp:"2023-11-14T22:28:20.000Z",id:"ORD-300",item:[{id:"SKU-A1",price:124.99,quantity:2}]}],full_url:"https://shop.example.com/checkout/complete",previous_url:"https://shop.example.com/cart"})]]},k={title:"Add to cart",description:"A product add becomes a Criteo addToCart event with the item id, price, and quantity.",in:y("product add",{timestamp:1700000901e3,data:{id:"SKU-B2",name:"Running Shoes",price:89.99},nested:[{entity:"product",data:{id:"SKU-B2",name:"Running Shoes",price:89.99,quantity:1}}],source:{type:"browser",platform:"web",url:"https://shop.example.com/products/running-shoes"}}),mapping:{name:"addToCart",data:{map:{item:{loop:["nested",{condition:e=>w(e)&&"product"===e.entity,map:{id:"data.id",price:"data.price",quantity:{key:"data.quantity",value:1}}}]}}}},out:[["sendServer",_,JSON.stringify({version:"walkeros_criteo_1.0.0",site_type:"d",account:"PARTNER_ID",id:{mapping_key:"CALLER_ID"},events:[{event:"addToCart",timestamp:"2023-11-14T22:28:21.000Z",item:[{id:"SKU-B2",price:89.99,quantity:1}]}],full_url:"https://shop.example.com/products/running-shoes"})]]},b={title:"View item",description:"A product view becomes a Criteo viewItem event with the viewed product id.",in:y("product view",{timestamp:1700000902e3,data:{id:"SKU-C3",name:"Coffee Maker"},nested:[{entity:"product",data:{id:"SKU-C3"}}],source:{type:"browser",platform:"web",url:"https://shop.example.com/products/coffee-maker"}}),mapping:{name:"viewItem",data:{map:{item:{loop:["nested",{condition:e=>w(e)&&"product"===e.entity,map:{id:"data.id"}}]}}}},out:[["sendServer",_,JSON.stringify({version:"walkeros_criteo_1.0.0",site_type:"d",account:"PARTNER_ID",id:{mapping_key:"CALLER_ID"},events:[{event:"viewItem",timestamp:"2023-11-14T22:28:22.000Z",item:[{id:"SKU-C3"}]}],full_url:"https://shop.example.com/products/coffee-maker"})]]},S={title:"Page view",description:"A page view becomes a Criteo viewHome event used for home page impression tracking.",in:y("page view",{timestamp:1700000903e3,source:{type:"browser",platform:"web",url:"https://example.com/"}}),mapping:{name:"viewHome"},out:[["sendServer",_,JSON.stringify({version:"walkeros_criteo_1.0.0",site_type:"d",account:"PARTNER_ID",id:{mapping_key:"CALLER_ID"},events:[{event:"viewHome",timestamp:"2023-11-14T22:28:23.000Z"}],full_url:"https://example.com/"})]]};export{u as examples,i as schemas};//# sourceMappingURL=dev.mjs.map
1
+ var e=Object.defineProperty,t=(t,i)=>{for(var a in i)e(t,a,{get:i[a],enumerable:!0})},i={};t(i,{CriteoEventNameSchema:()=>c,MappingSchema:()=>d,SettingsSchema:()=>n,mapping:()=>l,settings:()=>u});import{zodToSchema as a}from"@walkeros/core/dev";import{schemas as r,z as o}from"@walkeros/core/dev";var s=o.union([r.MappingSchemas.ValueSchema,o.literal(!1)]),n=o.object({partnerId:o.string().min(1).describe("Criteo Partner ID (numeric string, provided by Criteo)"),callerId:o.string().min(1).describe("Caller ID for user mapping (provided by Criteo)"),siteType:o.enum(["d","m","t"]).describe("Site type: d (desktop), m (mobile web), t (tablet)").optional(),country:o.string().length(2).describe("ISO 3166-1 alpha-2 country code").optional(),language:o.string().length(2).describe("2-letter language code").optional(),url:o.string().url().describe("Custom Events API endpoint (default https://widget.criteo.com/m/event?version=s2s_v0)").optional(),user_data:o.record(o.string(),o.string()).describe("Mapping for identity fields (like { email: 'user.email', mapped_user_id: 'user.id' })").optional(),ip:s.describe('Client IP, sent as ip. Resolves against { ingest, event }. Default: ["ingest.ip", "event.user.ip"]. false switches it off. A mapped user_data.ip wins.').optional(),userAgent:s.describe('Client user agent, sent as useragent. Resolves against { ingest, event }. Default: ["ingest.userAgent", "event.user.userAgent"]. false switches it off. A mapped user_data.useragent wins.').optional()});import{z as p}from"@walkeros/core/dev";var d=p.object({});import{z as m}from"@walkeros/core/dev";var c=m.union([m.enum(["viewHome","viewPage","viewItem","viewList","addToCart","viewBasket","beginCheckout","trackTransaction","addPaymentInfo","login"]),m.string()]),u=a(n),l=a(d),v={};t(v,{env:()=>g,step:()=>y});var g={};t(g,{push:()=>h,simulation:()=>w});var h={sendServer:async()=>({ok:!0,data:"OK"})},w=["sendServer"],y={};t(y,{addToCart:()=>S,pageView:()=>A,purchase:()=>k,viewItem:()=>C});import{getEvent as f,isObject as _}from"@walkeros/core";var b="https://widget.criteo.com/m/event?version=s2s_v0",k={title:"Purchase",description:"A completed order is posted to the Criteo Events API as a trackTransaction event with items.",in:f("order complete",{timestamp:17000009e5,data:{id:"ORD-300",total:249.99,currency:"EUR"},nested:[{entity:"product",data:{id:"SKU-A1",name:"Widget Pro",price:124.99,quantity:2}}],user:{id:"user-123",device:"device-456"},source:{type:"browser",platform:"web",url:"https://shop.example.com/checkout/complete",referrer:"https://shop.example.com/cart"}}),mapping:{name:"trackTransaction",data:{map:{id:"data.id",item:{loop:["nested",{condition:e=>_(e)&&"product"===e.entity,map:{id:"data.id",price:"data.price",quantity:{key:"data.quantity",value:1}}}]}}}},out:[["sendServer",b,JSON.stringify({version:"walkeros_criteo_1.0.0",site_type:"d",account:"PARTNER_ID",id:{mapping_key:"CALLER_ID"},events:[{event:"trackTransaction",timestamp:"2023-11-14T22:28:20.000Z",id:"ORD-300",item:[{id:"SKU-A1",price:124.99,quantity:2}]}],full_url:"https://shop.example.com/checkout/complete",previous_url:"https://shop.example.com/cart"})]]},S={title:"Add to cart",description:"A product add becomes a Criteo addToCart event with the item id, price, and quantity.",in:f("product add",{timestamp:1700000901e3,data:{id:"SKU-B2",name:"Running Shoes",price:89.99},nested:[{entity:"product",data:{id:"SKU-B2",name:"Running Shoes",price:89.99,quantity:1}}],source:{type:"browser",platform:"web",url:"https://shop.example.com/products/running-shoes"}}),mapping:{name:"addToCart",data:{map:{item:{loop:["nested",{condition:e=>_(e)&&"product"===e.entity,map:{id:"data.id",price:"data.price",quantity:{key:"data.quantity",value:1}}}]}}}},out:[["sendServer",b,JSON.stringify({version:"walkeros_criteo_1.0.0",site_type:"d",account:"PARTNER_ID",id:{mapping_key:"CALLER_ID"},events:[{event:"addToCart",timestamp:"2023-11-14T22:28:21.000Z",item:[{id:"SKU-B2",price:89.99,quantity:1}]}],full_url:"https://shop.example.com/products/running-shoes"})]]},C={title:"View item",description:"A product view becomes a Criteo viewItem event with the viewed product id.",in:f("product view",{timestamp:1700000902e3,data:{id:"SKU-C3",name:"Coffee Maker"},nested:[{entity:"product",data:{id:"SKU-C3"}}],source:{type:"browser",platform:"web",url:"https://shop.example.com/products/coffee-maker"}}),mapping:{name:"viewItem",data:{map:{item:{loop:["nested",{condition:e=>_(e)&&"product"===e.entity,map:{id:"data.id"}}]}}}},out:[["sendServer",b,JSON.stringify({version:"walkeros_criteo_1.0.0",site_type:"d",account:"PARTNER_ID",id:{mapping_key:"CALLER_ID"},events:[{event:"viewItem",timestamp:"2023-11-14T22:28:22.000Z",item:[{id:"SKU-C3"}]}],full_url:"https://shop.example.com/products/coffee-maker"})]]},A={title:"Page view",description:"A page view becomes a Criteo viewHome event used for home page impression tracking.",in:f("page view",{timestamp:1700000903e3,source:{type:"browser",platform:"web",url:"https://example.com/"}}),mapping:{name:"viewHome"},out:[["sendServer",b,JSON.stringify({version:"walkeros_criteo_1.0.0",site_type:"d",account:"PARTNER_ID",id:{mapping_key:"CALLER_ID"},events:[{event:"viewHome",timestamp:"2023-11-14T22:28:23.000Z"}],full_url:"https://example.com/"})]]};export{v as examples,i as schemas};//# sourceMappingURL=dev.mjs.map
package/dist/dev.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/schemas/index.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/schemas/primitives.ts","../src/examples/index.ts","../src/examples/env.ts","../src/examples/step.ts"],"sourcesContent":["import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nexport * from './primitives';\n\nexport { SettingsSchema, type Settings } from './settings';\nexport { MappingSchema, type Mapping } from './mapping';\n\n// JSON Schema\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\n","import { z } from '@walkeros/core/dev';\n\nexport const SettingsSchema = z.object({\n partnerId: z\n .string()\n .min(1)\n .describe('Criteo Partner ID (numeric string, provided by Criteo)'),\n callerId: z\n .string()\n .min(1)\n .describe('Caller ID for user mapping (provided by Criteo)'),\n siteType: z\n .enum(['d', 'm', 't'])\n .describe('Site type: d (desktop), m (mobile web), t (tablet)')\n .optional(),\n country: z\n .string()\n .length(2)\n .describe('ISO 3166-1 alpha-2 country code')\n .optional(),\n language: z.string().length(2).describe('2-letter language code').optional(),\n url: z\n .string()\n .url()\n .describe(\n 'Custom Events API endpoint (default https://widget.criteo.com/m/event?version=s2s_v0)',\n )\n .optional(),\n user_data: z\n .record(z.string(), z.string())\n .describe(\n \"Mapping for identity fields (like { email: 'user.email', mapped_user_id: 'user.id' })\",\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Criteo Events API Mapping Schema\n * Criteo has no event-level mapping configuration beyond name + data\n */\nexport const MappingSchema = z.object({});\n\n/**\n * Type inference from MappingSchema\n */\nexport type Mapping = z.infer<typeof MappingSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Standard Criteo Events API event names.\n * https://guides.criteotilt.com/events-api/\n */\nexport const CriteoEventNameSchema = z.union([\n z.enum([\n 'viewHome',\n 'viewPage',\n 'viewItem',\n 'viewList',\n 'addToCart',\n 'viewBasket',\n 'beginCheckout',\n 'trackTransaction',\n 'addPaymentInfo',\n 'login',\n ]),\n z.string(), // Allow custom event names\n]);\n","export * as env from './env';\nexport * as step from './step';\n","import type { SendDataValue, SendResponse } from '@walkeros/core';\nimport type { SendServerOptions } from '@walkeros/server-core';\nimport type { Env } from '../types';\n\n/**\n * Example environment configurations for Criteo Events API destination.\n *\n * These environments provide standardized mock structures for testing\n * and development without requiring actual HTTP requests.\n */\n\ntype MockSendServer = (\n url: string,\n data?: SendDataValue,\n options?: SendServerOptions,\n) => Promise<SendResponse>;\n\nconst mockSendServer: MockSendServer = async () => ({\n ok: true,\n data: 'OK',\n});\n\n/**\n * Standard mock environment for push operations.\n *\n * Use this for testing Criteo Events API pushes without making\n * actual HTTP requests to Criteo's servers.\n */\nexport const push: Env = {\n sendServer: mockSendServer,\n};\n\nexport const simulation = ['sendServer'];\n","import type { Flow } from '@walkeros/core';\nimport { getEvent, isObject } from '@walkeros/core';\n\n/**\n * Criteo Events API step examples.\n *\n * At push time, the destination calls `env.sendServer(url, body)` where\n * `url` is the configured Criteo endpoint (default:\n * `https://widget.criteo.com/m/event?version=s2s_v0`) and `body` is the\n * JSON-stringified request payload.\n *\n * Test fixture pins `partnerId = 'PARTNER_ID'` and `callerId = 'CALLER_ID'`,\n * so every call targets the default URL above.\n *\n * Body is emitted with keys in the order the destination assembles them:\n * 1. version\n * 2. site_type\n * 3. account\n * 4. id (identity block)\n * 5. events (always a single-element array)\n * 6. full_url (only when event.source.url is set)\n * 7. previous_url (only when event.source.referrer is set)\n */\nconst ENDPOINT = 'https://widget.criteo.com/m/event?version=s2s_v0';\n\nexport const purchase: Flow.StepExample = {\n title: 'Purchase',\n description:\n 'A completed order is posted to the Criteo Events API as a trackTransaction event with items.',\n in: getEvent('order complete', {\n timestamp: 1700000900000,\n data: { id: 'ORD-300', total: 249.99, currency: 'EUR' },\n nested: [\n {\n entity: 'product',\n data: { id: 'SKU-A1', name: 'Widget Pro', price: 124.99, quantity: 2 },\n },\n ],\n user: { id: 'user-123', device: 'device-456' },\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://shop.example.com/checkout/complete',\n referrer: 'https://shop.example.com/cart',\n },\n }),\n mapping: {\n name: 'trackTransaction',\n data: {\n map: {\n id: 'data.id',\n item: {\n loop: [\n 'nested',\n {\n condition: (entity: unknown) =>\n isObject(entity) && entity.entity === 'product',\n map: {\n id: 'data.id',\n price: 'data.price',\n quantity: { key: 'data.quantity', value: 1 },\n },\n },\n ],\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n version: 'walkeros_criteo_1.0.0',\n site_type: 'd',\n account: 'PARTNER_ID',\n id: {\n mapping_key: 'CALLER_ID',\n },\n events: [\n {\n event: 'trackTransaction',\n timestamp: '2023-11-14T22:28:20.000Z',\n id: 'ORD-300',\n item: [\n {\n id: 'SKU-A1',\n price: 124.99,\n quantity: 2,\n },\n ],\n },\n ],\n full_url: 'https://shop.example.com/checkout/complete',\n previous_url: 'https://shop.example.com/cart',\n }),\n ],\n ],\n};\n\nexport const addToCart: Flow.StepExample = {\n title: 'Add to cart',\n description:\n 'A product add becomes a Criteo addToCart event with the item id, price, and quantity.',\n in: getEvent('product add', {\n timestamp: 1700000901000,\n data: {\n id: 'SKU-B2',\n name: 'Running Shoes',\n price: 89.99,\n },\n nested: [\n {\n entity: 'product',\n data: {\n id: 'SKU-B2',\n name: 'Running Shoes',\n price: 89.99,\n quantity: 1,\n },\n },\n ],\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://shop.example.com/products/running-shoes',\n },\n }),\n mapping: {\n name: 'addToCart',\n data: {\n map: {\n item: {\n loop: [\n 'nested',\n {\n condition: (entity: unknown) =>\n isObject(entity) && entity.entity === 'product',\n map: {\n id: 'data.id',\n price: 'data.price',\n quantity: { key: 'data.quantity', value: 1 },\n },\n },\n ],\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n version: 'walkeros_criteo_1.0.0',\n site_type: 'd',\n account: 'PARTNER_ID',\n id: {\n mapping_key: 'CALLER_ID',\n },\n events: [\n {\n event: 'addToCart',\n timestamp: '2023-11-14T22:28:21.000Z',\n item: [\n {\n id: 'SKU-B2',\n price: 89.99,\n quantity: 1,\n },\n ],\n },\n ],\n full_url: 'https://shop.example.com/products/running-shoes',\n }),\n ],\n ],\n};\n\nexport const viewItem: Flow.StepExample = {\n title: 'View item',\n description:\n 'A product view becomes a Criteo viewItem event with the viewed product id.',\n in: getEvent('product view', {\n timestamp: 1700000902000,\n data: { id: 'SKU-C3', name: 'Coffee Maker' },\n nested: [\n {\n entity: 'product',\n data: { id: 'SKU-C3' },\n },\n ],\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://shop.example.com/products/coffee-maker',\n },\n }),\n mapping: {\n name: 'viewItem',\n data: {\n map: {\n item: {\n loop: [\n 'nested',\n {\n condition: (entity: unknown) =>\n isObject(entity) && entity.entity === 'product',\n map: {\n id: 'data.id',\n },\n },\n ],\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n version: 'walkeros_criteo_1.0.0',\n site_type: 'd',\n account: 'PARTNER_ID',\n id: {\n mapping_key: 'CALLER_ID',\n },\n events: [\n {\n event: 'viewItem',\n timestamp: '2023-11-14T22:28:22.000Z',\n item: [\n {\n id: 'SKU-C3',\n },\n ],\n },\n ],\n full_url: 'https://shop.example.com/products/coffee-maker',\n }),\n ],\n ],\n};\n\nexport const pageView: Flow.StepExample = {\n title: 'Page view',\n description:\n 'A page view becomes a Criteo viewHome event used for home page impression tracking.',\n in: getEvent('page view', {\n timestamp: 1700000903000,\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://example.com/',\n },\n }),\n mapping: {\n name: 'viewHome',\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n version: 'walkeros_criteo_1.0.0',\n site_type: 'd',\n account: 'PARTNER_ID',\n id: {\n mapping_key: 'CALLER_ID',\n },\n events: [\n {\n event: 'viewHome',\n timestamp: '2023-11-14T22:28:23.000Z',\n },\n ],\n full_url: 'https://example.com/',\n }),\n ],\n ],\n};\n"],"mappings":"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","names":["z","z"]}
1
+ {"version":3,"sources":["../src/schemas/index.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/schemas/primitives.ts","../src/examples/index.ts","../src/examples/env.ts","../src/examples/step.ts"],"sourcesContent":["import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nexport * from './primitives';\n\nexport { SettingsSchema, type Settings } from './settings';\nexport { MappingSchema, type Mapping } from './mapping';\n\n// JSON Schema\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\n","import { schemas, z } from '@walkeros/core/dev';\n\nconst InputSchema = z.union([\n schemas.MappingSchemas.ValueSchema,\n z.literal(false),\n]);\n\nexport const SettingsSchema = z.object({\n partnerId: z\n .string()\n .min(1)\n .describe('Criteo Partner ID (numeric string, provided by Criteo)'),\n callerId: z\n .string()\n .min(1)\n .describe('Caller ID for user mapping (provided by Criteo)'),\n siteType: z\n .enum(['d', 'm', 't'])\n .describe('Site type: d (desktop), m (mobile web), t (tablet)')\n .optional(),\n country: z\n .string()\n .length(2)\n .describe('ISO 3166-1 alpha-2 country code')\n .optional(),\n language: z.string().length(2).describe('2-letter language code').optional(),\n url: z\n .string()\n .url()\n .describe(\n 'Custom Events API endpoint (default https://widget.criteo.com/m/event?version=s2s_v0)',\n )\n .optional(),\n user_data: z\n .record(z.string(), z.string())\n .describe(\n \"Mapping for identity fields (like { email: 'user.email', mapped_user_id: 'user.id' })\",\n )\n .optional(),\n ip: InputSchema.describe(\n 'Client IP, sent as ip. Resolves against { ingest, event }. Default: [\"ingest.ip\", \"event.user.ip\"]. false switches it off. A mapped user_data.ip wins.',\n ).optional(),\n userAgent: InputSchema.describe(\n 'Client user agent, sent as useragent. Resolves against { ingest, event }. Default: [\"ingest.userAgent\", \"event.user.userAgent\"]. false switches it off. A mapped user_data.useragent wins.',\n ).optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Criteo Events API Mapping Schema\n * Criteo has no event-level mapping configuration beyond name + data\n */\nexport const MappingSchema = z.object({});\n\n/**\n * Type inference from MappingSchema\n */\nexport type Mapping = z.infer<typeof MappingSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Standard Criteo Events API event names.\n * https://guides.criteotilt.com/events-api/\n */\nexport const CriteoEventNameSchema = z.union([\n z.enum([\n 'viewHome',\n 'viewPage',\n 'viewItem',\n 'viewList',\n 'addToCart',\n 'viewBasket',\n 'beginCheckout',\n 'trackTransaction',\n 'addPaymentInfo',\n 'login',\n ]),\n z.string(), // Allow custom event names\n]);\n","export * as env from './env';\nexport * as step from './step';\n","import type { SendDataValue, SendResponse } from '@walkeros/core';\nimport type { SendServerOptions } from '@walkeros/server-core';\nimport type { Env } from '../types';\n\n/**\n * Example environment configurations for Criteo Events API destination.\n *\n * These environments provide standardized mock structures for testing\n * and development without requiring actual HTTP requests.\n */\n\ntype MockSendServer = (\n url: string,\n data?: SendDataValue,\n options?: SendServerOptions,\n) => Promise<SendResponse>;\n\nconst mockSendServer: MockSendServer = async () => ({\n ok: true,\n data: 'OK',\n});\n\n/**\n * Standard mock environment for push operations.\n *\n * Use this for testing Criteo Events API pushes without making\n * actual HTTP requests to Criteo's servers.\n */\nexport const push: Env = {\n sendServer: mockSendServer,\n};\n\nexport const simulation = ['sendServer'];\n","import type { Flow } from '@walkeros/core';\nimport { getEvent, isObject } from '@walkeros/core';\n\n/**\n * Criteo Events API step examples.\n *\n * At push time, the destination calls `env.sendServer(url, body)` where\n * `url` is the configured Criteo endpoint (default:\n * `https://widget.criteo.com/m/event?version=s2s_v0`) and `body` is the\n * JSON-stringified request payload.\n *\n * Test fixture pins `partnerId = 'PARTNER_ID'` and `callerId = 'CALLER_ID'`,\n * so every call targets the default URL above.\n *\n * Body is emitted with keys in the order the destination assembles them:\n * 1. version\n * 2. site_type\n * 3. account\n * 4. id (identity block)\n * 5. events (always a single-element array)\n * 6. full_url (only when event.source.url is set)\n * 7. previous_url (only when event.source.referrer is set)\n */\nconst ENDPOINT = 'https://widget.criteo.com/m/event?version=s2s_v0';\n\nexport const purchase: Flow.StepExample = {\n title: 'Purchase',\n description:\n 'A completed order is posted to the Criteo Events API as a trackTransaction event with items.',\n in: getEvent('order complete', {\n timestamp: 1700000900000,\n data: { id: 'ORD-300', total: 249.99, currency: 'EUR' },\n nested: [\n {\n entity: 'product',\n data: { id: 'SKU-A1', name: 'Widget Pro', price: 124.99, quantity: 2 },\n },\n ],\n user: { id: 'user-123', device: 'device-456' },\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://shop.example.com/checkout/complete',\n referrer: 'https://shop.example.com/cart',\n },\n }),\n mapping: {\n name: 'trackTransaction',\n data: {\n map: {\n id: 'data.id',\n item: {\n loop: [\n 'nested',\n {\n condition: (entity: unknown) =>\n isObject(entity) && entity.entity === 'product',\n map: {\n id: 'data.id',\n price: 'data.price',\n quantity: { key: 'data.quantity', value: 1 },\n },\n },\n ],\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n version: 'walkeros_criteo_1.0.0',\n site_type: 'd',\n account: 'PARTNER_ID',\n id: {\n mapping_key: 'CALLER_ID',\n },\n events: [\n {\n event: 'trackTransaction',\n timestamp: '2023-11-14T22:28:20.000Z',\n id: 'ORD-300',\n item: [\n {\n id: 'SKU-A1',\n price: 124.99,\n quantity: 2,\n },\n ],\n },\n ],\n full_url: 'https://shop.example.com/checkout/complete',\n previous_url: 'https://shop.example.com/cart',\n }),\n ],\n ],\n};\n\nexport const addToCart: Flow.StepExample = {\n title: 'Add to cart',\n description:\n 'A product add becomes a Criteo addToCart event with the item id, price, and quantity.',\n in: getEvent('product add', {\n timestamp: 1700000901000,\n data: {\n id: 'SKU-B2',\n name: 'Running Shoes',\n price: 89.99,\n },\n nested: [\n {\n entity: 'product',\n data: {\n id: 'SKU-B2',\n name: 'Running Shoes',\n price: 89.99,\n quantity: 1,\n },\n },\n ],\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://shop.example.com/products/running-shoes',\n },\n }),\n mapping: {\n name: 'addToCart',\n data: {\n map: {\n item: {\n loop: [\n 'nested',\n {\n condition: (entity: unknown) =>\n isObject(entity) && entity.entity === 'product',\n map: {\n id: 'data.id',\n price: 'data.price',\n quantity: { key: 'data.quantity', value: 1 },\n },\n },\n ],\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n version: 'walkeros_criteo_1.0.0',\n site_type: 'd',\n account: 'PARTNER_ID',\n id: {\n mapping_key: 'CALLER_ID',\n },\n events: [\n {\n event: 'addToCart',\n timestamp: '2023-11-14T22:28:21.000Z',\n item: [\n {\n id: 'SKU-B2',\n price: 89.99,\n quantity: 1,\n },\n ],\n },\n ],\n full_url: 'https://shop.example.com/products/running-shoes',\n }),\n ],\n ],\n};\n\nexport const viewItem: Flow.StepExample = {\n title: 'View item',\n description:\n 'A product view becomes a Criteo viewItem event with the viewed product id.',\n in: getEvent('product view', {\n timestamp: 1700000902000,\n data: { id: 'SKU-C3', name: 'Coffee Maker' },\n nested: [\n {\n entity: 'product',\n data: { id: 'SKU-C3' },\n },\n ],\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://shop.example.com/products/coffee-maker',\n },\n }),\n mapping: {\n name: 'viewItem',\n data: {\n map: {\n item: {\n loop: [\n 'nested',\n {\n condition: (entity: unknown) =>\n isObject(entity) && entity.entity === 'product',\n map: {\n id: 'data.id',\n },\n },\n ],\n },\n },\n },\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n version: 'walkeros_criteo_1.0.0',\n site_type: 'd',\n account: 'PARTNER_ID',\n id: {\n mapping_key: 'CALLER_ID',\n },\n events: [\n {\n event: 'viewItem',\n timestamp: '2023-11-14T22:28:22.000Z',\n item: [\n {\n id: 'SKU-C3',\n },\n ],\n },\n ],\n full_url: 'https://shop.example.com/products/coffee-maker',\n }),\n ],\n ],\n};\n\nexport const pageView: Flow.StepExample = {\n title: 'Page view',\n description:\n 'A page view becomes a Criteo viewHome event used for home page impression tracking.',\n in: getEvent('page view', {\n timestamp: 1700000903000,\n source: {\n type: 'browser',\n platform: 'web',\n url: 'https://example.com/',\n },\n }),\n mapping: {\n name: 'viewHome',\n },\n out: [\n [\n 'sendServer',\n ENDPOINT,\n JSON.stringify({\n version: 'walkeros_criteo_1.0.0',\n site_type: 'd',\n account: 'PARTNER_ID',\n id: {\n mapping_key: 'CALLER_ID',\n },\n events: [\n {\n event: 'viewHome',\n timestamp: '2023-11-14T22:28:23.000Z',\n },\n ],\n full_url: 'https://example.com/',\n }),\n ],\n ],\n};\n"],"mappings":"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","names":["z","z"]}
package/dist/index.d.mts CHANGED
@@ -16,6 +16,18 @@ interface Settings {
16
16
  url?: string;
17
17
  /** Mapping for identity fields (mapped_user_id, email, retailer_visitor_id) */
18
18
  user_data?: Mapping$1.Map;
19
+ /**
20
+ * Client IP, sent as ip. Resolves against { ingest, event }.
21
+ * `false` switches it off.
22
+ * @default ['ingest.ip', 'event.user.ip']
23
+ */
24
+ ip?: Mapping$1.Value | false;
25
+ /**
26
+ * Client user agent, sent as useragent. Resolves against
27
+ * { ingest, event }. `false` switches it off.
28
+ * @default ['ingest.userAgent', 'event.user.userAgent']
29
+ */
30
+ userAgent?: Mapping$1.Value | false;
19
31
  }
20
32
  type InitSettings = Partial<Settings>;
21
33
  interface Mapping {
package/dist/index.d.ts CHANGED
@@ -16,6 +16,18 @@ interface Settings {
16
16
  url?: string;
17
17
  /** Mapping for identity fields (mapped_user_id, email, retailer_visitor_id) */
18
18
  user_data?: Mapping$1.Map;
19
+ /**
20
+ * Client IP, sent as ip. Resolves against { ingest, event }.
21
+ * `false` switches it off.
22
+ * @default ['ingest.ip', 'event.user.ip']
23
+ */
24
+ ip?: Mapping$1.Value | false;
25
+ /**
26
+ * Client user agent, sent as useragent. Resolves against
27
+ * { ingest, event }. `false` switches it off.
28
+ * @default ['ingest.userAgent', 'event.user.userAgent']
29
+ */
30
+ userAgent?: Mapping$1.Value | false;
19
31
  }
20
32
  type InitSettings = Partial<Settings>;
21
33
  interface Mapping {
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";var mod,__defProp=Object.defineProperty,__getOwnPropDesc=Object.getOwnPropertyDescriptor,__getOwnPropNames=Object.getOwnPropertyNames,__hasOwnProp=Object.prototype.hasOwnProperty,index_exports={};((target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})})(index_exports,{DestinationCriteo:()=>types_exports,default:()=>index_default,destinationCriteo:()=>destinationCriteo}),module.exports=(mod=index_exports,((to,from,except,desc)=>{if(from&&"object"==typeof from||"function"==typeof from)for(let key of __getOwnPropNames(from))__hasOwnProp.call(to,key)||key===except||__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable});return to})(__defProp({},"__esModule",{value:!0}),mod));var DEFAULT_URL="https://widget.criteo.com/m/event?version=s2s_v0";var import_core=require("@walkeros/core"),import_server_core=require("@walkeros/server-core"),sha256HexPattern=/^[a-f0-9]{64}$/,md5HexPattern=/^[a-f0-9]{32}$/;function toStringOrUndef(value){if(null!=value)return"string"==typeof value?value:"number"==typeof value||"boolean"==typeof value?String(value):void 0}function toNumberOrUndef(value){if("number"==typeof value&&Number.isFinite(value))return value;if("string"==typeof value&&""!==value){const n=Number(value);if(Number.isFinite(n))return n}}var push=async function(event,{config:config,rule:rule,data:data,env:env,logger:logger,collector:collector}){const{partnerId:partnerId,callerId:callerId,siteType:siteType="d",country:country,language:language,url:url=DEFAULT_URL,user_data:user_data}=config.settings,eventData=(0,import_core.isObject)(data)?data:{},userDataCustom=user_data?await(0,import_core.getMappingValue)(event,{map:user_data},{collector:collector}):{},resolvedUserData=(0,import_core.isObject)(userDataCustom)?userDataCustom:{},identity={mapping_key:callerId},mappedUserId=toStringOrUndef(resolvedUserData.mapped_user_id);mappedUserId&&(identity.mapped_user_id=mappedUserId);const rawEmail=toStringOrUndef(resolvedUserData.email);if(rawEmail){const hashes=await async function(email){const normalized=email.toLowerCase().trim();if(!normalized)return{};if(sha256HexPattern.test(normalized))return{sha256:normalized};if(md5HexPattern.test(normalized))return{md5:normalized,sha256_md5:await(0,import_server_core.getHashServer)(normalized)};const md5=await(0,import_server_core.getHashServer)(normalized,void 0,{algorithm:"md5"});return{md5:md5,sha256:await(0,import_server_core.getHashServer)(normalized),sha256_md5:await(0,import_server_core.getHashServer)(md5)}}(rawEmail);Object.keys(hashes).length>0&&(identity.email=hashes)}const criteoEvent={event:"string"==typeof rule?.name&&rule.name||event.name,timestamp:(ts=event.timestamp,"number"==typeof ts&&Number.isFinite(ts)?new Date(ts).toISOString():"string"==typeof ts&&ts?ts:(new Date).toISOString())};var ts;const eventId=toStringOrUndef(eventData.id);eventId&&(criteoEvent.id=eventId);const items=function(raw){if(!Array.isArray(raw))return;const items=[];for(const entry of raw){if(!(0,import_core.isObject)(entry))continue;const id=toStringOrUndef(entry.id);if(!id)continue;const item={id:id},price=toNumberOrUndef(entry.price);void 0!==price&&(item.price=price);const quantity=toNumberOrUndef(entry.quantity);void 0!==quantity&&(item.quantity=quantity),items.push(item)}return items.length?items:void 0}(eventData.item);items&&(criteoEvent.item=items);const dedupId=toStringOrUndef(eventData.deduplication_page_view_id);dedupId&&(criteoEvent.deduplication_page_view_id=dedupId);const body={version:"walkeros_criteo_1.0.0",site_type:siteType,account:partnerId,id:identity,events:[criteoEvent]};event.source?.url&&(body.full_url=event.source.url),event.source?.referrer&&(body.previous_url=event.source.referrer);const retailerVisitorId=toStringOrUndef(resolvedUserData.retailer_visitor_id);retailerVisitorId&&(body.retailer_visitor_id=retailerVisitorId);const ip=toStringOrUndef(resolvedUserData.ip);ip&&(body.ip=ip);const useragent=toStringOrUndef(resolvedUserData.useragent);useragent&&(body.useragent=useragent),country&&(body.country=country),language&&(body.language=language),logger.debug("Calling Criteo Events API",{url:url,method:"POST",eventName:criteoEvent.event,eventId:criteoEvent.id});const sendServerFn=env?.sendServer||import_server_core.sendServer,result=await sendServerFn(url,JSON.stringify(body));logger.debug("Criteo API response",{ok:!(0,import_core.isObject)(result)||result.ok}),(0,import_core.isObject)(result)&&!1===result.ok&&logger.throw(`Criteo API error: ${JSON.stringify(result)}`)},types_exports={},destinationCriteo={type:"criteo",config:{},async init({config:partialConfig,logger:logger}){const config=function(partialConfig={},logger){const settings=partialConfig.settings||{},{partnerId:partnerId,callerId:callerId}=settings;partnerId||logger.throw("Config settings partnerId missing"),callerId||logger.throw("Config settings callerId missing");const settingsConfig={siteType:"d",url:DEFAULT_URL,...settings,partnerId:partnerId,callerId:callerId};return{...partialConfig,settings:settingsConfig}}(partialConfig,logger);return config},push:async(event,context)=>await push(event,context)},index_default=destinationCriteo;//# sourceMappingURL=index.js.map
1
+ "use strict";var mod,__defProp=Object.defineProperty,__getOwnPropDesc=Object.getOwnPropertyDescriptor,__getOwnPropNames=Object.getOwnPropertyNames,__hasOwnProp=Object.prototype.hasOwnProperty,index_exports={};((target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})})(index_exports,{DestinationCriteo:()=>types_exports,default:()=>index_default,destinationCriteo:()=>destinationCriteo}),module.exports=(mod=index_exports,((to,from,except,desc)=>{if(from&&"object"==typeof from||"function"==typeof from)for(let key of __getOwnPropNames(from))__hasOwnProp.call(to,key)||key===except||__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable});return to})(__defProp({},"__esModule",{value:!0}),mod));var DEFAULT_URL="https://widget.criteo.com/m/event?version=s2s_v0";var import_core=require("@walkeros/core"),import_server_core=require("@walkeros/server-core"),sha256HexPattern=/^[a-f0-9]{64}$/,md5HexPattern=/^[a-f0-9]{32}$/;function toStringOrUndef(value){if(null!=value)return"string"==typeof value?value:"number"==typeof value||"boolean"==typeof value?String(value):void 0}function toNumberOrUndef(value){if("number"==typeof value&&Number.isFinite(value))return value;if("string"==typeof value&&""!==value){const n=Number(value);if(Number.isFinite(n))return n}}var push=async function(event,{config:config,rule:rule,data:data,ingest:ingest,env:env,logger:logger,collector:collector}){const{partnerId:partnerId,callerId:callerId,siteType:siteType="d",country:country,language:language,url:url=DEFAULT_URL,user_data:user_data,ip:ip,userAgent:userAgent}=config.settings,eventData=(0,import_core.isObject)(data)?data:{},userDataCustom=user_data?await(0,import_core.getMappingValue)(event,{map:user_data},{collector:collector}):{},resolvedUserData=(0,import_core.isObject)(userDataCustom)?userDataCustom:{},identity={mapping_key:callerId},mappedUserId=toStringOrUndef(resolvedUserData.mapped_user_id);mappedUserId&&(identity.mapped_user_id=mappedUserId);const rawEmail=toStringOrUndef(resolvedUserData.email);if(rawEmail){const hashes=await async function(email){const normalized=email.toLowerCase().trim();if(!normalized)return{};if(sha256HexPattern.test(normalized))return{sha256:normalized};if(md5HexPattern.test(normalized))return{md5:normalized,sha256_md5:await(0,import_server_core.getHashServer)(normalized)};const md5=await(0,import_server_core.getHashServer)(normalized,void 0,{algorithm:"md5"});return{md5:md5,sha256:await(0,import_server_core.getHashServer)(normalized),sha256_md5:await(0,import_server_core.getHashServer)(md5)}}(rawEmail);Object.keys(hashes).length>0&&(identity.email=hashes)}const criteoEvent={event:"string"==typeof rule?.name&&rule.name||event.name,timestamp:(ts=event.timestamp,"number"==typeof ts&&Number.isFinite(ts)?new Date(ts).toISOString():"string"==typeof ts&&ts?ts:(new Date).toISOString())};var ts;const eventId=toStringOrUndef(eventData.id);eventId&&(criteoEvent.id=eventId);const items=function(raw){if(!Array.isArray(raw))return;const items=[];for(const entry of raw){if(!(0,import_core.isObject)(entry))continue;const id=toStringOrUndef(entry.id);if(!id)continue;const item={id:id},price=toNumberOrUndef(entry.price);void 0!==price&&(item.price=price);const quantity=toNumberOrUndef(entry.quantity);void 0!==quantity&&(item.quantity=quantity),items.push(item)}return items.length?items:void 0}(eventData.item);items&&(criteoEvent.item=items);const dedupId=toStringOrUndef(eventData.deduplication_page_view_id);dedupId&&(criteoEvent.deduplication_page_view_id=dedupId);const body={version:"walkeros_criteo_1.0.0",site_type:siteType,account:partnerId,id:identity,events:[criteoEvent]};event.source?.url&&(body.full_url=event.source.url),event.source?.referrer&&(body.previous_url=event.source.referrer);const retailerVisitorId=toStringOrUndef(resolvedUserData.retailer_visitor_id);retailerVisitorId&&(body.retailer_visitor_id=retailerVisitorId);const root=(0,import_core.createMappingRoot)(ingest,event),clientIp=await resolveClient(ip,DEFAULT_IP,root,collector),clientUserAgent=await resolveClient(userAgent,DEFAULT_USER_AGENT,root,collector),clientIpAddress=toStringOrUndef(resolvedUserData.ip)??clientIp;clientIpAddress&&(body.ip=clientIpAddress);const useragent=toStringOrUndef(resolvedUserData.useragent)??clientUserAgent;useragent&&(body.useragent=useragent),country&&(body.country=country),language&&(body.language=language),logger.debug("Calling Criteo Events API",{url:url,method:"POST",eventName:criteoEvent.event,eventId:criteoEvent.id});const sendServerFn=env?.sendServer||import_server_core.sendServer,result=await sendServerFn(url,JSON.stringify(body));logger.debug("Criteo API response",{ok:!(0,import_core.isObject)(result)||result.ok}),(0,import_core.isObject)(result)&&!1===result.ok&&logger.throw(`Criteo API error: ${JSON.stringify(result)}`)},DEFAULT_IP=["ingest.ip","event.user.ip"],DEFAULT_USER_AGENT=["ingest.userAgent","event.user.userAgent"];async function resolveClient(setting,fallback,root,collector){if(!1===setting)return;const value=await(0,import_core.getMappingValue)(root,setting??fallback,{collector:collector});return"string"==typeof value&&""!==value?value:void 0}var types_exports={},destinationCriteo={type:"criteo",config:{},async init({config:partialConfig,logger:logger}){const config=function(partialConfig={},logger){const settings=partialConfig.settings||{},{partnerId:partnerId,callerId:callerId}=settings;partnerId||logger.throw("Config settings partnerId missing"),callerId||logger.throw("Config settings callerId missing");const settingsConfig={siteType:"d",url:DEFAULT_URL,...settings,partnerId:partnerId,callerId:callerId};return{...partialConfig,settings:settingsConfig}}(partialConfig,logger);return config},push:async(event,context)=>await push(event,context)},index_default=destinationCriteo;//# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/config.ts","../src/push.ts","../src/types/index.ts"],"sourcesContent":["import type { Destination } from './types';\nimport { getConfig } from './config';\nimport { push } from './push';\n\n// Types\nexport * as DestinationCriteo from './types';\n\nexport const destinationCriteo: Destination = {\n type: 'criteo',\n\n config: {},\n\n async init({ config: partialConfig, logger }) {\n const config = getConfig(partialConfig, logger);\n return config;\n },\n\n async push(event, context) {\n return await push(event, context);\n },\n};\n\nexport default destinationCriteo;\n","import type { Config, Settings, PartialConfig } from './types';\nimport type { Logger } from '@walkeros/core';\n\nexport const DEFAULT_URL = 'https://widget.criteo.com/m/event?version=s2s_v0';\n\nexport function getConfig(\n partialConfig: PartialConfig = {},\n logger: Logger.Instance,\n): Config {\n const settings = (partialConfig.settings || {}) as Partial<Settings>;\n const { partnerId, callerId } = settings;\n\n if (!partnerId) logger.throw('Config settings partnerId missing');\n if (!callerId) logger.throw('Config settings callerId missing');\n\n const settingsConfig: Settings = {\n siteType: 'd',\n url: DEFAULT_URL,\n ...settings,\n partnerId,\n callerId,\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type {\n CriteoEmailHashes,\n CriteoEvent,\n CriteoIdentity,\n CriteoItem,\n CriteoRequestBody,\n Env,\n PushFn,\n Settings,\n} from './types';\nimport { getMappingValue, isObject } from '@walkeros/core';\nimport { getHashServer, sendServer } from '@walkeros/server-core';\nimport { DEFAULT_URL } from './config';\n\nconst INTEGRATION_VERSION = 'walkeros_criteo_1.0.0';\n\nconst sha256HexPattern = /^[a-f0-9]{64}$/;\nconst md5HexPattern = /^[a-f0-9]{32}$/;\n\n/**\n * Criteo Events API expects email in three hashed forms:\n * - md5: MD5 of lowercased/trimmed email\n * - sha256: SHA-256 of lowercased/trimmed email\n * - sha256_md5: SHA-256 of the MD5 hex string\n *\n * Already-hashed input is passed through: a SHA-256 hex only sets `sha256`;\n * an MD5 hex sets `md5` and derives `sha256_md5` from it.\n *\n * https://guides.criteotilt.com/events-api/\n */\nasync function hashEmail(email: string): Promise<CriteoEmailHashes> {\n const normalized = email.toLowerCase().trim();\n if (!normalized) return {};\n\n if (sha256HexPattern.test(normalized)) {\n return { sha256: normalized };\n }\n\n if (md5HexPattern.test(normalized)) {\n return { md5: normalized, sha256_md5: await getHashServer(normalized) };\n }\n\n const md5 = await getHashServer(normalized, undefined, { algorithm: 'md5' });\n return {\n md5,\n sha256: await getHashServer(normalized),\n sha256_md5: await getHashServer(md5),\n };\n}\n\nfunction toStringOrUndef(value: unknown): string | undefined {\n if (value === undefined || value === null) return undefined;\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean')\n return String(value);\n return undefined;\n}\n\nfunction toNumberOrUndef(value: unknown): number | undefined {\n if (typeof value === 'number' && Number.isFinite(value)) return value;\n if (typeof value === 'string' && value !== '') {\n const n = Number(value);\n if (Number.isFinite(n)) return n;\n }\n return undefined;\n}\n\nfunction toIsoTimestamp(ts: unknown): string {\n if (typeof ts === 'number' && Number.isFinite(ts)) {\n return new Date(ts).toISOString();\n }\n if (typeof ts === 'string' && ts) return ts;\n return new Date().toISOString();\n}\n\nfunction toItems(raw: unknown): CriteoItem[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const items: CriteoItem[] = [];\n for (const entry of raw) {\n if (!isObject(entry)) continue;\n const id = toStringOrUndef(entry.id);\n if (!id) continue;\n const item: CriteoItem = { id };\n const price = toNumberOrUndef(entry.price);\n if (price !== undefined) item.price = price;\n const quantity = toNumberOrUndef(entry.quantity);\n if (quantity !== undefined) item.quantity = quantity;\n items.push(item);\n }\n return items.length ? items : undefined;\n}\n\nexport const push: PushFn = async function (\n event,\n { config, rule, data, env, logger, collector },\n) {\n const {\n partnerId,\n callerId,\n siteType = 'd',\n country,\n language,\n url = DEFAULT_URL,\n user_data,\n } = config.settings as Settings;\n\n const eventData = isObject(data) ? data : {};\n const userDataCustom = user_data\n ? await getMappingValue(event, { map: user_data }, { collector })\n : {};\n const resolvedUserData = isObject(userDataCustom) ? userDataCustom : {};\n\n // Build identity block\n const identity: CriteoIdentity = { mapping_key: callerId };\n\n const mappedUserId = toStringOrUndef(resolvedUserData.mapped_user_id);\n if (mappedUserId) identity.mapped_user_id = mappedUserId;\n\n const rawEmail = toStringOrUndef(resolvedUserData.email);\n if (rawEmail) {\n const hashes = await hashEmail(rawEmail);\n if (Object.keys(hashes).length > 0) identity.email = hashes;\n }\n\n // Build event object\n const criteoEventName =\n (typeof rule?.name === 'string' && rule.name) || event.name;\n\n const criteoEvent: CriteoEvent = {\n event: criteoEventName,\n timestamp: toIsoTimestamp(event.timestamp),\n };\n\n const eventId = toStringOrUndef(eventData.id);\n if (eventId) criteoEvent.id = eventId;\n\n const items = toItems(eventData.item);\n if (items) criteoEvent.item = items;\n\n const dedupId = toStringOrUndef(eventData.deduplication_page_view_id);\n if (dedupId) criteoEvent.deduplication_page_view_id = dedupId;\n\n // Build request body\n const body: CriteoRequestBody = {\n version: INTEGRATION_VERSION,\n site_type: siteType,\n account: partnerId,\n id: identity,\n events: [criteoEvent],\n };\n\n if (event.source?.url) body.full_url = event.source.url;\n if (event.source?.referrer) body.previous_url = event.source.referrer;\n\n const retailerVisitorId = toStringOrUndef(\n resolvedUserData.retailer_visitor_id,\n );\n if (retailerVisitorId) body.retailer_visitor_id = retailerVisitorId;\n\n const ip = toStringOrUndef(resolvedUserData.ip);\n if (ip) body.ip = ip;\n\n const useragent = toStringOrUndef(resolvedUserData.useragent);\n if (useragent) body.useragent = useragent;\n\n if (country) body.country = country;\n if (language) body.language = language;\n\n logger.debug('Calling Criteo Events API', {\n url,\n method: 'POST',\n eventName: criteoEvent.event,\n eventId: criteoEvent.id,\n });\n\n const sendServerFn = (env as Env)?.sendServer || sendServer;\n const result = await sendServerFn(url, JSON.stringify(body));\n\n logger.debug('Criteo API response', {\n ok: isObject(result) ? result.ok : true,\n });\n\n if (isObject(result) && result.ok === false) {\n logger.throw(`Criteo API error: ${JSON.stringify(result)}`);\n }\n};\n","import type {\n Mapping as WalkerOSMapping,\n Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationServer, sendServer } from '@walkeros/server-core';\n\nexport interface Settings {\n /** Criteo Partner ID (numeric string, provided by Criteo) */\n partnerId: string;\n /** Caller ID for user mapping (provided by Criteo) */\n callerId: string;\n /** Site type: `d` (desktop), `m` (mobile web), `t` (tablet). Default `d`. */\n siteType?: SiteType;\n /** ISO 3166-1 alpha-2 country code */\n country?: string;\n /** 2-letter language code */\n language?: string;\n /** API endpoint override (default: https://widget.criteo.com/m/event?version=s2s_v0) */\n url?: string;\n /** Mapping for identity fields (mapped_user_id, email, retailer_visitor_id) */\n user_data?: WalkerOSMapping.Map;\n}\n\nexport type InitSettings = Partial<Settings>;\n\nexport interface Mapping {}\n\nexport interface Env extends DestinationServer.Env {\n sendServer?: typeof sendServer;\n}\n\nexport type Types = CoreDestination.Types<Settings, Mapping, Env, InitSettings>;\n\nexport interface Destination extends DestinationServer.Destination<Types> {\n init: DestinationServer.InitFn<Types>;\n}\n\nexport type Config = {\n settings: Settings;\n} & DestinationServer.Config<Types>;\n\nexport type InitFn = DestinationServer.InitFn<Types>;\nexport type PushFn = DestinationServer.PushFn<Types>;\n\nexport type PartialConfig = DestinationServer.PartialConfig<Types>;\n\nexport type PushEvents = DestinationServer.PushEvents<Mapping>;\n\nexport type Rule = WalkerOSMapping.Rule<Mapping>;\nexport type Rules = WalkerOSMapping.Rules<Rule>;\n\n/** Site type: desktop / mobile web / tablet */\nexport type SiteType = 'd' | 'm' | 't';\n\n/**\n * Criteo Events API (S2S v0)\n * https://guides.criteotilt.com/events-api/\n */\nexport interface CriteoRequestBody {\n /** Integration version identifier (e.g. `walkeros_criteo_1.0.0`) */\n version: string;\n site_type?: SiteType;\n /** Criteo Partner ID */\n account: string;\n id: CriteoIdentity;\n ip?: string;\n full_url?: string;\n previous_url?: string;\n useragent?: string;\n retailer_visitor_id?: string;\n country?: string;\n language?: string;\n events: CriteoEvent[];\n}\n\nexport interface CriteoIdentity {\n /** GUM ID */\n mapped_user_id?: string;\n /** Caller ID (provided by Criteo) */\n mapping_key: string;\n email?: CriteoEmailHashes;\n}\n\nexport interface CriteoEmailHashes {\n raw?: string;\n md5?: string;\n sha256?: string;\n sha256_md5?: string;\n}\n\nexport interface CriteoEvent {\n event: CriteoEventName;\n /** ISO 8601 timestamp */\n timestamp?: string;\n /** Transaction ID or event-level ID */\n id?: string;\n item?: CriteoItem[];\n deduplication_page_view_id?: string;\n}\n\nexport interface CriteoItem {\n id: string;\n price?: number;\n quantity?: number;\n}\n\n/**\n * Standard Criteo Events API event names.\n * Custom event names are also accepted as plain strings.\n */\nexport type CriteoEventName =\n | 'viewHome'\n | 'viewPage'\n | 'viewItem'\n | 'viewList'\n | 'addToCart'\n | 'viewBasket'\n | 'beginCheckout'\n | 'trackTransaction'\n | 'addPaymentInfo'\n | 'login'\n | (string & {});\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/config.ts","../src/push.ts","../src/types/index.ts"],"sourcesContent":["import type { Destination } from './types';\nimport { getConfig } from './config';\nimport { push } from './push';\n\n// Types\nexport * as DestinationCriteo from './types';\n\nexport const destinationCriteo: Destination = {\n type: 'criteo',\n\n config: {},\n\n async init({ config: partialConfig, logger }) {\n const config = getConfig(partialConfig, logger);\n return config;\n },\n\n async push(event, context) {\n return await push(event, context);\n },\n};\n\nexport default destinationCriteo;\n","import type { Config, Settings, PartialConfig } from './types';\nimport type { Logger } from '@walkeros/core';\n\nexport const DEFAULT_URL = 'https://widget.criteo.com/m/event?version=s2s_v0';\n\nexport function getConfig(\n partialConfig: PartialConfig = {},\n logger: Logger.Instance,\n): Config {\n const settings = (partialConfig.settings || {}) as Partial<Settings>;\n const { partnerId, callerId } = settings;\n\n if (!partnerId) logger.throw('Config settings partnerId missing');\n if (!callerId) logger.throw('Config settings callerId missing');\n\n const settingsConfig: Settings = {\n siteType: 'd',\n url: DEFAULT_URL,\n ...settings,\n partnerId,\n callerId,\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type {\n CriteoEmailHashes,\n CriteoEvent,\n CriteoIdentity,\n CriteoItem,\n CriteoRequestBody,\n Env,\n PushFn,\n Settings,\n} from './types';\nimport type { Collector, Mapping as WalkerOSMapping } from '@walkeros/core';\nimport { createMappingRoot, getMappingValue, isObject } from '@walkeros/core';\nimport { getHashServer, sendServer } from '@walkeros/server-core';\nimport { DEFAULT_URL } from './config';\n\nconst INTEGRATION_VERSION = 'walkeros_criteo_1.0.0';\n\nconst sha256HexPattern = /^[a-f0-9]{64}$/;\nconst md5HexPattern = /^[a-f0-9]{32}$/;\n\n/**\n * Criteo Events API expects email in three hashed forms:\n * - md5: MD5 of lowercased/trimmed email\n * - sha256: SHA-256 of lowercased/trimmed email\n * - sha256_md5: SHA-256 of the MD5 hex string\n *\n * Already-hashed input is passed through: a SHA-256 hex only sets `sha256`;\n * an MD5 hex sets `md5` and derives `sha256_md5` from it.\n *\n * https://guides.criteotilt.com/events-api/\n */\nasync function hashEmail(email: string): Promise<CriteoEmailHashes> {\n const normalized = email.toLowerCase().trim();\n if (!normalized) return {};\n\n if (sha256HexPattern.test(normalized)) {\n return { sha256: normalized };\n }\n\n if (md5HexPattern.test(normalized)) {\n return { md5: normalized, sha256_md5: await getHashServer(normalized) };\n }\n\n const md5 = await getHashServer(normalized, undefined, { algorithm: 'md5' });\n return {\n md5,\n sha256: await getHashServer(normalized),\n sha256_md5: await getHashServer(md5),\n };\n}\n\nfunction toStringOrUndef(value: unknown): string | undefined {\n if (value === undefined || value === null) return undefined;\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean')\n return String(value);\n return undefined;\n}\n\nfunction toNumberOrUndef(value: unknown): number | undefined {\n if (typeof value === 'number' && Number.isFinite(value)) return value;\n if (typeof value === 'string' && value !== '') {\n const n = Number(value);\n if (Number.isFinite(n)) return n;\n }\n return undefined;\n}\n\nfunction toIsoTimestamp(ts: unknown): string {\n if (typeof ts === 'number' && Number.isFinite(ts)) {\n return new Date(ts).toISOString();\n }\n if (typeof ts === 'string' && ts) return ts;\n return new Date().toISOString();\n}\n\nfunction toItems(raw: unknown): CriteoItem[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const items: CriteoItem[] = [];\n for (const entry of raw) {\n if (!isObject(entry)) continue;\n const id = toStringOrUndef(entry.id);\n if (!id) continue;\n const item: CriteoItem = { id };\n const price = toNumberOrUndef(entry.price);\n if (price !== undefined) item.price = price;\n const quantity = toNumberOrUndef(entry.quantity);\n if (quantity !== undefined) item.quantity = quantity;\n items.push(item);\n }\n return items.length ? items : undefined;\n}\n\nexport const push: PushFn = async function (\n event,\n { config, rule, data, ingest, env, logger, collector },\n) {\n const {\n partnerId,\n callerId,\n siteType = 'd',\n country,\n language,\n url = DEFAULT_URL,\n user_data,\n ip,\n userAgent,\n } = config.settings as Settings;\n\n const eventData = isObject(data) ? data : {};\n const userDataCustom = user_data\n ? await getMappingValue(event, { map: user_data }, { collector })\n : {};\n const resolvedUserData = isObject(userDataCustom) ? userDataCustom : {};\n\n // Build identity block\n const identity: CriteoIdentity = { mapping_key: callerId };\n\n const mappedUserId = toStringOrUndef(resolvedUserData.mapped_user_id);\n if (mappedUserId) identity.mapped_user_id = mappedUserId;\n\n const rawEmail = toStringOrUndef(resolvedUserData.email);\n if (rawEmail) {\n const hashes = await hashEmail(rawEmail);\n if (Object.keys(hashes).length > 0) identity.email = hashes;\n }\n\n // Build event object\n const criteoEventName =\n (typeof rule?.name === 'string' && rule.name) || event.name;\n\n const criteoEvent: CriteoEvent = {\n event: criteoEventName,\n timestamp: toIsoTimestamp(event.timestamp),\n };\n\n const eventId = toStringOrUndef(eventData.id);\n if (eventId) criteoEvent.id = eventId;\n\n const items = toItems(eventData.item);\n if (items) criteoEvent.item = items;\n\n const dedupId = toStringOrUndef(eventData.deduplication_page_view_id);\n if (dedupId) criteoEvent.deduplication_page_view_id = dedupId;\n\n // Build request body\n const body: CriteoRequestBody = {\n version: INTEGRATION_VERSION,\n site_type: siteType,\n account: partnerId,\n id: identity,\n events: [criteoEvent],\n };\n\n if (event.source?.url) body.full_url = event.source.url;\n if (event.source?.referrer) body.previous_url = event.source.referrer;\n\n const retailerVisitorId = toStringOrUndef(\n resolvedUserData.retailer_visitor_id,\n );\n if (retailerVisitorId) body.retailer_visitor_id = retailerVisitorId;\n\n // Client IP and user agent: a mapped user_data value wins over the\n // auto-fill from { ingest, event }\n const root = createMappingRoot(ingest, event);\n const clientIp = await resolveClient(ip, DEFAULT_IP, root, collector);\n const clientUserAgent = await resolveClient(\n userAgent,\n DEFAULT_USER_AGENT,\n root,\n collector,\n );\n const clientIpAddress = toStringOrUndef(resolvedUserData.ip) ?? clientIp;\n if (clientIpAddress) body.ip = clientIpAddress;\n\n const useragent =\n toStringOrUndef(resolvedUserData.useragent) ?? clientUserAgent;\n if (useragent) body.useragent = useragent;\n\n if (country) body.country = country;\n if (language) body.language = language;\n\n logger.debug('Calling Criteo Events API', {\n url,\n method: 'POST',\n eventName: criteoEvent.event,\n eventId: criteoEvent.id,\n });\n\n const sendServerFn = (env as Env)?.sendServer || sendServer;\n const result = await sendServerFn(url, JSON.stringify(body));\n\n logger.debug('Criteo API response', {\n ok: isObject(result) ? result.ok : true,\n });\n\n if (isObject(result) && result.ok === false) {\n logger.throw(`Criteo API error: ${JSON.stringify(result)}`);\n }\n};\n\nconst DEFAULT_IP: WalkerOSMapping.Value = ['ingest.ip', 'event.user.ip'];\nconst DEFAULT_USER_AGENT: WalkerOSMapping.Value = [\n 'ingest.userAgent',\n 'event.user.userAgent',\n];\n\n/** A client IP or user agent setting resolved to a non-empty string. */\nasync function resolveClient(\n setting: WalkerOSMapping.Value | false | undefined,\n fallback: WalkerOSMapping.Value,\n root: WalkerOSMapping.Root,\n collector: Collector.Instance,\n): Promise<string | undefined> {\n if (setting === false) return undefined;\n const value = await getMappingValue(root, setting ?? fallback, { collector });\n return typeof value === 'string' && value !== '' ? value : undefined;\n}\n","import type {\n Mapping as WalkerOSMapping,\n Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationServer, sendServer } from '@walkeros/server-core';\n\nexport interface Settings {\n /** Criteo Partner ID (numeric string, provided by Criteo) */\n partnerId: string;\n /** Caller ID for user mapping (provided by Criteo) */\n callerId: string;\n /** Site type: `d` (desktop), `m` (mobile web), `t` (tablet). Default `d`. */\n siteType?: SiteType;\n /** ISO 3166-1 alpha-2 country code */\n country?: string;\n /** 2-letter language code */\n language?: string;\n /** API endpoint override (default: https://widget.criteo.com/m/event?version=s2s_v0) */\n url?: string;\n /** Mapping for identity fields (mapped_user_id, email, retailer_visitor_id) */\n user_data?: WalkerOSMapping.Map;\n /**\n * Client IP, sent as ip. Resolves against { ingest, event }.\n * `false` switches it off.\n * @default ['ingest.ip', 'event.user.ip']\n */\n ip?: WalkerOSMapping.Value | false;\n /**\n * Client user agent, sent as useragent. Resolves against\n * { ingest, event }. `false` switches it off.\n * @default ['ingest.userAgent', 'event.user.userAgent']\n */\n userAgent?: WalkerOSMapping.Value | false;\n}\n\nexport type InitSettings = Partial<Settings>;\n\nexport interface Mapping {}\n\nexport interface Env extends DestinationServer.Env {\n sendServer?: typeof sendServer;\n}\n\nexport type Types = CoreDestination.Types<Settings, Mapping, Env, InitSettings>;\n\nexport interface Destination extends DestinationServer.Destination<Types> {\n init: DestinationServer.InitFn<Types>;\n}\n\nexport type Config = {\n settings: Settings;\n} & DestinationServer.Config<Types>;\n\nexport type InitFn = DestinationServer.InitFn<Types>;\nexport type PushFn = DestinationServer.PushFn<Types>;\n\nexport type PartialConfig = DestinationServer.PartialConfig<Types>;\n\nexport type PushEvents = DestinationServer.PushEvents<Mapping>;\n\nexport type Rule = WalkerOSMapping.Rule<Mapping>;\nexport type Rules = WalkerOSMapping.Rules<Rule>;\n\n/** Site type: desktop / mobile web / tablet */\nexport type SiteType = 'd' | 'm' | 't';\n\n/**\n * Criteo Events API (S2S v0)\n * https://guides.criteotilt.com/events-api/\n */\nexport interface CriteoRequestBody {\n /** Integration version identifier (e.g. `walkeros_criteo_1.0.0`) */\n version: string;\n site_type?: SiteType;\n /** Criteo Partner ID */\n account: string;\n id: CriteoIdentity;\n ip?: string;\n full_url?: string;\n previous_url?: string;\n useragent?: string;\n retailer_visitor_id?: string;\n country?: string;\n language?: string;\n events: CriteoEvent[];\n}\n\nexport interface CriteoIdentity {\n /** GUM ID */\n mapped_user_id?: string;\n /** Caller ID (provided by Criteo) */\n mapping_key: string;\n email?: CriteoEmailHashes;\n}\n\nexport interface CriteoEmailHashes {\n raw?: string;\n md5?: string;\n sha256?: string;\n sha256_md5?: string;\n}\n\nexport interface CriteoEvent {\n event: CriteoEventName;\n /** ISO 8601 timestamp */\n timestamp?: string;\n /** Transaction ID or event-level ID */\n id?: string;\n item?: CriteoItem[];\n deduplication_page_view_id?: string;\n}\n\nexport interface CriteoItem {\n id: string;\n price?: number;\n quantity?: number;\n}\n\n/**\n * Standard Criteo Events API event names.\n * Custom event names are also accepted as plain strings.\n */\nexport type CriteoEventName =\n | 'viewHome'\n | 'viewPage'\n | 'viewItem'\n | 'viewList'\n | 'addToCart'\n | 'viewBasket'\n | 'beginCheckout'\n | 'trackTransaction'\n | 'addPaymentInfo'\n | 'login'\n | (string & {});\n"],"mappings":"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","names":[]}
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- var DEFAULT_URL="https://widget.criteo.com/m/event?version=s2s_v0";import{getMappingValue,isObject}from"@walkeros/core";import{getHashServer,sendServer}from"@walkeros/server-core";var sha256HexPattern=/^[a-f0-9]{64}$/,md5HexPattern=/^[a-f0-9]{32}$/;function toStringOrUndef(value){if(null!=value)return"string"==typeof value?value:"number"==typeof value||"boolean"==typeof value?String(value):void 0}function toNumberOrUndef(value){if("number"==typeof value&&Number.isFinite(value))return value;if("string"==typeof value&&""!==value){const n=Number(value);if(Number.isFinite(n))return n}}var push=async function(event,{config:config,rule:rule,data:data,env:env,logger:logger,collector:collector}){const{partnerId:partnerId,callerId:callerId,siteType:siteType="d",country:country,language:language,url:url=DEFAULT_URL,user_data:user_data}=config.settings,eventData=isObject(data)?data:{},userDataCustom=user_data?await getMappingValue(event,{map:user_data},{collector:collector}):{},resolvedUserData=isObject(userDataCustom)?userDataCustom:{},identity={mapping_key:callerId},mappedUserId=toStringOrUndef(resolvedUserData.mapped_user_id);mappedUserId&&(identity.mapped_user_id=mappedUserId);const rawEmail=toStringOrUndef(resolvedUserData.email);if(rawEmail){const hashes=await async function(email){const normalized=email.toLowerCase().trim();if(!normalized)return{};if(sha256HexPattern.test(normalized))return{sha256:normalized};if(md5HexPattern.test(normalized))return{md5:normalized,sha256_md5:await getHashServer(normalized)};const md5=await getHashServer(normalized,void 0,{algorithm:"md5"});return{md5:md5,sha256:await getHashServer(normalized),sha256_md5:await getHashServer(md5)}}(rawEmail);Object.keys(hashes).length>0&&(identity.email=hashes)}const criteoEvent={event:"string"==typeof rule?.name&&rule.name||event.name,timestamp:(ts=event.timestamp,"number"==typeof ts&&Number.isFinite(ts)?new Date(ts).toISOString():"string"==typeof ts&&ts?ts:(new Date).toISOString())};var ts;const eventId=toStringOrUndef(eventData.id);eventId&&(criteoEvent.id=eventId);const items=function(raw){if(!Array.isArray(raw))return;const items=[];for(const entry of raw){if(!isObject(entry))continue;const id=toStringOrUndef(entry.id);if(!id)continue;const item={id:id},price=toNumberOrUndef(entry.price);void 0!==price&&(item.price=price);const quantity=toNumberOrUndef(entry.quantity);void 0!==quantity&&(item.quantity=quantity),items.push(item)}return items.length?items:void 0}(eventData.item);items&&(criteoEvent.item=items);const dedupId=toStringOrUndef(eventData.deduplication_page_view_id);dedupId&&(criteoEvent.deduplication_page_view_id=dedupId);const body={version:"walkeros_criteo_1.0.0",site_type:siteType,account:partnerId,id:identity,events:[criteoEvent]};event.source?.url&&(body.full_url=event.source.url),event.source?.referrer&&(body.previous_url=event.source.referrer);const retailerVisitorId=toStringOrUndef(resolvedUserData.retailer_visitor_id);retailerVisitorId&&(body.retailer_visitor_id=retailerVisitorId);const ip=toStringOrUndef(resolvedUserData.ip);ip&&(body.ip=ip);const useragent=toStringOrUndef(resolvedUserData.useragent);useragent&&(body.useragent=useragent),country&&(body.country=country),language&&(body.language=language),logger.debug("Calling Criteo Events API",{url:url,method:"POST",eventName:criteoEvent.event,eventId:criteoEvent.id});const sendServerFn=env?.sendServer||sendServer,result=await sendServerFn(url,JSON.stringify(body));logger.debug("Criteo API response",{ok:!isObject(result)||result.ok}),isObject(result)&&!1===result.ok&&logger.throw(`Criteo API error: ${JSON.stringify(result)}`)},types_exports={},destinationCriteo={type:"criteo",config:{},async init({config:partialConfig,logger:logger}){const config=function(partialConfig={},logger){const settings=partialConfig.settings||{},{partnerId:partnerId,callerId:callerId}=settings;partnerId||logger.throw("Config settings partnerId missing"),callerId||logger.throw("Config settings callerId missing");const settingsConfig={siteType:"d",url:DEFAULT_URL,...settings,partnerId:partnerId,callerId:callerId};return{...partialConfig,settings:settingsConfig}}(partialConfig,logger);return config},push:async(event,context)=>await push(event,context)},index_default=destinationCriteo;export{types_exports as DestinationCriteo,index_default as default,destinationCriteo};//# sourceMappingURL=index.mjs.map
1
+ var DEFAULT_URL="https://widget.criteo.com/m/event?version=s2s_v0";import{createMappingRoot,getMappingValue,isObject}from"@walkeros/core";import{getHashServer,sendServer}from"@walkeros/server-core";var sha256HexPattern=/^[a-f0-9]{64}$/,md5HexPattern=/^[a-f0-9]{32}$/;function toStringOrUndef(value){if(null!=value)return"string"==typeof value?value:"number"==typeof value||"boolean"==typeof value?String(value):void 0}function toNumberOrUndef(value){if("number"==typeof value&&Number.isFinite(value))return value;if("string"==typeof value&&""!==value){const n=Number(value);if(Number.isFinite(n))return n}}var push=async function(event,{config:config,rule:rule,data:data,ingest:ingest,env:env,logger:logger,collector:collector}){const{partnerId:partnerId,callerId:callerId,siteType:siteType="d",country:country,language:language,url:url=DEFAULT_URL,user_data:user_data,ip:ip,userAgent:userAgent}=config.settings,eventData=isObject(data)?data:{},userDataCustom=user_data?await getMappingValue(event,{map:user_data},{collector:collector}):{},resolvedUserData=isObject(userDataCustom)?userDataCustom:{},identity={mapping_key:callerId},mappedUserId=toStringOrUndef(resolvedUserData.mapped_user_id);mappedUserId&&(identity.mapped_user_id=mappedUserId);const rawEmail=toStringOrUndef(resolvedUserData.email);if(rawEmail){const hashes=await async function(email){const normalized=email.toLowerCase().trim();if(!normalized)return{};if(sha256HexPattern.test(normalized))return{sha256:normalized};if(md5HexPattern.test(normalized))return{md5:normalized,sha256_md5:await getHashServer(normalized)};const md5=await getHashServer(normalized,void 0,{algorithm:"md5"});return{md5:md5,sha256:await getHashServer(normalized),sha256_md5:await getHashServer(md5)}}(rawEmail);Object.keys(hashes).length>0&&(identity.email=hashes)}const criteoEvent={event:"string"==typeof rule?.name&&rule.name||event.name,timestamp:(ts=event.timestamp,"number"==typeof ts&&Number.isFinite(ts)?new Date(ts).toISOString():"string"==typeof ts&&ts?ts:(new Date).toISOString())};var ts;const eventId=toStringOrUndef(eventData.id);eventId&&(criteoEvent.id=eventId);const items=function(raw){if(!Array.isArray(raw))return;const items=[];for(const entry of raw){if(!isObject(entry))continue;const id=toStringOrUndef(entry.id);if(!id)continue;const item={id:id},price=toNumberOrUndef(entry.price);void 0!==price&&(item.price=price);const quantity=toNumberOrUndef(entry.quantity);void 0!==quantity&&(item.quantity=quantity),items.push(item)}return items.length?items:void 0}(eventData.item);items&&(criteoEvent.item=items);const dedupId=toStringOrUndef(eventData.deduplication_page_view_id);dedupId&&(criteoEvent.deduplication_page_view_id=dedupId);const body={version:"walkeros_criteo_1.0.0",site_type:siteType,account:partnerId,id:identity,events:[criteoEvent]};event.source?.url&&(body.full_url=event.source.url),event.source?.referrer&&(body.previous_url=event.source.referrer);const retailerVisitorId=toStringOrUndef(resolvedUserData.retailer_visitor_id);retailerVisitorId&&(body.retailer_visitor_id=retailerVisitorId);const root=createMappingRoot(ingest,event),clientIp=await resolveClient(ip,DEFAULT_IP,root,collector),clientUserAgent=await resolveClient(userAgent,DEFAULT_USER_AGENT,root,collector),clientIpAddress=toStringOrUndef(resolvedUserData.ip)??clientIp;clientIpAddress&&(body.ip=clientIpAddress);const useragent=toStringOrUndef(resolvedUserData.useragent)??clientUserAgent;useragent&&(body.useragent=useragent),country&&(body.country=country),language&&(body.language=language),logger.debug("Calling Criteo Events API",{url:url,method:"POST",eventName:criteoEvent.event,eventId:criteoEvent.id});const sendServerFn=env?.sendServer||sendServer,result=await sendServerFn(url,JSON.stringify(body));logger.debug("Criteo API response",{ok:!isObject(result)||result.ok}),isObject(result)&&!1===result.ok&&logger.throw(`Criteo API error: ${JSON.stringify(result)}`)},DEFAULT_IP=["ingest.ip","event.user.ip"],DEFAULT_USER_AGENT=["ingest.userAgent","event.user.userAgent"];async function resolveClient(setting,fallback,root,collector){if(!1===setting)return;const value=await getMappingValue(root,setting??fallback,{collector:collector});return"string"==typeof value&&""!==value?value:void 0}var types_exports={},destinationCriteo={type:"criteo",config:{},async init({config:partialConfig,logger:logger}){const config=function(partialConfig={},logger){const settings=partialConfig.settings||{},{partnerId:partnerId,callerId:callerId}=settings;partnerId||logger.throw("Config settings partnerId missing"),callerId||logger.throw("Config settings callerId missing");const settingsConfig={siteType:"d",url:DEFAULT_URL,...settings,partnerId:partnerId,callerId:callerId};return{...partialConfig,settings:settingsConfig}}(partialConfig,logger);return config},push:async(event,context)=>await push(event,context)},index_default=destinationCriteo;export{types_exports as DestinationCriteo,index_default as default,destinationCriteo};//# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/config.ts","../src/push.ts","../src/types/index.ts","../src/index.ts"],"sourcesContent":["import type { Config, Settings, PartialConfig } from './types';\nimport type { Logger } from '@walkeros/core';\n\nexport const DEFAULT_URL = 'https://widget.criteo.com/m/event?version=s2s_v0';\n\nexport function getConfig(\n partialConfig: PartialConfig = {},\n logger: Logger.Instance,\n): Config {\n const settings = (partialConfig.settings || {}) as Partial<Settings>;\n const { partnerId, callerId } = settings;\n\n if (!partnerId) logger.throw('Config settings partnerId missing');\n if (!callerId) logger.throw('Config settings callerId missing');\n\n const settingsConfig: Settings = {\n siteType: 'd',\n url: DEFAULT_URL,\n ...settings,\n partnerId,\n callerId,\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type {\n CriteoEmailHashes,\n CriteoEvent,\n CriteoIdentity,\n CriteoItem,\n CriteoRequestBody,\n Env,\n PushFn,\n Settings,\n} from './types';\nimport { getMappingValue, isObject } from '@walkeros/core';\nimport { getHashServer, sendServer } from '@walkeros/server-core';\nimport { DEFAULT_URL } from './config';\n\nconst INTEGRATION_VERSION = 'walkeros_criteo_1.0.0';\n\nconst sha256HexPattern = /^[a-f0-9]{64}$/;\nconst md5HexPattern = /^[a-f0-9]{32}$/;\n\n/**\n * Criteo Events API expects email in three hashed forms:\n * - md5: MD5 of lowercased/trimmed email\n * - sha256: SHA-256 of lowercased/trimmed email\n * - sha256_md5: SHA-256 of the MD5 hex string\n *\n * Already-hashed input is passed through: a SHA-256 hex only sets `sha256`;\n * an MD5 hex sets `md5` and derives `sha256_md5` from it.\n *\n * https://guides.criteotilt.com/events-api/\n */\nasync function hashEmail(email: string): Promise<CriteoEmailHashes> {\n const normalized = email.toLowerCase().trim();\n if (!normalized) return {};\n\n if (sha256HexPattern.test(normalized)) {\n return { sha256: normalized };\n }\n\n if (md5HexPattern.test(normalized)) {\n return { md5: normalized, sha256_md5: await getHashServer(normalized) };\n }\n\n const md5 = await getHashServer(normalized, undefined, { algorithm: 'md5' });\n return {\n md5,\n sha256: await getHashServer(normalized),\n sha256_md5: await getHashServer(md5),\n };\n}\n\nfunction toStringOrUndef(value: unknown): string | undefined {\n if (value === undefined || value === null) return undefined;\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean')\n return String(value);\n return undefined;\n}\n\nfunction toNumberOrUndef(value: unknown): number | undefined {\n if (typeof value === 'number' && Number.isFinite(value)) return value;\n if (typeof value === 'string' && value !== '') {\n const n = Number(value);\n if (Number.isFinite(n)) return n;\n }\n return undefined;\n}\n\nfunction toIsoTimestamp(ts: unknown): string {\n if (typeof ts === 'number' && Number.isFinite(ts)) {\n return new Date(ts).toISOString();\n }\n if (typeof ts === 'string' && ts) return ts;\n return new Date().toISOString();\n}\n\nfunction toItems(raw: unknown): CriteoItem[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const items: CriteoItem[] = [];\n for (const entry of raw) {\n if (!isObject(entry)) continue;\n const id = toStringOrUndef(entry.id);\n if (!id) continue;\n const item: CriteoItem = { id };\n const price = toNumberOrUndef(entry.price);\n if (price !== undefined) item.price = price;\n const quantity = toNumberOrUndef(entry.quantity);\n if (quantity !== undefined) item.quantity = quantity;\n items.push(item);\n }\n return items.length ? items : undefined;\n}\n\nexport const push: PushFn = async function (\n event,\n { config, rule, data, env, logger, collector },\n) {\n const {\n partnerId,\n callerId,\n siteType = 'd',\n country,\n language,\n url = DEFAULT_URL,\n user_data,\n } = config.settings as Settings;\n\n const eventData = isObject(data) ? data : {};\n const userDataCustom = user_data\n ? await getMappingValue(event, { map: user_data }, { collector })\n : {};\n const resolvedUserData = isObject(userDataCustom) ? userDataCustom : {};\n\n // Build identity block\n const identity: CriteoIdentity = { mapping_key: callerId };\n\n const mappedUserId = toStringOrUndef(resolvedUserData.mapped_user_id);\n if (mappedUserId) identity.mapped_user_id = mappedUserId;\n\n const rawEmail = toStringOrUndef(resolvedUserData.email);\n if (rawEmail) {\n const hashes = await hashEmail(rawEmail);\n if (Object.keys(hashes).length > 0) identity.email = hashes;\n }\n\n // Build event object\n const criteoEventName =\n (typeof rule?.name === 'string' && rule.name) || event.name;\n\n const criteoEvent: CriteoEvent = {\n event: criteoEventName,\n timestamp: toIsoTimestamp(event.timestamp),\n };\n\n const eventId = toStringOrUndef(eventData.id);\n if (eventId) criteoEvent.id = eventId;\n\n const items = toItems(eventData.item);\n if (items) criteoEvent.item = items;\n\n const dedupId = toStringOrUndef(eventData.deduplication_page_view_id);\n if (dedupId) criteoEvent.deduplication_page_view_id = dedupId;\n\n // Build request body\n const body: CriteoRequestBody = {\n version: INTEGRATION_VERSION,\n site_type: siteType,\n account: partnerId,\n id: identity,\n events: [criteoEvent],\n };\n\n if (event.source?.url) body.full_url = event.source.url;\n if (event.source?.referrer) body.previous_url = event.source.referrer;\n\n const retailerVisitorId = toStringOrUndef(\n resolvedUserData.retailer_visitor_id,\n );\n if (retailerVisitorId) body.retailer_visitor_id = retailerVisitorId;\n\n const ip = toStringOrUndef(resolvedUserData.ip);\n if (ip) body.ip = ip;\n\n const useragent = toStringOrUndef(resolvedUserData.useragent);\n if (useragent) body.useragent = useragent;\n\n if (country) body.country = country;\n if (language) body.language = language;\n\n logger.debug('Calling Criteo Events API', {\n url,\n method: 'POST',\n eventName: criteoEvent.event,\n eventId: criteoEvent.id,\n });\n\n const sendServerFn = (env as Env)?.sendServer || sendServer;\n const result = await sendServerFn(url, JSON.stringify(body));\n\n logger.debug('Criteo API response', {\n ok: isObject(result) ? result.ok : true,\n });\n\n if (isObject(result) && result.ok === false) {\n logger.throw(`Criteo API error: ${JSON.stringify(result)}`);\n }\n};\n","import type {\n Mapping as WalkerOSMapping,\n Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationServer, sendServer } from '@walkeros/server-core';\n\nexport interface Settings {\n /** Criteo Partner ID (numeric string, provided by Criteo) */\n partnerId: string;\n /** Caller ID for user mapping (provided by Criteo) */\n callerId: string;\n /** Site type: `d` (desktop), `m` (mobile web), `t` (tablet). Default `d`. */\n siteType?: SiteType;\n /** ISO 3166-1 alpha-2 country code */\n country?: string;\n /** 2-letter language code */\n language?: string;\n /** API endpoint override (default: https://widget.criteo.com/m/event?version=s2s_v0) */\n url?: string;\n /** Mapping for identity fields (mapped_user_id, email, retailer_visitor_id) */\n user_data?: WalkerOSMapping.Map;\n}\n\nexport type InitSettings = Partial<Settings>;\n\nexport interface Mapping {}\n\nexport interface Env extends DestinationServer.Env {\n sendServer?: typeof sendServer;\n}\n\nexport type Types = CoreDestination.Types<Settings, Mapping, Env, InitSettings>;\n\nexport interface Destination extends DestinationServer.Destination<Types> {\n init: DestinationServer.InitFn<Types>;\n}\n\nexport type Config = {\n settings: Settings;\n} & DestinationServer.Config<Types>;\n\nexport type InitFn = DestinationServer.InitFn<Types>;\nexport type PushFn = DestinationServer.PushFn<Types>;\n\nexport type PartialConfig = DestinationServer.PartialConfig<Types>;\n\nexport type PushEvents = DestinationServer.PushEvents<Mapping>;\n\nexport type Rule = WalkerOSMapping.Rule<Mapping>;\nexport type Rules = WalkerOSMapping.Rules<Rule>;\n\n/** Site type: desktop / mobile web / tablet */\nexport type SiteType = 'd' | 'm' | 't';\n\n/**\n * Criteo Events API (S2S v0)\n * https://guides.criteotilt.com/events-api/\n */\nexport interface CriteoRequestBody {\n /** Integration version identifier (e.g. `walkeros_criteo_1.0.0`) */\n version: string;\n site_type?: SiteType;\n /** Criteo Partner ID */\n account: string;\n id: CriteoIdentity;\n ip?: string;\n full_url?: string;\n previous_url?: string;\n useragent?: string;\n retailer_visitor_id?: string;\n country?: string;\n language?: string;\n events: CriteoEvent[];\n}\n\nexport interface CriteoIdentity {\n /** GUM ID */\n mapped_user_id?: string;\n /** Caller ID (provided by Criteo) */\n mapping_key: string;\n email?: CriteoEmailHashes;\n}\n\nexport interface CriteoEmailHashes {\n raw?: string;\n md5?: string;\n sha256?: string;\n sha256_md5?: string;\n}\n\nexport interface CriteoEvent {\n event: CriteoEventName;\n /** ISO 8601 timestamp */\n timestamp?: string;\n /** Transaction ID or event-level ID */\n id?: string;\n item?: CriteoItem[];\n deduplication_page_view_id?: string;\n}\n\nexport interface CriteoItem {\n id: string;\n price?: number;\n quantity?: number;\n}\n\n/**\n * Standard Criteo Events API event names.\n * Custom event names are also accepted as plain strings.\n */\nexport type CriteoEventName =\n | 'viewHome'\n | 'viewPage'\n | 'viewItem'\n | 'viewList'\n | 'addToCart'\n | 'viewBasket'\n | 'beginCheckout'\n | 'trackTransaction'\n | 'addPaymentInfo'\n | 'login'\n | (string & {});\n","import type { Destination } from './types';\nimport { getConfig } from './config';\nimport { push } from './push';\n\n// Types\nexport * as DestinationCriteo from './types';\n\nexport const destinationCriteo: Destination = {\n type: 'criteo',\n\n config: {},\n\n async init({ config: partialConfig, logger }) {\n const config = getConfig(partialConfig, logger);\n return config;\n },\n\n async push(event, context) {\n return await push(event, context);\n },\n};\n\nexport default destinationCriteo;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/config.ts","../src/push.ts","../src/types/index.ts","../src/index.ts"],"sourcesContent":["import type { Config, Settings, PartialConfig } from './types';\nimport type { Logger } from '@walkeros/core';\n\nexport const DEFAULT_URL = 'https://widget.criteo.com/m/event?version=s2s_v0';\n\nexport function getConfig(\n partialConfig: PartialConfig = {},\n logger: Logger.Instance,\n): Config {\n const settings = (partialConfig.settings || {}) as Partial<Settings>;\n const { partnerId, callerId } = settings;\n\n if (!partnerId) logger.throw('Config settings partnerId missing');\n if (!callerId) logger.throw('Config settings callerId missing');\n\n const settingsConfig: Settings = {\n siteType: 'd',\n url: DEFAULT_URL,\n ...settings,\n partnerId,\n callerId,\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type {\n CriteoEmailHashes,\n CriteoEvent,\n CriteoIdentity,\n CriteoItem,\n CriteoRequestBody,\n Env,\n PushFn,\n Settings,\n} from './types';\nimport type { Collector, Mapping as WalkerOSMapping } from '@walkeros/core';\nimport { createMappingRoot, getMappingValue, isObject } from '@walkeros/core';\nimport { getHashServer, sendServer } from '@walkeros/server-core';\nimport { DEFAULT_URL } from './config';\n\nconst INTEGRATION_VERSION = 'walkeros_criteo_1.0.0';\n\nconst sha256HexPattern = /^[a-f0-9]{64}$/;\nconst md5HexPattern = /^[a-f0-9]{32}$/;\n\n/**\n * Criteo Events API expects email in three hashed forms:\n * - md5: MD5 of lowercased/trimmed email\n * - sha256: SHA-256 of lowercased/trimmed email\n * - sha256_md5: SHA-256 of the MD5 hex string\n *\n * Already-hashed input is passed through: a SHA-256 hex only sets `sha256`;\n * an MD5 hex sets `md5` and derives `sha256_md5` from it.\n *\n * https://guides.criteotilt.com/events-api/\n */\nasync function hashEmail(email: string): Promise<CriteoEmailHashes> {\n const normalized = email.toLowerCase().trim();\n if (!normalized) return {};\n\n if (sha256HexPattern.test(normalized)) {\n return { sha256: normalized };\n }\n\n if (md5HexPattern.test(normalized)) {\n return { md5: normalized, sha256_md5: await getHashServer(normalized) };\n }\n\n const md5 = await getHashServer(normalized, undefined, { algorithm: 'md5' });\n return {\n md5,\n sha256: await getHashServer(normalized),\n sha256_md5: await getHashServer(md5),\n };\n}\n\nfunction toStringOrUndef(value: unknown): string | undefined {\n if (value === undefined || value === null) return undefined;\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean')\n return String(value);\n return undefined;\n}\n\nfunction toNumberOrUndef(value: unknown): number | undefined {\n if (typeof value === 'number' && Number.isFinite(value)) return value;\n if (typeof value === 'string' && value !== '') {\n const n = Number(value);\n if (Number.isFinite(n)) return n;\n }\n return undefined;\n}\n\nfunction toIsoTimestamp(ts: unknown): string {\n if (typeof ts === 'number' && Number.isFinite(ts)) {\n return new Date(ts).toISOString();\n }\n if (typeof ts === 'string' && ts) return ts;\n return new Date().toISOString();\n}\n\nfunction toItems(raw: unknown): CriteoItem[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const items: CriteoItem[] = [];\n for (const entry of raw) {\n if (!isObject(entry)) continue;\n const id = toStringOrUndef(entry.id);\n if (!id) continue;\n const item: CriteoItem = { id };\n const price = toNumberOrUndef(entry.price);\n if (price !== undefined) item.price = price;\n const quantity = toNumberOrUndef(entry.quantity);\n if (quantity !== undefined) item.quantity = quantity;\n items.push(item);\n }\n return items.length ? items : undefined;\n}\n\nexport const push: PushFn = async function (\n event,\n { config, rule, data, ingest, env, logger, collector },\n) {\n const {\n partnerId,\n callerId,\n siteType = 'd',\n country,\n language,\n url = DEFAULT_URL,\n user_data,\n ip,\n userAgent,\n } = config.settings as Settings;\n\n const eventData = isObject(data) ? data : {};\n const userDataCustom = user_data\n ? await getMappingValue(event, { map: user_data }, { collector })\n : {};\n const resolvedUserData = isObject(userDataCustom) ? userDataCustom : {};\n\n // Build identity block\n const identity: CriteoIdentity = { mapping_key: callerId };\n\n const mappedUserId = toStringOrUndef(resolvedUserData.mapped_user_id);\n if (mappedUserId) identity.mapped_user_id = mappedUserId;\n\n const rawEmail = toStringOrUndef(resolvedUserData.email);\n if (rawEmail) {\n const hashes = await hashEmail(rawEmail);\n if (Object.keys(hashes).length > 0) identity.email = hashes;\n }\n\n // Build event object\n const criteoEventName =\n (typeof rule?.name === 'string' && rule.name) || event.name;\n\n const criteoEvent: CriteoEvent = {\n event: criteoEventName,\n timestamp: toIsoTimestamp(event.timestamp),\n };\n\n const eventId = toStringOrUndef(eventData.id);\n if (eventId) criteoEvent.id = eventId;\n\n const items = toItems(eventData.item);\n if (items) criteoEvent.item = items;\n\n const dedupId = toStringOrUndef(eventData.deduplication_page_view_id);\n if (dedupId) criteoEvent.deduplication_page_view_id = dedupId;\n\n // Build request body\n const body: CriteoRequestBody = {\n version: INTEGRATION_VERSION,\n site_type: siteType,\n account: partnerId,\n id: identity,\n events: [criteoEvent],\n };\n\n if (event.source?.url) body.full_url = event.source.url;\n if (event.source?.referrer) body.previous_url = event.source.referrer;\n\n const retailerVisitorId = toStringOrUndef(\n resolvedUserData.retailer_visitor_id,\n );\n if (retailerVisitorId) body.retailer_visitor_id = retailerVisitorId;\n\n // Client IP and user agent: a mapped user_data value wins over the\n // auto-fill from { ingest, event }\n const root = createMappingRoot(ingest, event);\n const clientIp = await resolveClient(ip, DEFAULT_IP, root, collector);\n const clientUserAgent = await resolveClient(\n userAgent,\n DEFAULT_USER_AGENT,\n root,\n collector,\n );\n const clientIpAddress = toStringOrUndef(resolvedUserData.ip) ?? clientIp;\n if (clientIpAddress) body.ip = clientIpAddress;\n\n const useragent =\n toStringOrUndef(resolvedUserData.useragent) ?? clientUserAgent;\n if (useragent) body.useragent = useragent;\n\n if (country) body.country = country;\n if (language) body.language = language;\n\n logger.debug('Calling Criteo Events API', {\n url,\n method: 'POST',\n eventName: criteoEvent.event,\n eventId: criteoEvent.id,\n });\n\n const sendServerFn = (env as Env)?.sendServer || sendServer;\n const result = await sendServerFn(url, JSON.stringify(body));\n\n logger.debug('Criteo API response', {\n ok: isObject(result) ? result.ok : true,\n });\n\n if (isObject(result) && result.ok === false) {\n logger.throw(`Criteo API error: ${JSON.stringify(result)}`);\n }\n};\n\nconst DEFAULT_IP: WalkerOSMapping.Value = ['ingest.ip', 'event.user.ip'];\nconst DEFAULT_USER_AGENT: WalkerOSMapping.Value = [\n 'ingest.userAgent',\n 'event.user.userAgent',\n];\n\n/** A client IP or user agent setting resolved to a non-empty string. */\nasync function resolveClient(\n setting: WalkerOSMapping.Value | false | undefined,\n fallback: WalkerOSMapping.Value,\n root: WalkerOSMapping.Root,\n collector: Collector.Instance,\n): Promise<string | undefined> {\n if (setting === false) return undefined;\n const value = await getMappingValue(root, setting ?? fallback, { collector });\n return typeof value === 'string' && value !== '' ? value : undefined;\n}\n","import type {\n Mapping as WalkerOSMapping,\n Destination as CoreDestination,\n} from '@walkeros/core';\nimport type { DestinationServer, sendServer } from '@walkeros/server-core';\n\nexport interface Settings {\n /** Criteo Partner ID (numeric string, provided by Criteo) */\n partnerId: string;\n /** Caller ID for user mapping (provided by Criteo) */\n callerId: string;\n /** Site type: `d` (desktop), `m` (mobile web), `t` (tablet). Default `d`. */\n siteType?: SiteType;\n /** ISO 3166-1 alpha-2 country code */\n country?: string;\n /** 2-letter language code */\n language?: string;\n /** API endpoint override (default: https://widget.criteo.com/m/event?version=s2s_v0) */\n url?: string;\n /** Mapping for identity fields (mapped_user_id, email, retailer_visitor_id) */\n user_data?: WalkerOSMapping.Map;\n /**\n * Client IP, sent as ip. Resolves against { ingest, event }.\n * `false` switches it off.\n * @default ['ingest.ip', 'event.user.ip']\n */\n ip?: WalkerOSMapping.Value | false;\n /**\n * Client user agent, sent as useragent. Resolves against\n * { ingest, event }. `false` switches it off.\n * @default ['ingest.userAgent', 'event.user.userAgent']\n */\n userAgent?: WalkerOSMapping.Value | false;\n}\n\nexport type InitSettings = Partial<Settings>;\n\nexport interface Mapping {}\n\nexport interface Env extends DestinationServer.Env {\n sendServer?: typeof sendServer;\n}\n\nexport type Types = CoreDestination.Types<Settings, Mapping, Env, InitSettings>;\n\nexport interface Destination extends DestinationServer.Destination<Types> {\n init: DestinationServer.InitFn<Types>;\n}\n\nexport type Config = {\n settings: Settings;\n} & DestinationServer.Config<Types>;\n\nexport type InitFn = DestinationServer.InitFn<Types>;\nexport type PushFn = DestinationServer.PushFn<Types>;\n\nexport type PartialConfig = DestinationServer.PartialConfig<Types>;\n\nexport type PushEvents = DestinationServer.PushEvents<Mapping>;\n\nexport type Rule = WalkerOSMapping.Rule<Mapping>;\nexport type Rules = WalkerOSMapping.Rules<Rule>;\n\n/** Site type: desktop / mobile web / tablet */\nexport type SiteType = 'd' | 'm' | 't';\n\n/**\n * Criteo Events API (S2S v0)\n * https://guides.criteotilt.com/events-api/\n */\nexport interface CriteoRequestBody {\n /** Integration version identifier (e.g. `walkeros_criteo_1.0.0`) */\n version: string;\n site_type?: SiteType;\n /** Criteo Partner ID */\n account: string;\n id: CriteoIdentity;\n ip?: string;\n full_url?: string;\n previous_url?: string;\n useragent?: string;\n retailer_visitor_id?: string;\n country?: string;\n language?: string;\n events: CriteoEvent[];\n}\n\nexport interface CriteoIdentity {\n /** GUM ID */\n mapped_user_id?: string;\n /** Caller ID (provided by Criteo) */\n mapping_key: string;\n email?: CriteoEmailHashes;\n}\n\nexport interface CriteoEmailHashes {\n raw?: string;\n md5?: string;\n sha256?: string;\n sha256_md5?: string;\n}\n\nexport interface CriteoEvent {\n event: CriteoEventName;\n /** ISO 8601 timestamp */\n timestamp?: string;\n /** Transaction ID or event-level ID */\n id?: string;\n item?: CriteoItem[];\n deduplication_page_view_id?: string;\n}\n\nexport interface CriteoItem {\n id: string;\n price?: number;\n quantity?: number;\n}\n\n/**\n * Standard Criteo Events API event names.\n * Custom event names are also accepted as plain strings.\n */\nexport type CriteoEventName =\n | 'viewHome'\n | 'viewPage'\n | 'viewItem'\n | 'viewList'\n | 'addToCart'\n | 'viewBasket'\n | 'beginCheckout'\n | 'trackTransaction'\n | 'addPaymentInfo'\n | 'login'\n | (string & {});\n","import type { Destination } from './types';\nimport { getConfig } from './config';\nimport { push } from './push';\n\n// Types\nexport * as DestinationCriteo from './types';\n\nexport const destinationCriteo: Destination = {\n type: 'criteo',\n\n config: {},\n\n async init({ config: partialConfig, logger }) {\n const config = getConfig(partialConfig, logger);\n return config;\n },\n\n async push(event, context) {\n return await push(event, context);\n },\n};\n\nexport default destinationCriteo;\n"],"mappings":"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","names":[]}
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "$meta": {
3
3
  "package": "@walkeros/server-destination-criteo",
4
- "version": "4.7.0-next-1790245733116",
4
+ "version": "4.7.0",
5
5
  "type": "destination",
6
6
  "platform": [
7
7
  "server"
8
8
  ],
9
+ "exports": {},
9
10
  "docs": "https://www.walkeros.io/docs/destinations/server/criteo",
10
11
  "source": "https://github.com/elbwalker/walkerOS/tree/main/packages/server/destinations/criteo/src"
11
12
  },
@@ -65,13 +66,187 @@
65
66
  "type": "string"
66
67
  },
67
68
  "description": "Mapping for identity fields (like { email: 'user.email', mapped_user_id: 'user.id' })"
69
+ },
70
+ "ip": {
71
+ "anyOf": [
72
+ {
73
+ "$ref": "#/definitions/MappingValue"
74
+ },
75
+ {
76
+ "type": "boolean",
77
+ "const": false
78
+ }
79
+ ],
80
+ "description": "Client IP, sent as ip. Resolves against { ingest, event }. Default: [\"ingest.ip\", \"event.user.ip\"]. false switches it off. A mapped user_data.ip wins."
81
+ },
82
+ "userAgent": {
83
+ "anyOf": [
84
+ {
85
+ "$ref": "#/definitions/MappingValue"
86
+ },
87
+ {
88
+ "type": "boolean",
89
+ "const": false
90
+ }
91
+ ],
92
+ "description": "Client user agent, sent as useragent. Resolves against { ingest, event }. Default: [\"ingest.userAgent\", \"event.user.userAgent\"]. false switches it off. A mapped user_data.useragent wins."
68
93
  }
69
94
  },
70
95
  "required": [
71
96
  "partnerId",
72
97
  "callerId"
73
98
  ],
74
- "additionalProperties": false
99
+ "additionalProperties": false,
100
+ "definitions": {
101
+ "MappingValue": {
102
+ "title": "Mapping.Value",
103
+ "description": "Polymorphic transform primitive used in every mapping field. A string path, constant, operator object (map/loop/set/condition/consent), or array of values.",
104
+ "anyOf": [
105
+ {
106
+ "type": "string",
107
+ "description": "String value or property path (e.g., \"data.id\")"
108
+ },
109
+ {
110
+ "type": "number",
111
+ "description": "Numeric value"
112
+ },
113
+ {
114
+ "type": "boolean",
115
+ "description": "Boolean value"
116
+ },
117
+ {
118
+ "description": "Value transformation configuration with multiple strategies",
119
+ "allOf": [
120
+ {
121
+ "$ref": "#/definitions/MappingValueConfig"
122
+ }
123
+ ]
124
+ },
125
+ {
126
+ "type": "array",
127
+ "items": {
128
+ "$ref": "#/definitions/MappingValue"
129
+ },
130
+ "description": "Array of values"
131
+ }
132
+ ]
133
+ },
134
+ "MappingMap": {
135
+ "title": "Mapping.Map",
136
+ "description": "Map: object mapping keys to transformation values.",
137
+ "type": "object",
138
+ "propertyNames": {
139
+ "type": "string"
140
+ },
141
+ "additionalProperties": {
142
+ "$ref": "#/definitions/MappingValue"
143
+ }
144
+ },
145
+ "MappingLoop": {
146
+ "title": "Mapping.Loop",
147
+ "description": "Loop tuple [source, transform] for iterating and transforming arrays.",
148
+ "minItems": 2,
149
+ "maxItems": 2,
150
+ "type": "array",
151
+ "items": [
152
+ {
153
+ "$ref": "#/definitions/MappingValue"
154
+ },
155
+ {
156
+ "$ref": "#/definitions/MappingValue"
157
+ }
158
+ ]
159
+ },
160
+ "MappingSet": {
161
+ "title": "Mapping.Set",
162
+ "description": "Set: array of values for selection or combination.",
163
+ "type": "array",
164
+ "items": {
165
+ "$ref": "#/definitions/MappingValue"
166
+ }
167
+ },
168
+ "WalkerOSConsent": {
169
+ "type": "object",
170
+ "propertyNames": {
171
+ "type": "string"
172
+ },
173
+ "additionalProperties": {
174
+ "type": "boolean"
175
+ },
176
+ "title": "WalkerOS.Consent",
177
+ "description": "Consent state mapping. Keys are consent groups (e.g. marketing, functional), values are booleans for granted/denied."
178
+ },
179
+ "MappingValueConfig": {
180
+ "type": "object",
181
+ "properties": {
182
+ "key": {
183
+ "description": "Property path to extract from event (e.g., \"data.id\", \"user.email\")",
184
+ "type": "string"
185
+ },
186
+ "value": {
187
+ "description": "Static primitive value",
188
+ "anyOf": [
189
+ {
190
+ "type": "string"
191
+ },
192
+ {
193
+ "type": "number"
194
+ },
195
+ {
196
+ "type": "boolean"
197
+ }
198
+ ]
199
+ },
200
+ "fn": {
201
+ "description": "Custom transformation function as string (serialized)",
202
+ "type": "string"
203
+ },
204
+ "map": {
205
+ "description": "Object mapping: transform event data to structured output",
206
+ "allOf": [
207
+ {
208
+ "$ref": "#/definitions/MappingMap"
209
+ }
210
+ ]
211
+ },
212
+ "loop": {
213
+ "description": "Loop transformation: [source, transform] for array processing",
214
+ "allOf": [
215
+ {
216
+ "$ref": "#/definitions/MappingLoop"
217
+ }
218
+ ]
219
+ },
220
+ "set": {
221
+ "description": "Set of values: combine or select from multiple values",
222
+ "allOf": [
223
+ {
224
+ "$ref": "#/definitions/MappingSet"
225
+ }
226
+ ]
227
+ },
228
+ "consent": {
229
+ "description": "Required consent states to include this value",
230
+ "allOf": [
231
+ {
232
+ "$ref": "#/definitions/WalkerOSConsent"
233
+ }
234
+ ]
235
+ },
236
+ "condition": {
237
+ "description": "Condition function as string: return true to include value",
238
+ "type": "string"
239
+ },
240
+ "validate": {
241
+ "description": "Validation function as string: return true if value is valid",
242
+ "type": "string"
243
+ }
244
+ },
245
+ "additionalProperties": false,
246
+ "title": "Mapping.ValueConfig",
247
+ "description": "Object-form value transformation with map/loop/set/condition/consent etc."
248
+ }
249
+ }
75
250
  }
76
251
  },
77
252
  "examples": {
@@ -127,7 +302,7 @@
127
302
  "consent": {
128
303
  "functional": true
129
304
  },
130
- "id": "a04a9befc09b5d26",
305
+ "id": "7e961d3821e1ee79",
131
306
  "trigger": "click",
132
307
  "entity": "product",
133
308
  "action": "add",
@@ -150,7 +325,7 @@
150
325
  "nested",
151
326
  {
152
327
  "condition": {
153
- "$code": "e=>w(e)&&\"product\"===e.entity"
328
+ "$code": "e=>_(e)&&\"product\"===e.entity"
154
329
  },
155
330
  "map": {
156
331
  "id": "data.id",
@@ -215,7 +390,7 @@
215
390
  "consent": {
216
391
  "functional": true
217
392
  },
218
- "id": "d598b6551516a7e9",
393
+ "id": "3c8b49db49c9a984",
219
394
  "trigger": "load",
220
395
  "entity": "page",
221
396
  "action": "view",
@@ -280,7 +455,7 @@
280
455
  "consent": {
281
456
  "functional": true
282
457
  },
283
- "id": "91a4710addd3c934",
458
+ "id": "14221165aefc0541",
284
459
  "trigger": "load",
285
460
  "entity": "order",
286
461
  "action": "complete",
@@ -305,7 +480,7 @@
305
480
  "nested",
306
481
  {
307
482
  "condition": {
308
- "$code": "e=>w(e)&&\"product\"===e.entity"
483
+ "$code": "e=>_(e)&&\"product\"===e.entity"
309
484
  },
310
485
  "map": {
311
486
  "id": "data.id",
@@ -366,7 +541,7 @@
366
541
  "consent": {
367
542
  "functional": true
368
543
  },
369
- "id": "78ea33adba448799",
544
+ "id": "ce353e7ea46b4c7a",
370
545
  "trigger": "load",
371
546
  "entity": "product",
372
547
  "action": "view",
@@ -389,7 +564,7 @@
389
564
  "nested",
390
565
  {
391
566
  "condition": {
392
- "$code": "e=>w(e)&&\"product\"===e.entity"
567
+ "$code": "e=>_(e)&&\"product\"===e.entity"
393
568
  },
394
569
  "map": {
395
570
  "id": "data.id"
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@walkeros/server-destination-criteo",
3
3
  "description": "Criteo Events API server destination for walkerOS",
4
- "version": "4.7.0-next-1790245733116",
4
+ "version": "4.7.0",
5
5
  "license": "MIT",
6
6
  "exports": {
7
7
  ".": {
@@ -35,11 +35,11 @@
35
35
  "update": "npx npm-check-updates -u && npm update"
36
36
  },
37
37
  "dependencies": {
38
- "@walkeros/core": "4.7.0-next-1790245733116",
39
- "@walkeros/server-core": "4.7.0-next-1790245733116"
38
+ "@walkeros/core": "4.7.0",
39
+ "@walkeros/server-core": "4.7.0"
40
40
  },
41
41
  "devDependencies": {
42
- "@walkeros/collector": "4.7.0-next-1790245733116"
42
+ "@walkeros/collector": "4.7.0"
43
43
  },
44
44
  "repository": {
45
45
  "url": "git+https://github.com/elbwalker/walkerOS.git",