UNPKG

@walkeros/server-destination-meta

Version:

Meta server destination for walkerOS

1 lines 24.6 kB
{"version":3,"sources":["../src/config.ts","../src/push.ts","../src/hash.ts","../src/types/index.ts","../src/examples/index.ts","../src/examples/events.ts","../src/examples/mapping.ts","../src/index.ts"],"sourcesContent":["import type { Config, Settings, PartialConfig } from './types';\nimport { throwError } from '@walkeros/core';\n\nexport function getConfig(partialConfig: PartialConfig = {}): Config {\n const settings = (partialConfig.settings || {}) as Partial<Settings>;\n const { accessToken, pixelId } = settings;\n\n if (!accessToken) throwError('Config settings accessToken missing');\n if (!pixelId) throwError('Config settings pixelId missing');\n\n const settingsConfig: Settings = {\n ...settings,\n accessToken,\n pixelId,\n };\n\n return { ...partialConfig, settings: settingsConfig };\n}\n","import type { WalkerOS } from '@walkeros/core';\nimport type {\n BodyParameters,\n CustomerInformationParameters,\n PushFn,\n ServerEventParameters,\n} from './types';\nimport { getMappingValue, isObject } from '@walkeros/core';\nimport { sendServer } from '@walkeros/server-core';\nimport { hashEvent } from './hash';\n\nexport const push: PushFn = async function (\n event,\n { config, mapping, data, collector, wrap },\n) {\n const {\n accessToken,\n pixelId,\n action_source = 'website',\n doNotHash,\n test_event_code,\n url = 'https://graph.facebook.com/v22.0/',\n user_data,\n } = config.settings!;\n\n const eventData = isObject(data) ? data : {};\n const configData = config.data\n ? await getMappingValue(event, config.data)\n : {};\n const userDataCustom = user_data\n ? await getMappingValue(event, { map: user_data })\n : {};\n\n const userData: CustomerInformationParameters = {\n // Destination config\n ...(isObject(configData) && isObject(configData.user_data)\n ? configData.user_data\n : {}),\n // Custom user_data\n ...(isObject(userDataCustom) ? userDataCustom : {}),\n // Event mapping\n ...(isObject(eventData.user_data) ? eventData.user_data : {}),\n };\n\n if (userData.fbclid) {\n userData.fbc = formatClickId(\n userData.fbclid,\n collector?.session?.start || event.timestamp,\n );\n delete userData.fbclid;\n }\n const serverEvent: ServerEventParameters = {\n event_name: event.event,\n event_id: event.id,\n event_time: Math.round((event.timestamp || Date.now()) / 1000),\n action_source,\n ...eventData,\n user_data: userData,\n };\n\n if (action_source === 'website')\n serverEvent.event_source_url = event.source.id;\n\n const hashedServerEvent = await hashEvent(serverEvent, doNotHash);\n\n const body: BodyParameters = { data: [hashedServerEvent] };\n\n // Test event code\n if (test_event_code) body.test_event_code = test_event_code;\n\n const sendRequest = wrap('sendServer', sendServer);\n const result = await sendRequest(\n `${url}${pixelId}/events?access_token=${accessToken}`,\n JSON.stringify(body),\n );\n\n if (isObject(result) && result.ok === false)\n throw new Error(JSON.stringify(result));\n};\n\nfunction formatClickId(clickId: unknown, time?: number): string | undefined {\n // https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/fbp-and-fbc#2--format-clickid\n\n if (!clickId) return;\n\n // Version is always \"fb\"\n const version = 'fb';\n\n // Subdomain ('com' = 0, 'example.com' = 1, 'www.example.com' = 2)\n const subdomainIndex = '1';\n\n // Get the current timestamp in milliseconds (or when the fbclid was observed)\n const creationTime = time || Date.now();\n\n return `${version}.${subdomainIndex}.${creationTime}.${clickId}`;\n}\n\nfunction lower(str: WalkerOS.Property): string {\n return String(str).toLocaleLowerCase();\n}\n","import { WalkerOS } from '@walkeros/core';\nimport { isArray, isObject, isString } from '@walkeros/core';\nimport { getHashServer } from '@walkeros/server-core';\n\nconst keysToHash = [\n 'em',\n 'ph',\n 'fn',\n 'ln',\n 'db',\n 'ge',\n 'ct',\n 'st',\n 'zp',\n 'country',\n 'external_id',\n];\n\nfunction shouldBeHashed(key: string, doNotHash: string[] = []): boolean {\n return keysToHash.includes(key) && !doNotHash.includes(key);\n}\n\ntype HashableValue = WalkerOS.AnyObject | unknown | unknown[];\n\nasync function processValue(\n value: unknown,\n shouldHash: boolean,\n): Promise<unknown> {\n if (!shouldHash) return value;\n if (isArray(value)) {\n return Promise.all(value.map((item) => getHashServer(String(item))));\n }\n return getHashServer(String(value));\n}\n\nexport async function hashEvent<T extends HashableValue>(\n value: T,\n doNotHash: string[] = [],\n): Promise<T> {\n if (!isObject(value)) return value;\n\n const isUserData = 'user_data' in value;\n const target = (isUserData ? value.user_data : value) as WalkerOS.AnyObject;\n\n const entries = await Promise.all(\n Object.entries(target).map(async ([k, v]) => [\n k,\n await processValue(v, isUserData && shouldBeHashed(k, doNotHash)),\n ]),\n );\n\n const result = entries.reduce((acc, [k, v]) => {\n if (isString(k)) acc[k] = v;\n return acc;\n }, {} as WalkerOS.AnyObject);\n\n return isUserData ? { ...value, user_data: result } : (result as T);\n}\n","import type { Mapping as WalkerOSMapping, Elb } from '@walkeros/core';\nimport type { DestinationServer } from '@walkeros/server-core';\n\ndeclare global {\n // Augment the global WalkerOS namespace with destination-specific types\n namespace WalkerOS {\n interface Elb extends Elb.RegisterDestination<Destination, Config> {}\n }\n}\n\nexport interface Destination\n extends DestinationServer.Destination<Settings, Mapping> {\n init: DestinationServer.InitFn<Settings, Mapping>;\n}\n\nexport type Config = {\n settings: Settings;\n} & DestinationServer.Config<Settings, Mapping>;\n\nexport type InitFn = DestinationServer.InitFn<Settings, Mapping>;\nexport type PushFn = DestinationServer.PushFn<Settings, Mapping>;\n\nexport type PartialConfig = DestinationServer.PartialConfig<Settings, Mapping>;\n\nexport type PushEvents = DestinationServer.PushEvents<Mapping>;\n\nexport interface Settings {\n accessToken: string;\n pixelId: string;\n action_source?: ActionSource;\n doNotHash?: string[];\n test_event_code?: string;\n url?: string;\n user_data?: WalkerOSMapping.Map;\n}\n\nexport interface Mapping {}\n\nexport type Rule = WalkerOSMapping.Rule<Mapping>;\nexport type Rules = WalkerOSMapping.Rules<Rule>;\n\n// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/main-body\nexport interface BodyParameters {\n data: Array<ServerEventParameters>;\n test_event_code?: string;\n}\n\n/**\n * Represents the top‑level parameters for a server event sent via Meta's Conversions API.\n * https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/server-event\n */\nexport interface ServerEventParameters extends StandardParameters {\n /** The event name or custom event identifier. Required for deduplication. */\n event_name: EventName;\n\n /** Unix timestamp (in seconds) when the event actually occurred. GMT timezone. */\n event_time: number;\n\n /** Map of customer information for matching (emails, phone, etc.). */\n user_data: CustomerInformationParameters;\n\n /** Additional business data about the event. */\n custom_data?: Record<string, unknown>;\n\n /** URL of the page where the event occurred. */\n event_source_url?: string;\n\n /** If true, exclude this event from ads optimization (only attribution). */\n opt_out?: boolean;\n\n /** Unique ID for deduplication across Pixel and CAPI. */\n event_id?: string;\n\n /** Source of the event (e.g., website, app). */\n action_source: ActionSource;\n\n /** Processing options (e.g., ['LDU'] for CCPA limited data use). */\n data_processing_options?: DataProcessingOption[];\n\n /** Country code for data processing option (1 = USA, 0 = auto‑geolocate). */\n data_processing_options_country?: number;\n\n /** State code for data processing option (1000 = California, 0 = auto). */\n data_processing_options_state?: number;\n\n /** App‑specific data (required if action_source is 'app'). */\n app_data?: AppData;\n\n /** HTTP referrer header of the event. */\n referrer_url?: string;\n\n /** Metadata to link delayed events to past acquisition events. */\n original_event_data?: OriginalEventDataParameters;\n\n /** User segment for more context about the customer's relationship. */\n customer_segmentation?: CustomerSegmentation;\n}\n\nexport type EventName =\n | 'AddPaymentInfo'\n | 'AddToCart'\n | 'AddToWishlist'\n | 'CompleteRegistration'\n | 'Contact'\n | 'CustomizeProduct'\n | 'Donate'\n | 'FindLocation'\n | 'InitiateCheckout'\n | 'Lead'\n | 'Purchase'\n | 'Schedule'\n | 'Search'\n | 'StartTrial'\n | 'SubmitApplication'\n | 'Subscribe'\n | 'ViewContent'\n | string;\n\nexport type ActionSource =\n | 'email'\n | 'website'\n | 'app'\n | 'phone_call'\n | 'chat'\n | 'physical_store'\n | 'system_generated'\n | 'business_messaging'\n | 'other';\n\nexport type DataProcessingOption = 'LDU';\n\nexport type CustomerSegmentation =\n | 'new_customer_to_business'\n | 'new_customer_to_business_line'\n | 'new_customer_to_product_area'\n | 'new_customer_to_medium'\n | 'existing_customer_to_business'\n | 'existing_customer_to_business_line'\n | 'existing_customer_to_product_area'\n | 'existing_customer_to_medium'\n | 'customer_in_loyalty_program';\n\n/** Extended device info for app events (Android version 'a2', iOS 'i2') */\nexport interface AppData {\n /**\n * Comma-separated array of strings with fixed order:\n * [sdk_version, os_version, device_model, device_brand,\n * screen_width, screen_height, ...]\n */\n extinfo: string[];\n}\n\n// Customer Information Parameters\n// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/customer-information-parameters\nexport interface CustomerInformationParameters {\n /** Email(s), SHA-256 hashed, lowercase and trimmed */\n em?: string | string[];\n\n /** Phone number(s), SHA-256 hashed, E.164 format (no leading 0s or symbols) */\n ph?: string | string[];\n\n /** First name(s), SHA-256 hashed, lowercase */\n fn?: string | string[];\n\n /** Last name(s), SHA-256 hashed, lowercase */\n ln?: string | string[];\n\n /** Date(s) of birth in YYYYMMDD, SHA-256 hashed */\n db?: string | string[];\n\n /** Gender(s) in lowercase single letter (\"m\", \"f\", etc.), SHA-256 hashed */\n ge?: string | string[];\n\n /** City name(s), SHA-256 hashed, lowercase */\n ct?: string | string[];\n\n /** State abbreviation(s), SHA-256 hashed, lowercase (e.g., \"ca\", \"ny\") */\n st?: string | string[];\n\n /** ZIP or postal code(s), SHA-256 hashed, lowercase */\n zp?: string | string[];\n\n /** Country code(s), SHA-256 hashed, lowercase (ISO 3166-1 alpha-2) */\n country?: string | string[];\n\n /** External IDs, unique per user. SHA-256 hash recommended */\n external_id?: string | string[];\n\n /** IPv4 or IPv6 address of client. Do NOT hash. */\n client_ip_address?: string;\n\n /** User agent string from browser. Do NOT hash. */\n client_user_agent?: string;\n\n /** fbclid parameter value from the URL. Do NOT hash. */\n fbclid?: string;\n\n /** Facebook click ID (_fbc cookie). Do NOT hash. */\n fbc?: string;\n\n /** Facebook browser ID (_fbp cookie). Do NOT hash. */\n fbp?: string;\n\n /** Subscription ID for the transaction. Do NOT hash. */\n subscription_id?: string;\n\n /** Facebook login ID (App-Scoped ID). Do NOT hash. */\n fb_login_id?: number;\n\n /** Meta Lead Ad lead ID. Do NOT hash. */\n lead_id?: number;\n\n /** Anonymous install ID. App events only. Do NOT hash. */\n anon_id?: string;\n\n /** Mobile advertiser ID (GAID/IDFA). Do NOT hash. */\n madid?: string;\n\n /** Facebook Page ID. Do NOT hash. */\n page_id?: string;\n\n /** Messenger Page-scoped user ID. Do NOT hash. */\n page_scoped_user_id?: string;\n\n /** Click to WhatsApp ad click ID. Do NOT hash. */\n ctwa_clid?: string;\n\n /** Instagram business account ID. Do NOT hash. */\n ig_account_id?: string;\n\n /** Instagram-scoped user ID. Do NOT hash. */\n ig_sid?: string;\n}\n\n// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/custom-data\nexport interface StandardParameters {\n // Web and Offline parameters\n availability?: string;\n body_style?: string;\n checkin_date?: string;\n city?: string;\n condition_of_vehicle?: string;\n content_ids?: string[];\n content_type?: 'product' | 'product_group' | string;\n contents?: Array<{\n id: string;\n quantity?: number;\n item_price?: number;\n delivery_category?: string;\n }>;\n country?: string;\n currency?: string;\n delivery_category?: 'in_store' | 'curbside' | 'home_delivery' | string;\n departing_arrival_date?: string;\n departing_departure_date?: string;\n destination_airport?: string;\n destination_ids?: string[];\n dma_code?: string;\n drivetrain?: string;\n exterior_color?: string;\n fuel_type?: string;\n hotel_score?: number;\n interior_color?: string;\n lead_event_source?: string;\n lease_end_date?: string;\n lease_start_date?: string;\n listing_type?: string;\n make?: string;\n // @TODO is mileage an object?\n 'mileage.unit'?: string;\n 'mileage.value'?: number;\n model?: string;\n neighborhood?: string;\n net_revenue?: number;\n num_adults?: number;\n num_children?: number;\n num_infants?: number;\n num_items?: number;\n order_id?: string;\n origin_airport?: string;\n postal_code?: string;\n predicted_ltv?: number;\n preferred_baths_range?: string;\n preferred_beds_range?: string;\n preferred_neighborhoods?: string[];\n preferred_num_stops?: number;\n preferred_price_range?: string;\n preferred_star_ratings?: [number, number];\n price?: string;\n product_catalog_id?: string;\n property_type?: string;\n region?: string;\n returning_arrival_date?: string;\n returning_departure_date?: string;\n search_string?: string;\n state_of_vehicle?: string;\n suggested_destinations?: string[];\n suggested_home_listings?: string[];\n suggested_hotels?: string[];\n suggested_jobs?: string[];\n suggested_local_service_businesses?: string[];\n suggested_location_based_items?: string[];\n suggested_vehicles?: string[];\n transmission?: string;\n travel_class?: string;\n travel_end?: string;\n travel_start?: string;\n trim?: string;\n\n // App-specific parameters (with fb_ prefix)\n fb_availability?: string;\n fb_body_style?: string;\n fb_checkin_date?: string;\n fb_city?: string;\n fb_condition_of_vehicle?: string;\n fb_content_ids?: string[];\n fb_content_type?: string;\n fb_contents?: Array<{ id: string; quantity?: number; item_price?: number }>;\n fb_country?: string;\n fb_currency?: string;\n fb_delivery_category?: string;\n fb_departing_arrival_date?: string;\n fb_departing_departure_date?: string;\n fb_destination_airport?: string;\n fb_destination_ids?: string[];\n fb_dma_code?: string;\n fb_drivetrain?: string;\n fb_exterior_color?: string;\n fb_fuel_type?: string;\n fb_hotel_score?: number;\n fb_interior_color?: string;\n fb_lease_end_date?: string;\n fb_lease_start_date?: string;\n fb_listing_type?: string;\n fb_make?: string;\n // @TODO is fb_mileage an object?\n 'fb_mileage.unit'?: string;\n 'fb_mileage.value'?: number;\n fb_model?: string;\n fb_neighborhood?: string;\n fb_num_adults?: number;\n fb_num_children?: number;\n fb_num_infants?: number;\n fb_num_items?: number;\n fb_order_id?: string;\n fb_origin_airport?: string;\n fb_postal_code?: string;\n fb_predicted_ltv?: number;\n fb_preferred_baths_range?: string;\n fb_preferred_beds_range?: string;\n fb_preferred_neighborhoods?: string[];\n fb_preferred_num_stops?: number;\n fb_preferred_price_range?: string;\n fb_preferred_star_ratings?: [number, number];\n fb_price?: string;\n fb_product_catalog_id?: string;\n fb_property_type?: string;\n fb_region?: string;\n fb_returning_arrival_date?: string;\n fb_returning_departure_date?: string;\n fb_search_string?: string;\n fb_state_of_vehicle?: string;\n fb_suggested_destinations?: string[];\n fb_suggested_home_listings?: string[];\n fb_suggested_hotels?: string[];\n fb_suggested_jobs?: string[];\n fb_suggested_local_service_businesses?: string[];\n fb_suggested_location_based_items?: string[];\n fb_suggested_vehicles?: string[];\n fb_transmission?: string;\n fb_travel_class?: string;\n fb_travel_end?: string;\n fb_travel_start?: string;\n\n // Offline-specific parameters\n user_bucket?: string;\n value?: number;\n vin?: string;\n year?: number;\n item_number?: string;\n}\n\nexport interface OriginalEventDataParameters {\n event_name?: EventName;\n event_time?: number;\n order_id?: number;\n event_id?: string;\n}\n","import * as events from './events';\nimport * as mapping from './mapping';\n\nexport const destinationMetaExamples = {\n events,\n mapping\n};\n","import type { BodyParameters } from '../types';\nimport { getEvent } from '@walkeros/core';\n\nexport function Purchase(): BodyParameters {\n const event = getEvent('order complete');\n\n return {\n data: [\n {\n event_name: 'Purchase',\n event_time: event.timestamp / 1000,\n event_id: event.id,\n event_source_url: event.source.id,\n action_source: 'website',\n user_data: {\n external_id: [\n 'cc8e27118413234d4297ed00a02711365312c79325df9b5b8f4199cbd0b96e7e',\n '9176e6f336dbdb4f99b0e45cbd7e41e0e2323812b236822842a61ffbd362ac8c',\n ],\n },\n order_id: String(event.data.id),\n currency: 'EUR',\n value: Number(event.data.total),\n contents: event.nested\n .filter((item) => item.type === 'product')\n .map((item) => ({\n id: String(item.data.id),\n quantity: Number(item.data.quantity) || 1,\n item_price: Number(item.data.price),\n })),\n num_items: 2,\n },\n ],\n };\n}\n","import type { WalkerOS } from '@walkeros/core';\nimport type { DestinationMeta } from '..';\nimport { isObject } from '@walkeros/core';\n\nexport const InitUserData: DestinationMeta.Settings = {\n pixelId: 'p1x3l1d',\n accessToken: 's3cr3t',\n user_data: {\n external_id: { set: ['user.device', 'user.session'] },\n },\n};\n\nexport const Purchase: DestinationMeta.Rule = {\n name: 'Purchase',\n data: {\n map: {\n order_id: 'data.id',\n currency: { key: 'data.currency', value: 'EUR' },\n value: 'data.total',\n contents: {\n loop: [\n 'nested',\n {\n condition: (entity) =>\n isObject(entity) && entity.type === 'product',\n map: {\n id: 'data.id',\n item_price: 'data.price',\n quantity: { key: 'data.quantity', value: 1 },\n },\n },\n ],\n },\n num_items: {\n fn: (event) =>\n (event as WalkerOS.Event).nested.filter(\n (item) => item.type === 'product',\n ).length,\n },\n },\n },\n};\n\nexport const config = {\n order: { complete: Purchase },\n} satisfies DestinationMeta.Rules;\n","import type { Destination } from './types';\nimport { getConfig } from './config';\nimport { push } from './push';\n\n// Types\nexport * as DestinationMeta from './types';\n\n// Examples\nexport * as destinationMetaExamples from './examples';\n\nexport const destinationMeta: Destination = {\n type: 'meta',\n\n config: {},\n\n async init({ config: partialConfig }) {\n const config = getConfig(partialConfig);\n return config;\n },\n\n async push(event, { config, mapping, data, collector, wrap }) {\n return await push(event, { config, mapping, data, collector, wrap });\n },\n};\n\nexport default destinationMeta;\n"],"mappings":"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","names":["k","v","config","Purchase","Purchase","config"]}