{"version":3,"sources":["../../src/track/fbq.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-empty-object-type */\nimport type { Item } from './gtag';\nimport type { EventName, TrackName, TrackProperties } from './types';\n\nexport type Content = {\n  id: string;\n  quantity: number;\n  item_price?: number;\n  title?: string;\n  description?: string;\n  brand?: string;\n  category?: string;\n  delivery_category?: string;\n};\n\n/**\n * reference: https://developers.facebook.com/docs/meta-pixel/advanced/advanced-matching\n * reference: https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/customer-information-parameters\n */\nexport type MatchingParameters = {\n  /** Email: Unhashed lowercase or hashed SHA-256 */\n  em?: string;\n\n  /** First Name: Lowercase letters */\n  fn?: string;\n\n  /** Last Name: Lowercase letters */\n  ln?: string;\n\n  /** Phone Number: Digits only including country code and area code */\n  ph?: string;\n\n  /**\n   * External ID: Any unique ID from the advertiser, such as loyalty membership ID, user ID, and\n   * external cookie ID.\n   */\n  external_id?: string;\n\n  /** Gender: Single lowercase letter, f or m, if unknown, leave blank */\n  ge?: 'f' | 'm' | '';\n\n  /** Birthdate: Digits only with birth year, month, then day, YYYYMMDD */\n  db?: number;\n\n  /** City: Lowercase with any spaces removed, e.g. \"menlopark\" */\n  ct?: string;\n\n  /** State or Province: Lowercase two-letter state or province code, e.g. \"ca\" */\n  st?: string;\n\n  /** Zip or Postal Code: String */\n  zp?: string;\n\n  /** Country: Lowercase two-letter country code, e.g. \"us\" */\n  country?: string;\n\n  /** Client IP Address: Do not hash. */\n  client_ip_address?: string;\n\n  /** Client User Agent: Do not hash. */\n  client_user_agent?: string;\n\n  /**\n   * Click ID: Do not hash.\n   * The Facebook click ID value is stored in the _fbc browser cookie under your domain. See\n   * Managing fbc and fbp Parameters for how to get this value or generate this value from a fbclid\n   * query parameter.\n   *\n   * The format is fb.${subdomain_index}.${creation_time}.${fbclid}.\n   */\n  fbc?: string;\n\n  /**\n   * Browser ID: Do not hash.\n   * The Facebook browser ID value is stored in the _fbp browser cookie under your domain. See\n   * Managing fbc and fbp Parameters for how to get this value.\n   *\n   * The format is fb.${subdomain_index}.${creation_time}.${random_number}.\n   */\n  fbp?: string;\n\n  /**\n   * Subscription ID: Do not hash.\n   * The subscription ID for the user in this transaction; it is similar to the order ID for an\n   * individual product.\n   */\n  subscription_id?: string;\n\n  /**\n   * Facebook Login ID: Do not hash.\n   * The ID issued by Meta when a person first logs into an instance of an app. This is also known\n   * as App-Scoped ID.\n   */\n  fb_login_id?: number;\n\n  /**\n   * Lead ID: Do not hash.\n   * The ID associated with a lead generated by [Meta's Lead Ads](https://developers.facebook.com/docs/marketing-api/guides/lead-ads).\n   */\n  lead_id?: number;\n\n  /**\n   * Install ID: Do not hash.\n   * Your install ID. This field represents unique application installation instances.\n   * Note: This parameter is for app events only.\n   */\n  anon_id?: string;\n\n  /**\n   * Your mobile advertiser ID, the advertising ID from an Android device or the Advertising\n   * Identifier (IDFA) from an Apple device.\n   */\n  madid?: string;\n\n  /**\n   * Page ID: Do not hash.\n   * Your Page ID. Specifies the page ID associated with the event. Use the Facebook page ID of the\n   * page associated with the bot.\n   */\n  page_id?: string;\n\n  /**\n   * Page Scoped User ID: Do not hash.\n   * Specifies the page-scoped user ID associated with the messenger bot that logs the event. Use\n   * the page-scoped user ID provided to your webhook.\n   */\n  page_scoped_user_id?: string;\n\n  /**\n   * Do not hash.\n   * Click ID generated by Meta for ads that click to WhatsApp.\n   */\n  ctwa_clid?: string;\n\n  /**\n   * Do not hash.\n   * Instagram Account ID that is associated with the business.\n   */\n  ig_account_id?: string;\n\n  /**\n   * Do not hash.\n   * Users who interact with Instagram are identified by Instagram-Scoped User IDs (IGSID). IGSID\n   * can be obtained from this webhook.\n   */\n  ig_sid?: string;\n};\n\n/**\n * You can include the following predefined object properties with any custom events, and any\n * standard events that support them. Format your parameter object data using JSON. Learn more about\n * event parameters with Blueprint.\n */\nexport type ObjectProperties = {\n  content_category?: string;\n  content_ids?: string[];\n  content_name?: string;\n\n  /**\n   * Either product or product_group based on the content_ids or contents being passed. If the IDs\n   * being passed in content_ids or contents parameter are IDs of products, then the value should be\n   * product. If product group IDs are being passed, then the value should be product_group.\n   *\n   * If no content_type is provided, Meta will match the event to every item that has the same ID,\n   * independent of its type.\n   */\n  content_type?: 'product' | 'product_group' | (string & {});\n  contents?: Content[];\n  delivery_category?: 'in_store' | 'curbside' | 'home_delivery';\n  currency?: string;\n  num_items?: number;\n  predicted_ltv?: number;\n  search_string?: string;\n\n  /** Used with the CompleteRegistration event, to show the status of the registration. */\n  status?: boolean;\n  value?: number;\n};\n\n/**\n * reference: https://developers.facebook.com/docs/marketing-api/conversions-api/payload-helper\n */\nexport type StandardEvents = {\n  AddPaymentInfo: {\n    content_ids?: string[];\n    contents?: Content[];\n    currency?: string;\n    value?: number;\n  };\n  AddToCart: {\n    content_ids?: string[];\n    content_type?: string;\n    contents?: Content[]; // Required for Advantage+ catalog ads: contents\n    currency?: string;\n    value?: number;\n  };\n  AddToWishlist: {\n    content_ids?: string[];\n    contents?: Content[];\n    currency?: string;\n    value?: number;\n  };\n  CompleteRegistration: {\n    currency?: string;\n    value?: number;\n    method?: string;\n  };\n  Contact: {};\n  CustomizeProduct: {};\n  Donate: {};\n  FindLocation: {};\n  InitiateCheckout: {\n    content_ids?: string[];\n    contents?: Content[];\n    currency?: string;\n    num_items?: number;\n    value?: number;\n  };\n  Lead: {\n    currency?: string;\n    value?: number;\n  };\n  Purchase: {\n    content_ids?: string[]; // Required for Advantage+ catalog ads: contents or content_ids\n    content_type?: string;\n    contents?: Content[]; // Required for Advantage+ catalog ads: contents or content_ids\n    currency: string; // required\n    num_items?: number;\n    value: number; // required\n  };\n  Schedule: {};\n  Search: {\n    content_ids?: string[]; // Required for Advantage+ catalog ads: contents or content_ids\n    content_type?: string;\n    contents?: Content[]; // Required for Advantage+ catalog ads: contents or content_ids\n    currency?: string;\n    search_string?: string;\n    value?: number;\n  };\n  StartTrial: {\n    currency?: string;\n    predicted_ltv?: number;\n    value?: number;\n  };\n  SubmitApplication: {};\n  Subscribe: {\n    currency?: string;\n    predicted_ltv?: number;\n    value?: number;\n  };\n  ViewContent: {\n    content_ids?: string[]; // Required for Advantage+ catalog ads: contents or content_ids\n    content_type?: string;\n    contents?: Content[]; // Required for Advantage+ catalog ads: contents or content_ids\n    currency?: string;\n    value?: number;\n  };\n};\n\ntype JSONValue =\n  | null\n  | string\n  | number\n  | boolean\n  | Array<JSONValue>\n  | { [value: string]: JSONValue };\n\nexport type PixelId = `${number}`;\nexport type Options = { eventID?: string };\n\n/**\n * reference: https://developers.facebook.com/docs/meta-pixel/reference#standard-events\n *\n * We determine if events are identical based on their ID and name. So, for an event to be deduplicated:\n * - In corresponding events, a Meta Pixel's eventID must match the Conversion API's event_id.\n * - In corresponding events, a Meta Pixel's event must match the Conversion API's event_name.\n *\n * reference: https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/customer-information-parameters\n */\nexport interface FBQ {\n  /**\n   * reference: https://stackoverflow.com/questions/62304291/sending-user-data-parameters-via-pixel\n   *\n   * Call init the normal default way first:\n   * `fbq('init', 'XXXXX')`\n   *\n   * And at a later point in time, when you have obtained additional user data, you can call init\n   * again basically enriching the already running fbq instance with additional data:\n   * `fbq('init', 'XXXXX', { external_id: 1234, em: 'abc@abc.com' } )`\n   *\n   * Only caveat is that you have to send an event after this additional init call, otherwise the\n   * provided data will not be sent to Facebook.\n   */\n  fbq(type: 'init', pixelId: PixelId, parameters?: MatchingParameters): void;\n\n  /** Enable Manual Only mode. (value = false) */\n  fbq(type: 'set', key: 'autoConfig', value: boolean, pixelId: PixelId): void;\n\n  fbq<T extends keyof StandardEvents>(\n    type: 'track',\n    event: T,\n    properties?: StandardEvents[T] & ObjectProperties,\n    options?: Options\n  ): void;\n\n  fbq(\n    type: 'trackCustom',\n    event: string,\n    properties?: Record<string, JSONValue> & ObjectProperties,\n    options?: Options\n  ): void;\n\n  /** https://developers.facebook.com/docs/meta-pixel/guides/track-multiple-events/ */\n  fbq<T extends keyof StandardEvents>(\n    type: 'trackSingle',\n    pixelId: PixelId,\n    event: T,\n    properties?: StandardEvents[T] & ObjectProperties,\n    options?: Options\n  ): void;\n\n  /** https://developers.facebook.com/docs/meta-pixel/guides/track-multiple-events/ */\n  fbq(\n    type: 'trackSingleCustom',\n    pixelId: PixelId,\n    event: string,\n    properties?: Record<string, JSONValue> & ObjectProperties,\n    options?: Options\n  ): void;\n}\n\n/**\n * Please download this CSV filefor examples of properly normalized and hashed data for the\n * parameters below.\n */\nexport function normalize(parameters: MatchingParameters): MatchingParameters {\n  return {\n    ...parameters,\n    em: parameters.em?.toLowerCase().trim(),\n    ph: parameters.ph?.replace(/[-+()\\s]/g, '').replace(/^0+/, ''),\n    zp: parameters.zp?.split('-').at(0)?.trim(),\n    fn: parameters.fn?.toLowerCase().trim(),\n    ln: parameters.ln?.toLowerCase().trim(),\n    ct: parameters.ct?.toLowerCase().replace(/[s/-]/g, '').trim(),\n    st: parameters.st\n      ?.toLowerCase()\n      .replace(/[s/-/,.]/g, '')\n      .trim(),\n    country: parameters.country?.toLowerCase().replace(/[s/-]/g, '').trim(),\n  };\n}\n\nexport function mapItems(items?: Item[]): ObjectProperties {\n  if (!items) return {};\n  const categories = Array.from(new Set(items.map((i) => i.item_category).filter(Boolean)));\n  const contents: Content[] = items.map(\n    ({ item_id, quantity, price, item_name, item_brand, item_category, ..._others }) => ({\n      id: item_id,\n      quantity: quantity ?? 1,\n      item_price: price,\n      title: item_name,\n      brand: item_brand,\n      category: item_category,\n    })\n  );\n\n  return {\n    content_category: categories.length === 1 ? categories.at(0) : undefined,\n    contents,\n    content_ids: contents.map((c) => c.id),\n    num_items: items.reduce((acc, i) => acc + (i.quantity ?? 1), 0),\n  };\n}\n\ntype Mapped<F extends keyof StandardEvents> = ['track', F, StandardEvents[F] & ObjectProperties];\ntype Missed<F extends string> = ['trackCustom', F, Record<string, JSONValue> & ObjectProperties];\n\nexport function mapFBEvent<T extends EventName>(\n  name: TrackName<T>,\n  properties?: TrackProperties<T>\n): Mapped<keyof StandardEvents> | Missed<TrackName<T>> {\n  if (name === 'add_payment_info') {\n    const p = properties as TrackProperties<'add_payment_info'> | undefined;\n    return [\n      'track',\n      'AddPaymentInfo',\n      { currency: p?.currency, value: p?.value, ...mapItems(p?.items) },\n    ];\n  } else if (name === 'add_to_cart') {\n    const p = properties as TrackProperties<'add_to_cart'> | undefined;\n    return [\n      'track',\n      'AddToCart',\n      { currency: p?.currency, value: p?.value, ...mapItems(p?.items) },\n    ];\n  } else if (name === 'add_to_wishlist') {\n    const p = properties as TrackProperties<'add_to_wishlist'> | undefined;\n    return [\n      'track',\n      'AddToWishlist',\n      { currency: p?.currency, value: p?.value, ...mapItems(p?.items) },\n    ];\n  } else if (name === 'login') {\n    const p = properties as TrackProperties<'login'> | undefined;\n    return ['track', 'CompleteRegistration', { method: p?.method }];\n  } else if (name === 'contact') {\n    return ['track', 'Contact', {}];\n  } else if (name === 'customize_product') {\n    return ['track', 'CustomizeProduct', {}];\n  } else if (name === 'donate') {\n    return ['track', 'Donate', {}];\n  } else if (name === 'find_location') {\n    return ['track', 'FindLocation', {}];\n  } else if (name === 'begin_checkout') {\n    const p = properties as TrackProperties<'begin_checkout'> | undefined;\n    return [\n      'track',\n      'InitiateCheckout',\n      { currency: p?.currency, value: p?.value, ...mapItems(p?.items) },\n    ];\n  } else if (name === 'generate_lead') {\n    const p = properties as TrackProperties<'generate_lead'> | undefined;\n    return ['track', 'Lead', { currency: p?.currency, value: p?.value }];\n  } else if (name === 'purchase') {\n    const p = properties as TrackProperties<'purchase'> | undefined;\n    return [\n      'track',\n      'Purchase',\n      { currency: p?.currency ?? 'USD', value: p?.value ?? 0, ...mapItems(p?.items) },\n    ];\n  } else if (name === 'schedule') {\n    return ['track', 'Schedule', {}];\n  } else if (name === 'search') {\n    const p = properties as TrackProperties<'search'> | undefined;\n    return ['track', 'Search', { search_string: p?.search_term }];\n  } else if (name === 'trial_begin') {\n    const p = properties as TrackProperties<'trial_begin'> | undefined;\n    return ['track', 'StartTrial', { currency: p?.currency, value: p?.value }];\n  } else if (name === 'submit_application') {\n    return ['track', 'SubmitApplication', {}];\n  } else if (name === 'subscribe') {\n    const p = properties as TrackProperties<'subscribe'> | undefined;\n    return ['track', 'Subscribe', { currency: p?.currency, value: p?.value }];\n  } else if (name === 'view_item') {\n    const p = properties as TrackProperties<'view_item'> | undefined;\n    return [\n      'track',\n      'ViewContent',\n      { currency: p?.currency, value: p?.value, ...mapItems(p?.items) },\n    ];\n  } else {\n    return ['trackCustom', name, properties ?? {}];\n  }\n}\n"],"mappings":"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","names":[]}