Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@ import { defaultValues } from '@segment/actions-core'

declare global {
interface Window {
fbq: FBClient,
fbq: FBClient
_fbq: FBClient
clientParamBuilder: FBClientParamBuilder | undefined
}
}

export const destination: BrowserDestinationDefinition<Settings, { fbq: FBClient, clientParamBuilder: FBClientParamBuilder | undefined }> = {
export const destination: BrowserDestinationDefinition<
Settings,
{ fbq: FBClient; clientParamBuilder: FBClientParamBuilder | undefined }
> = {
name: 'Facebook Conversions Api Web',
slug: 'actions-facebook-conversions-api-web',
mode: 'device',
Expand All @@ -24,22 +27,25 @@ export const destination: BrowserDestinationDefinition<Settings, { fbq: FBClient
description: 'The Pixel ID associated with your Facebook Pixel.',
label: 'Pixel ID',
type: 'string',
required: true
required: true
},
disablePushState: {
description: "If set to true, prevents Facebook Pixel from sending PageView events on history state changes. Set to true if you want to trigger PageView events manually via the pageView Action.",
description:
'If set to true, prevents Facebook Pixel from sending PageView events on history state changes. Set to true if you want to trigger PageView events manually via the pageView Action.',
label: 'Disable Push State',
type: 'boolean',
default: false
},
disableAutoConfig: {
description: "Control whether Facebook’s Meta Pixel automatically collects additional page and button data to optimize ads and measurement. When this toggle is on, Auto Config is disabled and only basic pixel tracking will occur. Turning it off enables Auto Config, allowing the Pixel to automatically send page metadata and button interactions to improve ad delivery and reporting.",
description:
'Control whether Facebook’s Meta Pixel automatically collects additional page and button data to optimize ads and measurement. When this toggle is on, Auto Config is disabled and only basic pixel tracking will occur. Turning it off enables Auto Config, allowing the Pixel to automatically send page metadata and button interactions to improve ad delivery and reporting.',
label: 'Disable Auto Config',
type: 'boolean',
default: true
},
disableFirstPartyCookies: {
description: "Control whether Facebook’s Meta Pixel uses first-party cookies. When this toggle is on, first-party cookies are disabled, enhancing user privacy. Turning it off enables the use of first-party cookies for more accurate tracking.",
description:
'Control whether Facebook’s Meta Pixel uses first-party cookies. When this toggle is on, first-party cookies are disabled, enhancing user privacy. Turning it off enables the use of first-party cookies for more accurate tracking.',
label: 'Disable First Party Cookies',
type: 'boolean',
default: false
Expand All @@ -56,8 +62,8 @@ export const destination: BrowserDestinationDefinition<Settings, { fbq: FBClient
type: 'string',
required: true,
choices: [
{ label: 'LDU disabled', value: LDU.Disabled.key},
{ label: "LDU enabled - Use Meta Geolocation Logic", value: LDU.GeolocationLogic.key },
{ label: 'LDU disabled', value: LDU.Disabled.key },
{ label: 'LDU enabled - Use Meta Geolocation Logic', value: LDU.GeolocationLogic.key },
{ label: 'LDU enabled - California only', value: LDU.California.key },
{ label: 'LDU enabled - Colorado only', value: LDU.Colorado.key },
{ label: 'LDU enabled - Connecticut only', value: LDU.Connecticut.key },
Expand All @@ -69,12 +75,15 @@ export const destination: BrowserDestinationDefinition<Settings, { fbq: FBClient
{ label: 'LDU enabled - Nebraska only', value: LDU.Nebraska.key },
{ label: 'LDU enabled - New Hampshire only', value: LDU.NewHampshire.key },
{ label: 'LDU enabled - New Jersey only', value: LDU.NewJersey.key },
{ label: 'LDU enabled - Minnesota only', value: LDU.Minnesota.key }
{ label: 'LDU enabled - Minnesota only', value: LDU.Minnesota.key },
{ label: 'LDU enabled - Maryland only', value: LDU.Maryland.key },
{ label: 'LDU enabled - Rhode Island only', value: LDU.RhodeIsland.key }
],
default: LDU.Disabled.key
},
},
formatUserDataWithParamBuilder: {
description: 'If enabled, uses Facebook’s Parameter Builder library to help ensure that User Data values are properly formatted before being sent to Facebook.',
description:
'If enabled, uses Facebook’s Parameter Builder library to help ensure that User Data values are properly formatted before being sent to Facebook.',
label: 'Format User Data with Parameter Builder',
type: 'boolean',
default: true
Expand All @@ -84,8 +93,8 @@ export const destination: BrowserDestinationDefinition<Settings, { fbq: FBClient
const { formatUserDataWithParamBuilder } = settings
initScript(settings, analytics)
await deps.resolveWhen(() => typeof window.fbq === 'function', 100)
if(formatUserDataWithParamBuilder){
const script = `https://capi-automation.s3.us-east-2.amazonaws.com/public/client_js/capiParamBuilder/clientParamBuilder.bundle.js`
if (formatUserDataWithParamBuilder) {
const script = `https://unpkg.com/meta-capi-param-builder-clientjs/dist/clientParamBuilder.bundle.js`
await deps.loadScript(script)
Comment thread
joe-ayoub-segment marked this conversation as resolved.
Comment thread
joe-ayoub-segment marked this conversation as resolved.
await deps.resolveWhen(() => typeof window.clientParamBuilder === 'object', 100)
Comment thread
joe-ayoub-segment marked this conversation as resolved.
Comment on lines +96 to 99
}
Comment thread
joe-ayoub-segment marked this conversation as resolved.
Comment thread
joe-ayoub-segment marked this conversation as resolved.
Expand All @@ -99,27 +108,21 @@ export const destination: BrowserDestinationDefinition<Settings, { fbq: FBClient
name: 'AddPaymentInfo',
subscribe: 'event = "Payment Info Entered"',
partnerAction: 'send',
mapping:
{
mapping: {
...defaultValues(send.fields),
event_config: {
event_name: 'AddPaymentInfo',
show_fields: false
}
event_name: 'AddPaymentInfo',
show_fields: false
},
type: 'automatic'
},
{
name: 'AddToCart',
subscribe: 'event = "Product Added"',
partnerAction: 'send',
mapping:
{
mapping: {
...defaultValues(send.fields),
event_config: {
event_name: 'AddToCart',
show_fields: false
},
event_name: 'AddToCart',
show_fields: false,
contents: {
id: { '@path': '$.properties.product_id' },
quantity: { '@path': '$.properties.quantity' },
Expand All @@ -129,18 +132,15 @@ export const destination: BrowserDestinationDefinition<Settings, { fbq: FBClient
value: { '@path': '$.properties.price' }
},
type: 'automatic'
},
},
{
name: 'AddToWishlist',
subscribe: 'event = "Product Added To Wishlist"',
partnerAction: 'send',
mapping:
{
mapping: {
...defaultValues(send.fields),
event_config: {
event_name: 'AddToWishlist',
show_fields: false
},
event_name: 'AddToWishlist',
show_fields: false,
contents: {
id: { '@path': '$.properties.product_id' },
quantity: { '@path': '$.properties.quantity' },
Expand All @@ -155,27 +155,21 @@ export const destination: BrowserDestinationDefinition<Settings, { fbq: FBClient
name: 'CompleteRegistration',
subscribe: 'event = "Signed Up"',
partnerAction: 'send',
mapping:
{
mapping: {
...defaultValues(send.fields),
event_config: {
event_name: 'CompleteRegistration',
show_fields: false
}
event_name: 'CompleteRegistration',
show_fields: false
},
type: 'automatic'
},
},
{
name: 'InitiateCheckout',
subscribe: 'event = "Checkout Started"',
partnerAction: 'send',
mapping:
{
mapping: {
...defaultValues(send.fields),
event_config: {
event_name: 'InitiateCheckout',
show_fields: false
}
event_name: 'InitiateCheckout',
show_fields: false
},
type: 'automatic'
},
Expand All @@ -185,10 +179,8 @@ export const destination: BrowserDestinationDefinition<Settings, { fbq: FBClient
partnerAction: 'send',
mapping: {
...defaultValues(send.fields),
event_config: {
event_name: 'PageView',
show_fields: false
},
event_name: 'PageView',
show_fields: false,
content_name: { '@path': '$.name' },
content_category: { '@path': '$.category' }
},
Expand All @@ -198,14 +190,11 @@ export const destination: BrowserDestinationDefinition<Settings, { fbq: FBClient
name: 'Purchase',
subscribe: 'event = "Order Completed"',
partnerAction: 'send',
mapping:
{
mapping: {
...defaultValues(send.fields),
event_config: {
event_name: 'Purchase',
show_fields: false
},
value: { '@path': '$.properties.revenue' },
event_name: 'Purchase',
show_fields: false,
value: { '@path': '$.properties.revenue' },
custom_data: {
order_id: { '@path': '$.properties.order_id' }
}
Expand All @@ -216,13 +205,10 @@ export const destination: BrowserDestinationDefinition<Settings, { fbq: FBClient
name: 'Search',
subscribe: 'event = "Products Searched"',
partnerAction: 'send',
mapping:
{
mapping: {
...defaultValues(send.fields),
event_config: {
event_name: 'Search',
show_fields: false
},
event_name: 'Search',
show_fields: false,
contents: {
id: { '@path': '$.properties.product_id' },
quantity: { '@path': '$.properties.quantity' },
Expand All @@ -236,18 +222,15 @@ export const destination: BrowserDestinationDefinition<Settings, { fbq: FBClient
name: 'ViewContent',
subscribe: 'event = "Product Viewed"',
partnerAction: 'send',
mapping:
{
mapping: {
...defaultValues(send.fields),
event_config: {
event_name: 'ViewContent',
show_fields: false
},
event_name: 'ViewContent',
show_fields: false,
contents: {
id: { '@path': '$.properties.product_id' },
quantity: { '@path': '$.properties.quantity' },
item_price: { '@path': '$.properties.price' }
},
},
content_ids: { '@path': '$.properties.product_id' },
value: { '@path': '$.properties.price' }
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { content_ids } from '../fields'
import { formatFBEvent } from '../functions'
import { Payload } from '../generated-types'

describe('content_ids field', () => {
describe('field definition', () => {
it('is a multiple string field', () => {
expect(content_ids.type).toBe('string')
expect(content_ids.multiple).toBe(true)
})

// Regression guard: the field previously shipped a broken default that
// used the disabled Liquid `map` filter
// ({ '@liquid': "{{ properties.products | map: 'product_id' }}" }).
// That default threw / never resolved to an array, so content_ids was
// always dropped. We removed the default; customers configure it if
// needed. Do NOT reintroduce a default without verifying it resolves to
// an array of strings AND renders in the app mapping-editor UI.
it('has no default mapping', () => {
expect(content_ids.default).toBeUndefined()
})

it('is gated behind the relevant event dependencies', () => {
expect(content_ids.depends_on).toBeDefined()
})
})

describe('formatFBEvent handling of content_ids', () => {
it('passes a provided array of ids through', () => {
const payload: Partial<Payload> = {
event_name: 'ViewContent',
show_fields: true,
content_ids: ['SKU-ABC-123', 'SKU-XYZ-789']
}
Comment thread
joe-ayoub-segment marked this conversation as resolved.

const result = formatFBEvent(payload as Payload)

expect(result.content_ids).toEqual(['SKU-ABC-123', 'SKU-XYZ-789'])
})

it('omits content_ids when it is an empty array', () => {
const payload: Partial<Payload> = {
event_name: 'AddToCart',
show_fields: true,
content_ids: []
}

const result = formatFBEvent(payload as Payload)

expect(result).not.toHaveProperty('content_ids')
})

it('omits content_ids when it is absent', () => {
const payload: Partial<Payload> = {
event_name: 'Purchase',
show_fields: true,
value: 45.97
}

const result = formatFBEvent(payload as Payload)

expect(result).not.toHaveProperty('content_ids')
})
})
})
Original file line number Diff line number Diff line change
@@ -1,28 +1,55 @@
import { getDependenciesFor } from '../depends-on'

describe('depends-on getDependenciesFor', () => {
test('returns correct depends_on rules', () => {
test('multi-event field includes show_fields plus one condition per event', () => {
const result = getDependenciesFor('delivery_category')
expect(true).toBe(true)
expect(result.match).toBe('any')
expect(result.conditions).toEqual(
[
{
fieldKey: 'event_config.show_fields',
operator: 'is',
value: 'true'
},
{
fieldKey: 'event_config.event_name',
operator: 'is',
value: 'Purchase'
},
{
fieldKey: 'event_config.event_name',
operator: 'is',
value: 'InitiateCheckout'
}
]
)
})
expect(result.conditions).toEqual([
{
fieldKey: 'show_fields',
operator: 'is',
value: true
},
{
fieldKey: 'event_name',
operator: 'is',
value: 'Purchase'
},
{
fieldKey: 'event_name',
operator: 'is',
value: 'InitiateCheckout'
}
])
})

test('single-event field still includes its event condition', () => {
// status is relevant to exactly one event (CompleteRegistration); it must
// still gate on that event, not only on show_fields.
const result = getDependenciesFor('status')
expect(result.match).toBe('any')
expect(result.conditions).toEqual([
{ fieldKey: 'show_fields', operator: 'is', value: true },
{ fieldKey: 'event_name', operator: 'is', value: 'CompleteRegistration' }
])
})

test('custom_event_name gates on show_fields and the CustomEvent event', () => {
const result = getDependenciesFor('custom_event_name')
expect(result.conditions).toEqual([
{ fieldKey: 'show_fields', operator: 'is', value: true },
{ fieldKey: 'event_name', operator: 'is', value: 'CustomEvent' }
])
})

test('show_fields condition uses a boolean value, not the string "true"', () => {
const result = getDependenciesFor('status')
const showFieldsCondition = result.conditions.find((c) => 'fieldKey' in c && c.fieldKey === 'show_fields')
expect(showFieldsCondition).toEqual({ fieldKey: 'show_fields', operator: 'is', value: true })
})

test('unknown field returns only the show_fields condition', () => {
const result = getDependenciesFor('not_a_real_field')
expect(result.conditions).toEqual([{ fieldKey: 'show_fields', operator: 'is', value: true }])
})
})
Loading
Loading