Dynamic Ads enables you to show people ads based on their cross-device purchasing intent. You can collect signals of user intent from mobile apps and websites then use this data to build an audience to target prospective customers.
This describes how you can create an audience:
This document also covers:
Since September 2018, we do not support subtype
for custom audiences for websites, apps, engagement custom audiences, and audiences from offline conversion data. The one exception is that subtype
is still supported for engagement custom audiences for video.
To collect user signals, use App Events (for your mobile app) or Facebook Pixel (for your website):
For MobileFor WebsitesIf you have an app and you are only running ads on desktop, you should still install Facebook SDK. This helps to capture signals and expand your target audience.
You must add the following events to your app through Facebook SDK for iOS and Android:
Events | iOS Event | Android Event |
---|---|---|
Search |
|
|
View Content |
|
|
Add To Cart |
|
|
Purchase | // Send through logPurchase
|
|
All of these events should include a content type and a content id (or a JSON array of content ids).
Unlike the Facebook pixel, App Events has no product_catalog_id
parameter. Therefore you must make an association between your catalog and app with the external_event_sources
endpoint described below.
Sample Add To Cart event on iOS:
[FBSDKAppEvents logEvent:FBSDKAppEventNameAddedToCart valueToSum:54.23 parameters:@{ FBSDKAppEventParameterNameCurrency : @"USD", FBSDKAppEventParameterNameContentType : @"product", FBSDKAppEventParameterNameContentID : @"123456789" } ];
An example purchase event on iOS with two different items purchased with quantity:
[FBSDKAppEvents logPurchase:21.97 currency:@"USD" parameters:@{ FBSDKAppEventParameterNameContent : @"[{\"id\":\"1234\",\"quantity\":2},{\"id\":\"5678\",\"quantity\":1}]", FBSDKAppEventParameterNameContentType : @"product" } ];
An example purchase event on Android with two items purchased with quantity:
Bundle parameters = new Bundle(); parameters.putString(AppEventsConstants.EVENT_PARAM_CURRENCY, "USD"); parameters.putString(AppEventsConstants.EVENT_PARAM_CONTENT_TYPE, "product"); parameters.putString(AppEventsConstants.EVENT_PARAM_CONTENT, "[{\"id\":\"1234\",\"quantity\":2},{\"id\":\"5678\",\"quantity\":1}]"); logger.logEvent( AppEventsConstants.EVENT_NAME_PURCHASED, 21.97, parameters );
An example purchase event on Android with two items purchased:
Bundle parameters = new Bundle(); parameters.putString(AppEventsConstants.EVENT_PARAM_CURRENCY, "USD"); parameters.putString(AppEventsConstants.EVENT_PARAM_CONTENT_TYPE, "product"); parameters.putString(AppEventsConstants.EVENT_PARAM_CONTENT_ID, "[\"1234\",\"5678\"]"); logger.logEvent( AppEventsConstants.EVENT_NAME_PURCHASED, 21.97, parameters );
Note that either CONTENT_ID
or CONTENT
can be used with Dynamic Ads to report product IDs. CONTENT
param will allow you to provide additional information about the products.
To use Dynamic Ads with a mobile measurement partner (MMP), you should trigger required separate events as someone uses your app. The key interaction points you should track are when someone searches for products, views a product, adds something to a cart and purchases items. You should select the events at your MMP that correspond to the following standard Dynamic Ads events:
Event name | Description |
---|---|
| Someone searches for products. |
| When a person views a product. |
| Someone ads an item to the cart. |
| Person purchases one or more items. |
Also, you need two additional parameters for each of the events to be registered successfully as a valid Dynamic Ads event. These two parameters represent the id of the item being viewed, added to cart or purchased and whether the id is a product or a product group id. The additional parameters available are:
Field Name | Description |
---|---|
type: string | Either The retailer's product or product group id(s). This should be a string containing a JSON encoded array of ids. Use product ids if possible for more accurate targeting. |
type: string | Either A list of JSON object that contains the International Article Number (EAN) when applicable, or other product or content identifier(s) as well as quantities and prices of the products. |
type: string | Required. either |
type: string | Optional. The total value of the products |
type: string | Optional. The currency of the product or purchase amount |
It is advisable to send the _valueToSum
and fb_currency
parameters when a purchase is made.
The following events must be added to your website if applicable:
Search
ViewCategory
ViewContent
AddToCart
Purchase
These events should be sent with the following data parameters:
Field Name | Description |
---|---|
type: string or string[] | Either The retailer's product or product group id(s). Use product ids if possible for more accurate targeting. |
type: object[] | Either A list of JSON object that contains the retailer's product or product group id(s) as well as additional information about the products. id, quantity are the required fields. e.g. |
type: string | Required. Either |
type: string | Optional. A product catalog to be used. If this is supplied this will be the only catalog pixel fires will be associated with. If this is not supplied, the catalog(s) associated with your pixel will be used. See "Associate User Signals to Product Catalog" to learn more. |
More details on specifying events and parameters are under Remarketing Events, see Tag API documentation.
An example of Search
standard event is shown below. We recommend providing 5 to 10 items in content_ids
from your top search results.
<!-- Facebook Pixel Code --> <script> !function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod? n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n; n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0; t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window, document,'script','https://connect.facebook.net/en_US/fbevents.js'); // Insert Your Facebook Pixel ID below. fbq('init', '<FB_PIXEL_ID>'); fbq('track', 'PageView'); fbq('track', 'Search', { search_string: 'leather sandals', content_ids: ['1234', '2424', '1318', '6832'], // top 5-10 search results content_type: 'product' }); </script> <!-- End Facebook Pixel Code -->
An example of ViewCategory
event is shown below. We recommend providing 5 to 10 items in content_ids
from your top results. Note that ViewCategory
is not a standard event, thus the trackCustom
function is used.
<!-- Facebook Pixel Code --> <script> !function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod? n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n; n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0; t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window, document,'script','https://connect.facebook.net/en_US/fbevents.js'); // Insert Your Facebook Pixel ID below. fbq('init', '<FB_PIXEL_ID>'); fbq('track', 'PageView'); fbq('trackCustom', 'ViewCategory', { content_name: 'Really Fast Running Shoes', content_category: 'Apparel & Accessories > Shoes', content_ids: ['1234', '2424', '1318', '6832'], // top 5-10 results content_type: 'product' }); </script> <!-- End Facebook Pixel Code -->
An example of ViewContent
standard event is shown below. More details on pixel setup, see Facebook Pixel.
<!-- Facebook Pixel Code --> <script> !function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod? n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n; n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0; t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window, document,'script','https://connect.facebook.net/en_US/fbevents.js'); // Insert Your Facebook Pixel ID below. fbq('init', '<FB_PIXEL_ID>'); fbq('track', 'PageView'); fbq('track', 'ViewContent', { content_ids: ['1234'], content_type: 'product', value: 0.50, currency: 'USD' }); </script> <!-- End Facebook Pixel Code -->
An example of AddToCart
standard event depends on how your eCommerce platform handles adding an item to a cart. If it is done dynamically this should be placed in an onclick
event handler so it is triggered on the button click. If a separate page is loaded then the pixel event can be fired like normal.
<!-- Facebook Pixel Code --> <script> !function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod? n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n; n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0; t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window, document,'script','https://connect.facebook.net/en_US/fbevents.js'); // Insert Your Facebook Pixel ID below. fbq('init', '<FB_PIXEL_ID>'); fbq('track', 'PageView'); // If you have a separate add to cart page that is loaded. fbq('track', 'AddToCart', { content_ids: ['1234', '1853', '9386'], content_type: 'product', value: 3.50, currency: 'USD' }); </script> <!-- End Facebook Pixel Code -->
If the event needs to be fired on button click and there is no separate page that loads:
<!-- The below method uses jQuery, but that is not required --> <button id="addToCartButton">Add To Cart</button> <!-- Add event to the button's click handler --> <script type="text/javascript"> $( '#addToCartButton' ).click(function() { fbq('track', 'AddToCart', { content_ids: ['1234'], content_type: 'product', value: 2.99, currency: 'USD' }); }); </script>
An example of Purchase
standard event with two items with quantity:
<!-- Facebook Pixel Code --> <script> !function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod? n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n; n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0; t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window, document,'script','https://connect.facebook.net/en_US/fbevents.js'); // Insert Your Facebook Pixel ID below. fbq('init', '<FB_PIXEL_ID>'); fbq('track', 'PageView'); fbq('track', 'Purchase', { contents: [ {'id': '1234', 'quantity': 2}, {'id': '4642', 'quantity': 1} ], content_type: 'product', value: 21.97, currency: 'USD' }); </script> <!-- End Facebook Pixel Code -->
An example of Purchase
standard event with two items:
<!-- Facebook Pixel Code --> <script> !function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod? n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n; n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0; t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window, document,'script','https://connect.facebook.net/en_US/fbevents.js'); // Insert Your Facebook Pixel ID below. fbq('init', '<FB_PIXEL_ID>'); fbq('track', 'PageView'); fbq('track', 'Purchase', { content_ids: ['1234', '4642'], content_type: 'product', value: 21.97, currency: 'USD' }); </script> <!-- End Facebook Pixel Code -->
content_type
(fb_content_type
for mobile)If the page is about a specific SKU (specific size, color, etc), then use product
for content_type
and pass the product IDs (id
column in the Product Feed) in content_ids
. ALL AddToCart
and Purchase
events should use content_type=product
because people buy specific products. People don't buy an amorphous shirt of indeterminate size and color; they buy a specific shirt with a specific size and color.
If the page is about a group of related products that vary by size, color, etc but belong to the same product group, use product_group
and pass the product group IDs (item_group_id
column in the Product Feed) in content_ids
. A common use case is a ViewContent
page where the user has not chosen a size yet. Do NOT use product_group
with AddToCart
or Purchase
.
It's important that the content_type
matches the type of id(s) included in the content_ids
or contents
parameter.
Passing the specific product IDs (content_type=product
) allows Facebook to recommend more relevant products because it knows which specific variant (size, color, etc) the user expressed interest in. Note that what content_type
you pass does not impact the recommendation logic. We will always show products (not product groups), even if content_type=product_group
.
Next, you need to associate your event sources with each of your product catalogs so that Facebook can get this data and display the correct product in an ad. You can do this by visiting your Business Manager's Catalog Page and clicking the Associate Event Source
button. Make sure to select the app and pixel that will be receiving the Dynamic Ads events.
Alternatively, you can make a HTTP POST
with a list of external event sources as a UTF-8 encoded query string parameters:
use FacebookAds\Object\ProductCatalog;
$product_catalog = new ProductCatalog(<PRODUCT_CATALOG_ID>);
$product_catalog->createExternalEventSource(array(), array(
'external_event_sources' => array(
<PIXEL_ID>,
<APP_ID>,
),
));
from facebookads.adobjects.productcatalog import ProductCatalog
product_catalog = ProductCatalog(<PRODUCT_CATALOG_ID>)
product_catalog.add_external_event_sources([
<PIXEL_ID>,
<APP_ID>,
])
curl \
-F 'external_event_sources=["<PIXEL_ID>","<APP_ID>"]' \
-F 'access_token=<ACCESS_TOKEN>' \
https://graph.facebook.com/v2.11/<PRODUCT_CATALOG_ID>/external_event_sources
You need to have permissions on the catalog, the pixel, and the app as well as the business.
When you make the API call, specify the following parameters:
Field Name | Description |
---|---|
type: Array of App and Pixel IDs to add | Required. App and Pixel IDs to associate, as a UTF-8 encoded query string parameters if you make a |
The next step is to build Product Audiences, based on activity on your mobile apps and website. You can choose what events to use and target ads using your Product Audiences.
For standard app events, the audience will be aggregated under the Ads Pixel event names:
Search
ViewContent
AddToCart
Purchase
Use these event names in your audience rules, even if it includes users on Android and iOS.
Create a Product Audience by making an HTTP POST
call to:
https://graph.facebook.com/<API_VERSION>/act_<AD_ACCOUNT_ID>/product_audiences
Specify the following parameters:
Field Name | Description |
---|---|
type: string | Required. The name of the audience |
type: string | Optional. A description of the audience |
type: numeric string | Required. The Product Set to target with this audience |
type: JSON object | Required. A set of events to target. At least one inclusion is required. Each inclusion should have exactly one event |
type: int | Required. The number of seconds to keep the person in the audience |
type: object[] | Required. Website Custom Audience Rule referencing one |
type: JSON object | Optional. Events for which a person should be excluded from targeting. For exclusions, a person with these events will be excluded from targeting if the event has happened on any product in the same product group i.e products that have the same item_group_id in the product feed. E.g. Product audience is set to include |
type: int | Required, if exclusion is specified. The number seconds to retain the exclusion |
type: object[] | Required, if exclusion is specified. Website Custom Audience Rule referencing one |
Each rule must include event
with operator eq
either as a top-level rule or as part of a top-level and
rule.
If the same event
is used in both inclusions and exclusions, any additional parameter checks must be exactly the same.
To create an audience targeting people that viewed or added products to a cart, but didn't finish the purchase, you can use the following example:
curl -X POST \
-F 'name="Test Product Audience"' \
-F 'product_set_id="<PRODUCT_SET_ID>"' \
-F 'inclusions=[
{
"retention_seconds": 86400,
"rule": {
"event": {
"eq": "AddToCart"
}
}
},
{
"retention_seconds": 72000,
"rule": {
"event": {
"eq": "ViewContent"
}
}
}
]' \
-F 'exclusions=[
{
"retention_seconds": 172800,
"rule": {
"event": {
"eq": "Purchase"
}
}
}
]' \
-F 'access_token=<ACCESS_TOKEN>' \
https://graph.facebook.com/v5.0/act_<AD_ACCOUNT_ID>/product_audiences
If you want target people that viewed a product on the web with iPhone, but haven't purchased on any device, create the following audience below.
This assumes that you include a userAgent
parameter in your Facebook pixel:
curl -X POST \
-F 'name="Test Iphone Product Audience"' \
-F 'product_set_id="<PRODUCT_SET_ID>"' \
-F 'inclusions=[
{
"retention_seconds": 86400,
"rule": {
"and": [
{
"event": {
"eq": "AddToCart"
}
},
{
"userAgent": {
"i_contains": "iPhone"
}
}
]
}
}
]' \
-F 'exclusions=[
{
"retention_seconds": 172800,
"rule": {
"event": {
"eq": "Purchase"
}
}
}
]' \
-F 'access_token=<ACCESS_TOKEN>' \
https://graph.facebook.com/v5.0/act_<AD_ACCOUNT_ID>/product_audiences
Once you create a product audience, you can retrieve it with Custom Audiences API. See Custom Audience Creating. You can get the original parameters used for audience creation with the data_source
parameter.
Product Audience is a specific type of Custom Audience that's dynamically generated from product events. The act_{AD_ACCOUNT_ID}/product_audiences
endpoint is a special POST endpoint to construct these audiences.
Example to retrieve Custom Audience:
Example to retrieve a specific Product Audience:
use FacebookAds\Object\ProductAudience;
$product_audience = new ProductAudience(<PRODUCT_AUDIENCE_ID>);
$product_audience->read();
from facebookads.objects import ProductAudience
product_audience = ProductAudience(<PRODUCT_AUDIENCE_ID>)
product_audience.remote_read()
CustomAudience customAudience2 = new CustomAudience(<PRODUCT_AUDIENCE_ID>, context).get()
.execute();
curl -G \
-d 'access_token=<ACCESS_TOKEN>' \
https://graph.facebook.com/v2.11/<PRODUCT_AUDIENCE_ID>
The video below walks through common issues found when setting up the pixel, app events, and catalog. It also features tools you can use to debug.