Dynamic Ads - Create Ads

Dynamic Ads enables you to create Link Ads that render ads and target to the right audiences based on a set of products.

In this document we describe:

Finally, you can preview your ads, fetch ad statistics and comments.

Prerequisites

To create a Dynamic Ads campaign, you need:

  • A Facebook Page representing the advertiser, and optionally an Instagram Account if running this campaign on Instagram.
  • An Ad Account with registered payment information.
  • An Audience available in your ad account.
  • A Catalog, such as a product catalog available in your Business Manager account.

Step 1. Create a Campaign

See Ad Campaign to about create this object.

Dynamic Ads campaigns must have PRODUCT_CATALOG_SALES, WEBSITE_CONVERSIONS, LINK_CLICKS or APP_INSTALLS objective.

use FacebookAds\Object\Campaign;
use FacebookAds\Object\Fields\CampaignFields;
use FacebookAds\Object\Values\CampaignObjectiveValues;

$campaign = new Campaign(null, 'act_<AD_ACCOUNT_ID>');
$campaign->setData(array(
  CampaignFields::NAME => 'Product Catalog Sales Campaign',
  CampaignFields::OBJECTIVE => CampaignObjectiveValues::PRODUCT_CATALOG_SALES,
  CampaignFields::PROMOTED_OBJECT => array(
    'product_catalog_id' => <PRODUCT_CATALOG_ID>,
  ),
));

$campaign->create(array(
  Campaign::STATUS_PARAM_NAME => Campaign::STATUS_PAUSED,
));
from facebookads.adobjects.campaign import Campaign

campaign = Campaign(parent_id='act_<AD_ACCOUNT_ID>')
campaign[Campaign.Field.name] = 'Product Catalog Sales Campaign'
objective = Campaign.Objective.product_catalog_sales
campaign[Campaign.Field.objective] = objective
campaign[Campaign.Field.promoted_object] = {
    'product_catalog_id': <PRODUCT_CATALOG_ID>,
}

campaign.remote_create(params={
    'status': Campaign.Status.paused,
})
Campaign campaign = new AdAccount(act_<AD_ACCOUNT_ID>, context).createCampaign()
  .setName("Product Catalog Sales Campaign Group")
  .setObjective(Campaign.EnumObjective.VALUE_PRODUCT_CATALOG_SALES)
  .setPromotedObject("{\"product_catalog_id\":\"" + <PRODUCT_CATALOG_ID> + "\"}")
  .setStatus(Campaign.EnumStatus.VALUE_PAUSED)
  .execute();
String campaign_id = campaign.getId();
curl \
  -F 'name=Product Catalog Sales Campaign' \
  -F 'objective=PRODUCT_CATALOG_SALES' \
  -F 'promoted_object={"product_catalog_id":"<PRODUCT_CATALOG_ID>"}' \
  -F 'status=PAUSED' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/campaigns

Step 2. Create an Ad Set

Related Topics

In this section, you'll learn how to create an ad set for:

For Dynamic Ads, you must specify product_set_id in promoted_object for your ad set level to promote products from that product set.

In addition, you can also define your own conversion event for that product set by specifying custom_event_type in promoted_object when the optimization_goal is OFFSITE_CONVERSIONS. This targets your ads to people who performed that event in your app or site.

For example, if you set this to ADD_TO_CART, it means Add to Cart event is the conversion event. By default custom_event_type is set to PURCHASE. Learn more about standard events and values for custom_event_type at Facebook Pixel, Conversion Tracking.

If you want to optimize for offsite conversions, including conversions from both app events and Facebook pixel, and to be billed on impressions:

  • Set the optimization_goal to OFFSITE_CONVERSIONS and
  • Set the billing_event to IMPRESSIONS.

Although the default optimization_goal for dynamic ads is set to LINK_CLICKS, we recommend using OFFSITE_CONVERSIONS. More details on valid optimization_goal and billing_event combinations can be found Validation Best Practices, Objectives and optimization_goal.

An example of creating an ad set that is billed on IMPRESSIONS and optimizes for OFFSITE_CONVERSIONS:

use FacebookAds\Object\AdSet;
use FacebookAds\Object\Fields\AdSetFields;
use FacebookAds\Object\Fields\TargetingFields;
use FacebookAds\Object\Values\AdSetBillingEventValues;
use FacebookAds\Object\Values\AdSetOptimizationGoalValues;

$adset = new AdSet(null, 'act_<AD_ACCOUNT_ID>');

$adset->setData(array(
  AdSetFields::NAME => 'Product Catalog Sales Adset',
  AdSetFields::BID_AMOUNT => 3000,
  AdSetFields::BILLING_EVENT => AdSetBillingEventValues::IMPRESSIONS,
  AdSetFields::OPTIMIZATION_GOAL =>
    AdSetOptimizationGoalValues::OFFSITE_CONVERSIONS,
  AdSetFields::DAILY_BUDGET => 15000,
  AdSetFields::CAMPAIGN_ID => <CAMPAIGN_ID>,
  AdSetFields::TARGETING => array(
    TargetingFields::GEO_LOCATIONS => array(
      'countries' => array('US'),
    ),
    TargetingFields::DYNAMIC_AUDIENCE_IDS => array(<DYNAMIC_AUDIENCE_ID>),
  ),
  AdSetFields::PROMOTED_OBJECT => array(
    'product_set_id' => <PRODUCT_SET_ID>,
  ),
));

$adset->create(array(
  AdSet::STATUS_PARAM_NAME => AdSet::STATUS_PAUSED,
));
from facebookads.adobjects.adset import AdSet
from facebookads.adobjects.targeting import Targeting

adset = AdSet(parent_id=ad_account_id)
adset[AdSet.Field.name] = 'Product Catalog Sales Adset'
adset[AdSet.Field.bid_amount] = 3000
adset[AdSet.Field.billing_event] = AdSet.BillingEvent.impressions
adset[AdSet.Field.optimization_goal] = \
    AdSet.OptimizationGoal.offsite_conversions
adset[AdSet.Field.daily_budget] = 15000
adset[AdSet.Field.campaign_id] = campaign_id
adset[AdSet.Field.targeting] = {
    Targeting.Field.geo_locations: {
        Targeting.Field.countries: ['US'],
    },
    Targeting.Field.dynamic_audience_ids: [
        dynamic_audience_id,
    ],
}
adset[AdSet.Field.promoted_object] = {
    'product_set_id': product_set_id,
}

adset.remote_create()
AdSet adSet = new AdAccount(act_<AD_ACCOUNT_ID>, context).createAdSet()
  .setName("Product Catalog Sales Adset")
  .setBidAmount(3000L)
  .setBillingEvent(AdSet.EnumBillingEvent.VALUE_IMPRESSIONS)
  .setOptimizationGoal(AdSet.EnumOptimizationGoal.VALUE_OFFSITE_CONVERSIONS)
  .setDailyBudget(15000L)
  .setCampaignId(<CAMPAIGN_ID>)
  .setTargeting(
    new Targeting()
      .setFieldDynamicAudienceIds(Arrays.asList(<DYNAMIC_AUDIENCE_ID>))
      .setFieldGeoLocations(
        new TargetingGeoLocation()
          .setFieldCountries(Arrays.asList("US"))
      )
  )
  .setPromotedObject("{\"product_set_id\":\"" + <PRODUCT_SET_ID> + "\"}")
  .setStatus(AdSet.EnumStatus.VALUE_PAUSED)
  .execute();
String ad_set_id = adSet.getId();
curl \
  -F 'name=Product Catalog Sales Adset' \
  -F 'bid_amount=3000' \
  -F 'billing_event=IMPRESSIONS' \
  -F 'optimization_goal=OFFSITE_CONVERSIONS' \
  -F 'daily_budget=15000' \
  -F 'campaign_id=<CAMPAIGN_ID>' \
  -F 'targeting={ 
    "geo_locations": {"countries":["US"]}, 
    "dynamic_audience_ids": ["<DYNAMIC_AUDIENCE_ID>"] 
  }' \
  -F 'promoted_object={"product_set_id":"<PRODUCT_SET_ID>"}' \
  -F 'status=PAUSED' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/adsets

The DYNAMIC_AUDIENCE_ID refers to a Product Audience.

Optionally, you can omit dynamic_audience_ids from the call and instead send the behavioral targeting information as part of:

  • product_audience_specs or
  • excluded_product_audience_specs parameters.

These specs are defined by the same parameters you use to create a Product Audience:

Field Name Description Type Required

product_set_id

The Product Set to target with this audience

numeric string

Yes

inclusions

A set of events to target. At least one inclusion is required. Each inclusion should have exactly one event', 'JSON object

JSON object

Yes

inclusions.retention_seconds

The number of seconds to keep the person in the audience

int

Yes

inclusions.rule

Website Custom Audience Rule referencing one event

object[]

Yes

exclusions

A set of events that remove a person from targeting

JSON object

No

exclusions.retention_seconds

The number seconds to retain the exclusion

int

Yes if exclusion is specified

exclusions.rule

Website Custom Audience Rule referencing one event

object[]

Yes if exclusion is specified

Each rule must include event with operator eq either as a top-level rule or as part of a top-level and rule.


Retargeting

In this example, we target people that viewed products in the last 3-5 days, but have not purchased. The ads placements are on mobile feed and audience network. Create this audience:

use FacebookAds\Object\AdSet;
use FacebookAds\Object\Fields\AdSetFields;
use FacebookAds\Object\Fields\TargetingFields;
use FacebookAds\Object\Values\AdSetBillingEventValues;
use FacebookAds\Object\Values\AdSetOptimizationGoalValues;

$adset = new AdSet(null, 'act_<AD_ACCOUNT_ID>');

$adset->setData(array(
  AdSetFields::NAME => 'Product Catalog Sales Adset',
  AdSetFields::BID_AMOUNT => 3000,
  AdSetFields::BILLING_EVENT => AdSetBillingEventValues::LINK_CLICKS,
  AdSetFields::OPTIMIZATION_GOAL => AdSetOptimizationGoalValues::LINK_CLICKS,
  AdSetFields::DAILY_BUDGET => 15000,
  AdSetFields::CAMPAIGN_ID => <CAMPAIGN_ID>,
  AdSetFields::TARGETING => array(
    TargetingFields::PUBLISHER_PLATFORMS => array(
      'facebook',
      'audience_network',
    ),
    TargetingFields::DEVICE_PLATFORMS => array('mobile'),
    TargetingFields::GEO_LOCATIONS => array(
      'countries' => array('US'),
    ),
    TargetingFields::PRODUCT_AUDIENCE_SPECS => array(array(
      'product_set_id' => <PRODUCT_SET_ID>,
      'inclusions' => array(array(
        'retention_seconds' => 432000,
        'rule' =>  array('event' => array('eq' => 'ViewContent')),
      )),
      'exclusions' => array(array(
        'retention_seconds' => 432000,
        'rule' =>  array('event' => array('eq' => 'Purchase')),
      )),
    )),
    TargetingFields::EXCLUDED_PRODUCT_AUDIENCE_SPECS => array(array(
      'product_set_id' => <PRODUCT_SET_ID>,
      'inclusions' => array(array(
        'retention_seconds' => 259200,
        'rule' =>  array('event' => array('eq' => 'ViewContent')),
      )),
    )),
  ),
  AdSetFields::PROMOTED_OBJECT => array(
    'product_set_id' => <PRODUCT_SET_ID>,
  ),
));

$adset->create(array(
  AdSet::STATUS_PARAM_NAME => AdSet::STATUS_PAUSED,
));
from facebookads.adobjects.adset import AdSet
from facebookads.adobjects.targeting import Targeting

adset = AdSet(parent_id='act_<AD_ACCOUNT_ID>')
adset[AdSet.Field.name] = 'Product Catalog Sales Adset'
adset[AdSet.Field.bid_amount] = 3000
adset[AdSet.Field.billing_event] = AdSet.BillingEvent.link_clicks
adset[AdSet.Field.optimization_goal] = AdSet.OptimizationGoal.link_clicks
adset[AdSet.Field.daily_budget] = 15000
adset[AdSet.Field.campaign_id] = <CAMPAIGN_ID>
adset[AdSet.Field.targeting] = {
    Targeting.Field.publisher_platforms: ['facebook', 'audience_network'],
    Targeting.Field.device_platforms: ['mobile'],
    Targeting.Field.geo_locations: {
        Targeting.Field.countries: ['US'],
    },
    Targeting.Field.product_audience_specs: [
        {
            'product_set_id': <PRODUCT_SET_ID>,
            'inclusions': [
                {
                    'retention_seconds': 432000,
                    'rule': {
                        'event': {
                            'eq': 'ViewContent',
                        },
                    },
                },
            ],
            'exclusions': [
                {
                    'retention_seconds': 259200,
                    'rule': {
                        'event': {
                            'eq': 'Purchase',
                        },
                    },
                },
            ],
        },
    ],
    Targeting.Field.excluded_product_audience_specs: [
        {
            'product_set_id': <PRODUCT_SET_ID>,
            'inclusions': [
                {
                    'retention_seconds': 259200,
                    'rule': {
                        'event': {
                            'eq': 'ViewContent',
                        },
                    },
                },
            ],
        },
    ],
}
adset[AdSet.Field.promoted_object] = {
    'product_set_id': <PRODUCT_SET_ID>,
}

adset.remote_create()
AdSet adSet = new AdAccount(act_<AD_ACCOUNT_ID>, context).createAdSet()
  .setName("Product Catalog Sales Adset")
  .setBidAmount(3000L)
  .setBillingEvent(AdSet.EnumBillingEvent.VALUE_LINK_CLICKS)
  .setOptimizationGoal(AdSet.EnumOptimizationGoal.VALUE_LINK_CLICKS)
  .setDailyBudget(15000L)
  .setCampaignId(<CAMPAIGN_ID>)
  .setTargeting(
    new Targeting()
      .setFieldDevicePlatforms(Arrays.asList(Targeting.EnumDevicePlatforms.VALUE_MOBILE))
      .setFieldExcludedProductAudienceSpecs(Arrays.asList(
        new TargetingProductAudienceSpec()
          .setFieldInclusions(Arrays.asList(
            new TargetingProductAudienceSubSpec()
              .setFieldRetentionSeconds("259200")
              .setFieldRule("{\"event\":{\"eq\":\"ViewContent\"}}")
          ))
          .setFieldProductSetId(<PRODUCT_SET_ID>)
      ))
      .setFieldGeoLocations(
        new TargetingGeoLocation()
          .setFieldCountries(Arrays.asList("US"))
      )
      .setFieldProductAudienceSpecs(Arrays.asList(
        new TargetingProductAudienceSpec()
          .setFieldExclusions(Arrays.asList(
            new TargetingProductAudienceSubSpec()
              .setFieldRetentionSeconds("432000")
              .setFieldRule("{\"event\":{\"eq\":\"Purchase\"}}")
          ))
          .setFieldInclusions(Arrays.asList(
            new TargetingProductAudienceSubSpec()
              .setFieldRetentionSeconds("432000")
              .setFieldRule("{\"event\":{\"eq\":\"ViewContent\"}}")
          ))
          .setFieldProductSetId(<PRODUCT_SET_ID>)
      ))
      .setFieldPublisherPlatforms(Arrays.asList("facebook", "audience_network"))
  )
  .setPromotedObject("{\"product_set_id\":\"" + <PRODUCT_SET_ID> + "\"}")
  .setStatus(AdSet.EnumStatus.VALUE_PAUSED)
  .execute();
String ad_set_id = adSet.getId();
curl \
  -F 'name=Product Catalog Sales Adset' \
  -F 'bid_amount=3000' \
  -F 'billing_event=LINK_CLICKS' \
  -F 'optimization_goal=LINK_CLICKS' \
  -F 'daily_budget=15000' \
  -F 'campaign_id=<CAMPAIGN_ID>' \
  -F 'targeting={ 
    "publisher_platforms": ["facebook","audience_network"], 
    "device_platforms": ["mobile"], 
    "geo_locations": {"countries":["US"]}, 
    "product_audience_specs": [ 
      { 
        "product_set_id": "<PRODUCT_SET_ID>", 
        "inclusions": [{"retention_seconds":432000,"rule":{"event":{"eq":"ViewContent"}}}], 
        "exclusions": [{"retention_seconds":432000,"rule":{"event":{"eq":"Purchase"}}}] 
      } 
    ], 
    "excluded_product_audience_specs": [ 
      { 
        "product_set_id": "<PRODUCT_SET_ID>", 
        "inclusions": [{"retention_seconds":259200,"rule":{"event":{"eq":"ViewContent"}}}] 
      } 
    ] 
  }' \
  -F 'promoted_object={"product_set_id":"<PRODUCT_SET_ID>"}' \
  -F 'status=PAUSED' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/adsets

Cross-Sell or Upsell

Example for advertising products that the user has not looked at:

curl \
-F 'name=Case 1 Adset' \
-F 'bid_amount=3000' \
-F 'billing_event=IMPRESSIONS' \
-F 'status=ACTIVE' \
-F 'daily_budget=15000' \
-F 'campaign_id=<CAMPAIGN_ID>' \
-F 'targeting= { \
            "geo_locations": { \
            "countries":["US"], \
             }, \
            "interests":[ \
                {"id":6003397425735,"name":"Tennis"}, \
            ], \
        }' \
-F 'promoted_object={"product_set_id”:<PRODUCT_SET_ID>}' \
-F 'access_token=<ACCESS_TOKEN>’ \
https://graph.facebook.com/<API_VERSION>/act_<ACCOUNT_ID>/adsets

To cross-sell between product sets:

  • Provide the product audience with event rules related to product set A and
  • Show products from product set B in the ad by setting the product_set_id to product set B at the ad creative level.

For example, a business wants to increase the sale of handbags in {PRODUCT_SET_1} by targeting an ad to existing users who have shown interest in shoes that belong in {PRODUCT_SET_2}.

Set the product_set_id in product_audience_specs to {PRODUCT_SET_2} or shoes. and the product_set_id in promoted_object to {PRODUCT_SET_1} or handbags:

use FacebookAds\Object\AdSet;
use FacebookAds\Object\Fields\AdSetFields;
use FacebookAds\Object\Fields\TargetingFields;
use FacebookAds\Object\Values\AdSetBillingEventValues;
use FacebookAds\Object\Values\AdSetOptimizationGoalValues;

$adset = new AdSet(null, 'act_<AD_ACCOUNT_ID>');

$adset->setData(array(
  AdSetFields::NAME => 'My cross sell ad set',
  AdSetFields::BID_AMOUNT => 3000,
  AdSetFields::BILLING_EVENT => AdSetBillingEventValues::LINK_CLICKS,
  AdSetFields::OPTIMIZATION_GOAL => AdSetOptimizationGoalValues::LINK_CLICKS,
  AdSetFields::DAILY_BUDGET => 15000,
  AdSetFields::CAMPAIGN_ID => <CAMPAIGN_ID>,
  AdSetFields::TARGETING => array(
    TargetingFields::GEO_LOCATIONS => array(
      'countries' => array('US'),
    ),
    TargetingFields::PRODUCT_AUDIENCE_SPECS => array(array(
      'product_set_id' => <PRODUCT_SET_2_ID>,
      'inclusions' => array(array(
        'retention_seconds' => 432000,
        'rule' =>  array('event' => array('eq' => 'ViewContent')),
      )),
      'exclusions' => array(array(
        'retention_seconds' => 432000,
        'rule' =>  array('event' => array('eq' => 'Purchase')),
      )),
    )),
    TargetingFields::EXCLUDED_PRODUCT_AUDIENCE_SPECS => array(array(
      'product_set_id' => <PRODUCT_SET_2_ID>,
      'inclusions' => array(array(
        'retention_seconds' => 259200,
        'rule' =>  array('event' => array('eq' => 'ViewContent')),
      )),
    )),
  ),
  AdSetFields::PROMOTED_OBJECT => array(
    'product_set_id' => <PRODUCT_SET_1_ID>,
  ),
));

$adset->create(array(
  AdSet::STATUS_PARAM_NAME => AdSet::STATUS_PAUSED,
));
from facebookads.adobjects.adset import AdSet
from facebookads.adobjects.targeting import Targeting

adset = AdSet(parent_id='act_<AD_ACCOUNT_ID>')
adset[AdSet.Field.name] = 'My cross sell ad set'
adset[AdSet.Field.bid_amount] = 3000
adset[AdSet.Field.billing_event] = 'LINK_CLICKS'
adset[AdSet.Field.optimization_goal] = 'LINK_CLICKS'
adset[AdSet.Field.daily_budget] = 15000
adset[AdSet.Field.campaign_id] = <CAMPAIGN_ID>
adset[AdSet.Field.targeting] = {
    Targeting.Field.geo_locations: {
        Targeting.Field.countries: ['US'],
    },
    Targeting.Field.product_audience_specs: [
        {
            'product_set_id': <PRODUCT_SET_ID_2>,
            'inclusions': [
                {
                    'retention_seconds': 432000,
                    'rule': {'event': {'eq': 'ViewContent'}},
                },
            ],
            'exclusions': [
                {
                    'retention_seconds': 432000,
                    'rule': {'event': {'eq': 'Purchase'}},
                },
            ],
        },
    ],
    Targeting.Field.excluded_product_audience_specs: [
        {
            'product_set_id': <PRODUCT_SET_ID_2>,
            'inclusions': [
                {
                    'retention_seconds': 259200,
                    'rule': {'event': {'eq': 'ViewContent'}},
                },
            ],
        },
    ],
}
adset[AdSet.Field.promoted_object] = {
    'product_set_id': <PRODUCT_SET_ID_1>,
}

adset.remote_create(params={
    'status': AdSet.Status.paused,
})
AdSet adSet = new AdAccount(act_<AD_ACCOUNT_ID>, context).createAdSet()
  .setName("My cross sell ad set")
  .setBidAmount(3000L)
  .setBillingEvent(AdSet.EnumBillingEvent.VALUE_LINK_CLICKS)
  .setOptimizationGoal(AdSet.EnumOptimizationGoal.VALUE_LINK_CLICKS)
  .setDailyBudget(15000L)
  .setCampaignId(<CAMPAIGN_ID>)
  .setTargeting(
    new Targeting()
      .setFieldExcludedProductAudienceSpecs(Arrays.asList(
        new TargetingProductAudienceSpec()
          .setFieldInclusions(Arrays.asList(
            new TargetingProductAudienceSubSpec()
              .setFieldRetentionSeconds("259200")
              .setFieldRule("{\"event\":{\"eq\":\"ViewContent\"}}")
          ))
          .setFieldProductSetId(<PRODUCT_SET_1_ID>)
      ))
      .setFieldGeoLocations(
        new TargetingGeoLocation()
          .setFieldCountries(Arrays.asList("US"))
      )
      .setFieldProductAudienceSpecs(Arrays.asList(
        new TargetingProductAudienceSpec()
          .setFieldExclusions(Arrays.asList(
            new TargetingProductAudienceSubSpec()
              .setFieldRetentionSeconds("432000")
              .setFieldRule("{\"event\":{\"eq\":\"Purchase\"}}")
          ))
          .setFieldInclusions(Arrays.asList(
            new TargetingProductAudienceSubSpec()
              .setFieldRetentionSeconds("432000")
              .setFieldRule("{\"event\":{\"eq\":\"ViewContent\"}}")
          ))
          .setFieldProductSetId(<PRODUCT_SET_1_ID>)
      ))
  )
  .setPromotedObject("{\"product_set_id\":\"" + <PRODUCT_SET_1_ID> + "\"}")
  .setStatus(AdSet.EnumStatus.VALUE_PAUSED)
  .execute();
String ad_set_id = adSet.getId();
curl \
  -F 'name=My cross sell ad set' \
  -F 'bid_amount=3000' \
  -F 'billing_event=LINK_CLICKS' \
  -F 'optimization_goal=LINK_CLICKS' \
  -F 'daily_budget=15000' \
  -F 'campaign_id=<CAMPAIGN_ID>' \
  -F 'targeting={ 
    "geo_locations": {"countries":["US"]}, 
    "product_audience_specs": [ 
      { 
        "product_set_id": "<PRODUCT_SET_2_ID>", 
        "inclusions": [{"retention_seconds":432000,"rule":{"event":{"eq":"ViewContent"}}}], 
        "exclusions": [{"retention_seconds":432000,"rule":{"event":{"eq":"Purchase"}}}] 
      } 
    ], 
    "excluded_product_audience_specs": [ 
      { 
        "product_set_id": "<PRODUCT_SET_2_ID>", 
        "inclusions": [{"retention_seconds":259200,"rule":{"event":{"eq":"ViewContent"}}}] 
      } 
    ] 
  }' \
  -F 'promoted_object={"product_set_id":"<PRODUCT_SET_1_ID>"}' \
  -F 'status=PAUSED' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/adsets

And set product_set_id in the creative as {PRODUCT_SET_1}; for example, handbags.

use FacebookAds\Object\AdCreative;
use FacebookAds\Object\Fields\AdCreativeFields;
use FacebookAds\Object\Fields\AdCreativeLinkDataFields;
use FacebookAds\Object\Fields\AdCreativeObjectStorySpecFields;
use FacebookAds\Object\AdCreativeLinkData;
use FacebookAds\Object\AdCreativeObjectStorySpec;

$object_story_spec = new AdCreativeObjectStorySpec();
$object_story_spec->setData(array(
  AdCreativeObjectStorySpecFields::PAGE_ID => <PAGE_ID>,
  AdCreativeObjectStorySpecFields::TEMPLATE_DATA =>
    (new AdCreativeLinkData())->setData(array(
      AdCreativeLinkDataFields::MESSAGE => 'Test {{product.name | titleize}}',
      AdCreativeLinkDataFields::LINK => '<LINK>',
      AdCreativeLinkDataFields::NAME => 'Headline {{product.price}}',
      AdCreativeLinkDataFields::DESCRIPTION =>
        'Description {{product.description}}',
    )),
));

$creative = new AdCreative(null, 'act_<AD_ACCOUNT_ID>');

$creative->setData(array(
  AdCreativeFields::NAME => 'Dynamic Ad Template Creative Sample',
  AdCreativeFields::OBJECT_STORY_SPEC => $object_story_spec,
  AdCreativeFields::PRODUCT_SET_ID => <PRODUCT_SET_ID>,
));

$creative->create();
from facebookads.adobjects.adcreative import AdCreative
from facebookads.adobjects.adcreativeobjectstoryspec \
    import AdCreativeObjectStorySpec

story = AdCreativeObjectStorySpec()
story[story.Field.page_id] = <PAGE_ID>
story[story.Field.template_data] = {
    'message': 'Test {{product.name | titleize}}',
    'link': '<LINK>',
    'name': 'Headline {{product.price}}',
    'description': 'Description {{product.description}}',
}

creative = AdCreative(parent_id='act_<AD_ACCOUNT_ID>')
creative[AdCreative.Field.name] = 'Dynamic Ad Template Creative Sample'
creative[AdCreative.Field.object_story_spec] = story
creative[AdCreative.Field.product_set_id] = <PRODUCT_SET_ID_1>
creative.remote_create()
AdCreative adCreative = new AdAccount(act_<AD_ACCOUNT_ID>, context).createAdCreative()
  .setName("Dynamic Ad Template Creative Sample")
  .setObjectStorySpec(
    new AdCreativeObjectStorySpec()
      .setFieldPageId(<PAGE_ID>)
      .setFieldTemplateData(
        new AdCreativeLinkData()
          .setFieldDescription("Description {{product.description}}")
          .setFieldLink(<LINK>)
          .setFieldMessage("Test {{product.name | titleize}}")
          .setFieldName("Headline {{product.price}}")
      )
  )
  .setProductSetId(<PRODUCT_SET_ID>)
  .execute();
String ad_creative_id = adCreative.getId();
curl \
  -F 'name=Dynamic Ad Template Creative Sample' \
  -F 'object_story_spec={ 
    "page_id": "<PAGE_ID>", 
    "template_data": { 
      "description": "Description {{product.description}}", 
      "link": "<LINK>", 
      "message": "Test {{product.name | titleize}}", 
      "name": "Headline {{product.price}}" 
    } 
  }' \
  -F 'product_set_id=<PRODUCT_SET_ID>' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/adcreatives

Broad Audience Targeting

In addition to retargeting and cross-selling to existing customers, Dynamic Ads may be used to target broad audiences, utilizing age, gender and other demographic targeting, with relevant products from your product catalog. By utilizing broadly targeted audiences combined with bidding for offsite conversions, dynamic ads enable you to greatly expand the reach of your ads efficiently.

To target broad audiences:

  • Create an audience using basic demographic targeting such as women in the US over 18.
  • Include customOptimize for OFFSITE_CONVERSIONS with stronger intent signals such as Purchase or InitiateCheckout.

In this example, we create an adset targeted at women, age 30-65 in the US, excluding customers who have purchased in the past 10 days. We will bid $8, using OFFSITE_CONVERSIONS for PURCHASE events.

use FacebookAds\Object\AdSet;
use FacebookAds\Object\Fields\AdSetFields;
use FacebookAds\Object\Fields\TargetingFields;
use FacebookAds\Object\Values\AdSetBillingEventValues;
use FacebookAds\Object\Values\AdSetOptimizationGoalValues;

$adset = new AdSet(null, 'act_<AD_ACCOUNT_ID>');

$adset->setData(array(
  AdSetFields::NAME => 'Broad Audience Targeting',
  AdSetFields::BID_AMOUNT => 800,
  AdSetFields::BILLING_EVENT => AdSetBillingEventValues::IMPRESSIONS,
  AdSetFields::DAILY_BUDGET => 15000,
  AdSetFields::CAMPAIGN_ID => <CAMPAIGN_ID>,
  AdSetFields::TARGETING => array(
    TargetingFields::AGE_MAX => 65,
    TargetingFields::AGE_MIN => 30,
    TargetingFields::GEO_LOCATIONS => array(
      'countries' => array('US'),
    ),
    TargetingFields::GENDERS => array(2),
    TargetingFields::EXCLUDED_PRODUCT_AUDIENCE_SPECS => array(array(
      'product_set_id' => <PRODUCT_SET_ID>,
      'inclusions' => array(array(
        'retention_seconds' => 864000,
        'rule' =>  array('event' => array('eq' => 'Purchase')),
      )),
    )),
  ),
  AdSetFields::PROMOTED_OBJECT => array(
    'product_set_id' => <PRODUCT_SET_ID>,
    'custom_event_type' => 'PURCHASE',
  ),
  AdSetFields::OPTIMIZATION_GOAL =>
    AdSetOptimizationGoalValues::OFFSITE_CONVERSIONS,
));

$adset->create(array(
  AdSet::STATUS_PARAM_NAME => AdSet::STATUS_PAUSED,
));
curl \
  -F 'name=Broad Audience Targeting' \
  -F 'bid_amount=800' \
  -F 'billing_event=IMPRESSIONS' \
  -F 'daily_budget=15000' \
  -F 'campaign_id=<CAMPAIGN_ID>' \
  -F 'targeting={ 
    "age_max": 65, 
    "age_min": 30, 
    "geo_locations": {"countries":["US"]}, 
    "genders": [2], 
    "excluded_product_audience_specs": [ 
      { 
        "product_set_id": "<PRODUCT_SET_ID>", 
        "inclusions": [{"retention_seconds":864000,"rule":{"event":{"eq":"Purchase"}}}] 
      } 
    ] 
  }' \
  -F 'promoted_object={"product_set_id":"<PRODUCT_SET_ID>","custom_event_type":"PURCHASE"}' \
  -F 'optimization_goal=OFFSITE_CONVERSIONS' \
  -F 'status=PAUSED' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/adsets

Dynamic Ads with Offers

You can now deliver Offers in Dynamic Ads. With offers, advertisers can provide discounts to customers on Facebook and direct people to shop on their website, at their physical store, or both. Offers in Dynamic Ads, appear as a fixed card in the first slot of the carousel, and is followed by recommended products.

In the ad set, set offer_id and product_set_id in promoted_object:

curl \
  -F 'name=DA Offer Adset' \
  -F 'bid_amount=3000' \
  -F 'billing_event=IMPRESSIONS' \
  -F 'status=ACTIVE' \
  -F 'daily_budget=15000' \
  -F 'campaign_id=<CAMPAIGN_ID>' \
  -F 'targeting={ 
    "geo_locations": {"countries":["US"]}, 
    "dynamic_audience_ids": ["<DYNAMIC_AUDIENCE_ID>"] 
  }' \
  -F 'promoted_object={"offer_id":<OFFER_ID>, "product_set_id”:<PRODUCT_SET_ID>}' \
  -F 'access_token=<ACCESS_TOKEN>’ \
  https://graph.facebook.com/<API_VERSION>/act_<AD_ACCOUNT_ID>/adsets

In the creative:

curl \
  -F 'name=DA Offer Creative Sample' \
  -F 'object_story_spec={ 
    "page_id": "<PAGE_ID>", 
    "template_data": { 
      "offer_id": "<OFFER_ID>", 
      "child_attachments": [ 
        {
              "link": "<URL>",
              "image_hash": “<HASH>",
              "name": "Offer title at L2",
              "call_to_action": {"type": "GET_OFFER_VIEW"},
               "static_card": true
         },
        { 
          "call_to_action": {"type":"SHOP_NOW"}, 
          "description": "Description {{product.description}}", 
          "name": "Headline {{product.price}}" 
        } 
      ], 
      "link": "<URL>"
    } 
  }' \
  -F 'product_set_id=<PRODUCT_SET_ID>' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/<API_VERSION>/act_<AD_ACCOUNT_ID>/adcreatives

Categories for Dynamic Ads

Categories for Dynamic Ads introduces two new creative options for the Dynamic Ads platform, both of which can be used to personalize creative for shoppers who are earlier in their decision journey. With this feature, you can create what is effectively a second, smaller creative catalog of images that represent each category (in addition to the catalog you already have of product imagery), and we will match product categories to people in your ads the same way we match products to people. Categories for Dynamic Ads can be used with any targeting option in the Traffic, Conversion, or Catalog Sales objective. If you don't have a high quality image representative of each category or brand, Facebook can auto-generate a 2x2 collage of top products for each group of products.

When mapping this new imagery to their existing product catalogs, advertisers can use one of three columns in their feed to group items: brand, product type, and Google product category. Using product type as an example, in the catalog below, the Product Type column has five unique values. The advertiser can provide up to five collages or lifestyle images—one for each unique value in product_type. The product type is the category's categorization criteria, which is the catalog field name used to define the categories. The catalog field value is category's criteria value. A category can be uniquely identified by:

  • Product catalog ID
  • Categorization criteria (brand, product type, or Google product product category)
  • Criteria value (pulled from catalog)
Retailer ID Name Price Product Type Brand Category

prod_1

T-Shirt

USD 25

Clothes

Brand A

Category A

prod_2

FB Hoodie

USD 30

Clothes

Brand B

Category A

prod_3

iPhone 6

USD 800

Phone

Brand C

Category B

prod_4

Samsung Galaxy S5

USD 750

Phone

Brand C

Category B

prod_5

Rice cooker

USD 120

Appliance

Brand C

Category C

prod_6

Parker Sofa

USD 500

Appliance

Brand D

Category D

prod_7

Sunscreen

USD 14

Personal Care

Brand E

Category E

The advertiser can associate each category (for example, each group of products as defined by unique values in one of the columns specified above) with assets:

  • Name - A user-facing short name of the category (up to 40 characters).
  • Description - A user-facing description of the category (up to 20 characters).
  • destination_uri - URL of the landing page when auser clicks the category.
  • image_url - Optional. URL of a life style image representing the category. If no image_url is provided, we will autogenerate a collage of top products from that category.

During ads delivery time, we dynamically match each person with the categories they are most likely to respond to based using the same machine learning models that power dynamic ads today.


Categories Management API

Categories information is stored at the catalog level, meaning that different ads promoting the categories from the same catalog would share assets, the same as ads promoting products would share assets defined in catalogs. We do support different creative options to customize category ads.

Below are the APIs to get and update categories information.

Get Categories

curl -G \
  -d 'fields=["criteria_value","name","description","destination_uri","image_url"]' \
  -d 'categorization_criteria=product_type' \
  -d 'filter={"price_amount":{"gt":1500}}' \ # optional
  -d 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/<API_VERSION>/<PRODUCT_CATALOG_ID>/categories

We query Elastic Search for all products (optional filter is supported) and find the top 1,000 categories (order by number of products). Below is an example of how the response looks. Note: Using the Graph API, the advertiser specifies the category's field name, description, destination_uri and image_url.

{
  "data": [
    {
      "criteria_value": "clothes",
      "name": "Awesome clothes",
      "description": "Check out these awesome clothes!",
      "destination_uri": "http://www.example.com/clothes",
      "image_url": "http://www.example.com/clothes.jpg"
    },
    ...
    {
      "criteria_value": "shoes",
      "name": "Awesome shoes",
      "description": "Check out these awesome shoes!",
      "destination_uri": "http://www.example.com/shoes",
      "image_url": "http://www.example.com/shoes.jpg"
    }
  ]
}

Update Categories

curl \
  -F 'data=[{"categorization_criteria":"product_type","criteria_value":"product_type_value","name":"Name","description":"Description","destination_uri":"http://www.example.com/","image_url":"<IMAGE_URL>"}]' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/<API_VERSION>/<PRODUCT_CATALOG_ID>/categories
  • Can specify multiple categories information in data
  • For each category, categorization_criteria and criteria_value are required. The name, description, destination_uri, and image_url are optional.
  • When updating information of a category for the first time, you must specify the destination_uri.
  • Deleting a category is not supported at this time. If advertisers want to skip delivery of a category, simply set its destination_uri to be empty.

Ads Creation

Category for Dynamic Ads ad creation is similar to ad creation for other dynamic ads, but the creative selection is slightly different. Note: Advertisers are still promoting a product set with dynamic category ads; the difference is that we're showing category creatives instead.

curl \
  -F "name=Dynamic Category Ad Creative" \
  -F 'object_story_spec={"page_id": "<PAGE_ID>", "template_data": {"description": "{{category.description}}", "link": "https://www.example.com/", "message": "<MESSAGE>", "name": "{{category.name}}"}}' \
  -F 'product_set_id=<PRODUCT_SET_ID>' \
  -F 'categorization_criteria=brand' \
  -F 'category_media_source=MIXED' \ # optional
  -F access_token=<ACCESS_TOKEN> \
  https://graph.facebook.com/<API_VERSION>/act_<ACCOUNT_ID>/adcreatives

This creates a category ad creative rendered in a carousel format:

Category Tokens

Here's a list of supported category tokens:

  • category.name - Category name within the promoted product set.
  • category.description - Category description within the promoted product set.
  • category.destination_uri - Category destination URI
  • category.min_price - Minimum price for this category within promoted product set. This information is pulled from the catalog.

Parameters

  • categorization_criteria: Specified which category type to use. Possible values include:

    • brand
    • product_type
    • google_product_category
  • category_media_source: Specifies how to render the category carousel card. Possible values include:

    • category: Use the category's image; skip this category if this category doesn't have a image.
    • products_collage: Generate a 2x2 collage of product images from this category; see below example.
    • mixed (default): Use the category's image if exists; otherwise, fall back to products_collage.
    • products_slideshow: Render a slideshow of products from this category.

During the category ad creative creation, we search for possible renderable categories. Note: We filter out categories without a name or destination URL. We also filter out categories without images if category_media_source = category.

Common Errors

Creative creation fails if there are less than 4 eligible categories (for example, to use Categories for Dynamic Ads as your creative for a given campaign, there must be **at least four unique values*** in a given column from your product feed).

Step 3. Provide Ad Creative

Related Topics

Dynamic Ad Templates use Inline Page Post API for creating Dynamic Ad Template Creatives.

In this section, we cover:


Build a Creative Template

Creating a Dynamic Ad Template Creative is similar to creating other ad creatives. The difference is that you can add template parameters that properly render at runtime based on data in your Product Feed.

Build the template based on the template_data object of the object_story_spec and use the following fields:

Field Name Description Accepts Template Parameters Type

call_to_action

Call to Action object. The value field should be omitted.

No

object

message

Message for your ad, visible on Instagram.

Yes

string

link

Link to your website, used to generate the caption of the ad. This field will always be replaced with the link field from your product feed, except the end card of Carousel Ads which will link to this. This cannot be a URL on Facebook.com

No

string

name

Name or title for your ad, visible on Instagram.

Yes

string

description

Description for your ad. Not visible on Instagram.

Yes

string

force_single_link

Force to render a single link format. This field is optional.


When set to true, the creative will be a link page post ad showing a single product.


When left out, the resulting ad will be a carousel ad. Facebook will choose the number of cards to optimize the performance of your ad.

No

boolean

show_multiple_images

Show multiple images in the carousel for a single product. Note that force_single_link and multi_share_end_card must be set to true and false respectively.

No

boolean

multi_share_end_card

Use this optional field in carousel format. If set to false, it will remove the end card which displays the page icon. Default is true.

No

boolean

additional_image_index

Which image from the additional images array should be used as the ad image. This is a zero-based index between 0-9. If there is no image for a given product at the specified index, use the main product image.

No

int

child_attachments

Enables you to provide one or more static cards in dynamic ads for the carousel format. The static cards appear either before or after all dynamic ads. Provide the field static_card set to true for each static card under child_attachments.

No

array

image_layer_specs

Specifies how to transform the images when they are delivered to users in the ad.

No

AdCreativeLinkDataImageLayerSpecs; one AdCreativeLinkDataImageOverlaySpec is needed for each layer to define how to render the layer. The layers will be rendered in the order they appear in the list. Note: AdCreativeLinkDataImageLayerSpecs is available on a limited basis. Please contact your Facebook representative for more details.

image_overlay_spec

Specifies how to render overlays on an image for a dynamic item.

No

AdCreativeLinkDataImageOverlaySpec

preferred_image_tags

Select which image to use, if you have added tags to your images. For any item, we choose the image as follows: we get the first tag in preferred_image_tags that has at least one image for the item, then render the first image for that tag. If no tags correspond to an image, we serve the first image.

No

array

Create a Carousel Dynamic Ad Template (Example)

use FacebookAds\Object\AdCreative;
use FacebookAds\Object\Fields\AdCreativeFields;
use FacebookAds\Object\Fields\AdCreativeLinkDataFields;
use FacebookAds\Object\Fields\AdCreativeObjectStorySpecFields;
use FacebookAds\Object\AdCreativeObjectStorySpec;
use FacebookAds\Object\AdCreativeLinkData;

$object_story_spec = new AdCreativeObjectStorySpec();
$object_story_spec->setData(array(
  AdCreativeObjectStorySpecFields::PAGE_ID => <PAGE_ID>,
  AdCreativeObjectStorySpecFields::TEMPLATE_DATA =>
    (new AdCreativeLinkData())->setData(array(
      AdCreativeLinkDataFields::MESSAGE => 'Test {{product.name | titleize}}',
      AdCreativeLinkDataFields::LINK => '<LINK>',
      AdCreativeLinkDataFields::NAME => 'Headline {{product.price}}',
      AdCreativeLinkDataFields::DESCRIPTION =>
        'Description {{product.description}}',
    )),
));

$creative = new AdCreative(null, 'act_<AD_ACCOUNT_ID>');
$creative->setData(array(
  AdCreativeFields::NAME => 'Dynamic Ad Template Creative Sample',
  AdCreativeFields::OBJECT_STORY_SPEC => $object_story_spec,
  AdCreativeFields::PRODUCT_SET_ID => <PRODUCT_SET_ID>,
));

$creative->create();
from facebookads.adobjects.adcreative import AdCreative
from facebookads.adobjects.adcreativeobjectstoryspec \
    import AdCreativeObjectStorySpec

story = AdCreativeObjectStorySpec()
story[story.Field.page_id] = <PAGE_ID>
story[story.Field.template_data] = {
    'message': 'Test {{product.name | titleize}}',
    'link': '<LINK>',
    'name': 'Headline {{product.price}}',
    'description': 'Description {{product.description}}',
}

creative = AdCreative(parent_id='act_<AD_ACCOUNT_ID>')
creative[AdCreative.Field.name] = 'Dynamic Ad Template Creative Sample'
creative[AdCreative.Field.object_story_spec] = story
creative[AdCreative.Field.product_set_id] = <PRODUCT_SET_ID>
creative.remote_create()
AdCreative adCreative = new AdAccount(act_<AD_ACCOUNT_ID>, context).createAdCreative()
  .setName("Dynamic Ad Template Creative Sample")
  .setObjectStorySpec(
    new AdCreativeObjectStorySpec()
      .setFieldPageId(<PAGE_ID>)
      .setFieldTemplateData(
        new AdCreativeLinkData()
          .setFieldDescription("Description {{product.description}}")
          .setFieldLink(<LINK>)
          .setFieldMessage("Test {{product.name | titleize}}")
          .setFieldName("Headline {{product.price}}")
      )
  )
  .setProductSetId(<PRODUCT_SET_ID>)
  .execute();
String ad_creative_id = adCreative.getId();
curl \
  -F 'name=Dynamic Ad Template Creative Sample' \
  -F 'object_story_spec={ 
    "page_id": "<PAGE_ID>", 
    "template_data": { 
      "description": "Description {{product.description}}", 
      "link": "<LINK>", 
      "message": "Test {{product.name | titleize}}", 
      "name": "Headline {{product.price}}" 
    } 
  }' \
  -F 'product_set_id=<PRODUCT_SET_ID>' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/adcreatives

Using a Dynamic Ad Template with Image Overlays (Example)

curl \
  -F 'name=Dynamic Ad Template Creative Sample' \
  -F 'object_story_spec={ 
    "page_id": "<PAGE_ID>", 
    "template_data": { 
      "call_to_action": {"type":"SHOP_NOW"}, 
      "description": "Description {{product.description}}", 
      "link": "<LINK>", 
      "message": "Test {{product.name | titleize}}", 
      "name": "Headline {{product.price}}",
      "image_layer_specs": [
        {
          "layer_type": "image",
          "image_source": "catalog"
        },
        {
          "layer_type": "frame_overlay",
          "blending_mode": "lighten",
          "frame_image_hash": "<HASH>",
          "frame_source": "custom",
          "opacity": 100,
          "overlay_position": "center",
          "scale": 100
        },
        {
          "layer_type": "text_overlay",
          "content": {
            "type": "price"
          },
          "opacity": 100,
          "overlay_position": "top_left",
          "overlay_shape": "rectangle",
          "shape_color": "DF0005",
          "text_color": "FFFFFF",
          "text_font": "open_sans_bold"
        }
      ]
    } 
  }' \
  -F 'product_set_id=<PRODUCT_SET_ID>' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/<API_VERSION>/act_<AD_ACCOUNT_ID>/adcreatives

Create a Single Product Dynamic Ad Template with a Call to Action (Example)

use FacebookAds\Object\AdCreative;
use FacebookAds\Object\Fields\AdCreativeFields;
use FacebookAds\Object\Fields\AdCreativeLinkDataFields;
use FacebookAds\Object\Fields\AdCreativeObjectStorySpecFields;
use FacebookAds\Object\AdCreativeObjectStorySpec;
use FacebookAds\Object\AdCreativeLinkData;
use FacebookAds\Object\Values\AdCreativeCallToActionTypeValues;

$object_story_spec = new AdCreativeObjectStorySpec();
$object_story_spec->setData(array(
  AdCreativeObjectStorySpecFields::PAGE_ID => <PAGE_ID>,
  AdCreativeObjectStorySpecFields::TEMPLATE_DATA =>
    (new AdCreativeLinkData())->setData(array(
      AdCreativeLinkDataFields::CALL_TO_ACTION => array(
        'type' => AdCreativeCallToActionTypeValues::SHOP_NOW,
      ),
      AdCreativeLinkDataFields::MESSAGE => 'Test {{product.name | titleize}}',
      AdCreativeLinkDataFields::LINK => '<LINK>',
      AdCreativeLinkDataFields::NAME => 'Headline {{product.price}}',
      AdCreativeLinkDataFields::DESCRIPTION =>
        'Description {{product.description}}',
      AdCreativeLinkDataFields::FORCE_SINGLE_LINK => true,
    )),
));

$creative = new AdCreative(null, 'act_<AD_ACCOUNT_ID>');

$creative->setData(array(
  AdCreativeFields::NAME => 'Dynamic Ad Template Creative Sample',
  AdCreativeFields::OBJECT_STORY_SPEC => $object_story_spec,
  AdCreativeFields::PRODUCT_SET_ID => <PRODUCT_SET_ID>,
));

$creative->create();
from facebookads.adobjects.adcreative import AdCreative
from facebookads.adobjects.adcreativeobjectstoryspec \
    import AdCreativeObjectStorySpec

story = AdCreativeObjectStorySpec()
story[story.Field.page_id] = <PAGE_ID>
story[story.Field.template_data] = {
    'message': 'Test {{product.name | titleize}}',
    'link': '<LINK>',
    'name': 'Headline {{product.price}}',
    'description': 'Description {{product.description}}',
    'force_single_link': True,
}

creative = AdCreative(parent_id='act_<AD_ACCOUNT_ID>')
creative[AdCreative.Field.name] = 'Dynamic Ad Template Creative Sample'
creative[AdCreative.Field.object_story_spec] = story
template_url = ('http://clicktrack.com/cm325?id={{product.retailer_id}}'
                '&redirect_url={{product.url|urlencode}}')
creative[AdCreative.Field.template_url] = template_url
creative[AdCreative.Field.product_set_id] = <PRODUCT_SET_ID>
creative.remote_create()
AdCreative adCreative = new AdAccount(act_<AD_ACCOUNT_ID>, context).createAdCreative()
  .setName("Dynamic Ad Template Creative Sample")
  .setObjectStorySpec(
    new AdCreativeObjectStorySpec()
      .setFieldPageId(<PAGE_ID>)
      .setFieldTemplateData(
        new AdCreativeLinkData()
          .setFieldCallToAction(
            new AdCreativeLinkDataCallToAction()
              .setFieldType(AdCreativeLinkDataCallToAction.EnumType.VALUE_SHOP_NOW)
          )
          .setFieldDescription("Description {{product.description}}")
          .setFieldForceSingleLink(true)
          .setFieldLink(<LINK>)
          .setFieldMessage("Test {{product.name | titleize}}")
          .setFieldName("Headline {{product.price}}")
      )
  )
  .setProductSetId(<PRODUCT_SET_ID>)
  .execute();
String ad_creative_id = adCreative.getId();
curl \
  -F 'name=Dynamic Ad Template Creative Sample' \
  -F 'object_story_spec={ 
    "page_id": "<PAGE_ID>", 
    "template_data": { 
      "call_to_action": {"type":"SHOP_NOW"}, 
      "description": "Description {{product.description}}", 
      "force_single_link": true, 
      "link": "<LINK>", 
      "message": "Test {{product.name | titleize}}", 
      "name": "Headline {{product.price}}" 
    } 
  }' \
  -F 'product_set_id=<PRODUCT_SET_ID>' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/adcreatives

Creating a Carousel Dynamic Ad Template where the Ad Image Uses the First Image from the Additional Images Array (Example)

To preview Dynamic Ads with additional_image_index, you must pass the entire object_story_spec to the /generatepreviews. Passing only object_story_id doesn't generate a preview.

use FacebookAds\Object\AdCreative;
use FacebookAds\Object\Fields\AdCreativeFields;
use FacebookAds\Object\Fields\AdCreativeLinkDataFields;
use FacebookAds\Object\Fields\AdCreativeObjectStorySpecFields;
use FacebookAds\Object\AdCreativeObjectStorySpec;
use FacebookAds\Object\AdCreativeLinkData;

$object_story_spec = new AdCreativeObjectStorySpec();
$object_story_spec->setData(array(
  AdCreativeObjectStorySpecFields::PAGE_ID => <PAGE_ID>,
  AdCreativeObjectStorySpecFields::TEMPLATE_DATA =>
    (new AdCreativeLinkData())->setData(array(
      AdCreativeLinkDataFields::MESSAGE => 'Test {{product.name | titleize}}',
      AdCreativeLinkDataFields::LINK => '<LINK>',
      AdCreativeLinkDataFields::NAME => 'Headline {{product.price}}',
      AdCreativeLinkDataFields::DESCRIPTION =>
        'Description {{product.description}}',
      AdCreativeLinkDataFields::ADDITIONAL_IMAGE_INDEX => 0,
    )),
));

$creative = new AdCreative(null, 'act_<AD_ACCOUNT_ID>');
$creative->setData(array(
  AdCreativeFields::NAME => 'Dynamic Ad Template Creative Sample',
  AdCreativeFields::OBJECT_STORY_SPEC => $object_story_spec,
  AdCreativeFields::PRODUCT_SET_ID => <PRODUCT_SET_ID>,
));

$creative->create();
from facebookads.adobjects.adcreative import AdCreative
from facebookads.adobjects.adcreativeobjectstoryspec \
    import AdCreativeObjectStorySpec

story = AdCreativeObjectStorySpec()
story[story.Field.page_id] = <PAGE_ID>
story[story.Field.template_data] = {
    'message': 'Test {{product.name | titleize}}',
    'link': '<LINK>',
    'name': 'Headline {{product.price}}',
    'description': 'Description {{product.description}}',
    'additional_image_index': 0,
}

creative = AdCreative(parent_id='act_<AD_ACCOUNT_ID>')
creative[AdCreative.Field.name] = 'Dynamic Ad Template Creative Sample'
creative[AdCreative.Field.object_story_spec] = story
creative[AdCreative.Field.product_set_id] = <PRODUCT_SET_ID>
creative.remote_create()
AdCreative adCreative = new AdAccount(act_<AD_ACCOUNT_ID>, context).createAdCreative()
  .setName("Dynamic Ad Template Creative Sample")
  .setObjectStorySpec(
    new AdCreativeObjectStorySpec()
      .setFieldPageId(<PAGE_ID>)
      .setFieldTemplateData(
        new AdCreativeLinkData()
          .setFieldDescription("Description {{product.description}}")
          .setFieldLink(<LINK>)
          .setFieldMessage("Test {{product.name | titleize}}")
          .setFieldName("Headline {{product.price}}")
          .setFieldAdditionalImageIndex((long) 0)
      )
  )
  .setProductSetId(<PRODUCT_SET_ID>)
  .execute();
String ad_creative_id = adCreative.getId();
curl \
  -F 'name=Dynamic Ad Template Creative Sample' \
  -F 'object_story_spec={ 
    "page_id": "<PAGE_ID>", 
    "template_data": { 
      "additional_image_index": 0, 
      "description": "Description {{product.description}}", 
      "link": "<LINK>", 
      "message": "Test {{product.name | titleize}}", 
      "name": "Headline {{product.price}}" 
    } 
  }' \
  -F 'product_set_id=<PRODUCT_SET_ID>' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/adcreatives

Create a Carousel Dynamic Ad Template for a Single Product Where Each Image Comes from Additional Images array in the Catalog (Example)

curl -X POST \
     -F 'name=Dynamic Ad Template Creative Sample' \
     -F 'object_story_spec={
           "page_id": <PAGE_ID>,
           "template_data": {
             "message": "Test {{product.name | titleize}}",
             "link": "<YOUR_LINK_URL>",
             "name": "Headline {{product.price}}",
             "description": "Description {{product.description}}",
             "multi_share_end_card": false,
             "force_single_link": true,
             "show_multiple_images": true,
           }
         }' \
     -F 'product_set_id=<PRODUCT_SET_ID>' \
     -F 'access_token=<ACCESS_TOKEN>' \
https://graph.facebook.com/<API_VERSION>/act_<AD_ACCOUNT_ID>/adcreatives

Create a Carousel Dynamic Ad Template with First Card as Coupon Static Card (Example)

use FacebookAds\Object\AdCreative;
use FacebookAds\Object\Fields\AdCreativeFields;
use FacebookAds\Object\Fields\AdCreativeLinkDataFields;
use FacebookAds\Object\Fields\AdCreativeObjectStorySpecFields;
use FacebookAds\Object\Fields\AdCreativeLinkDataChildAttachmentFields;
use FacebookAds\Object\AdCreativeLinkDataChildAttachment;
use FacebookAds\Object\AdCreativeObjectStorySpec;
use FacebookAds\Object\AdCreativeLinkData;
use FacebookAds\Object\Values\AdCreativeCallToActionTypeValues;

$static_card = (new AdCreativeLinkDataChildAttachment())->setData(array(
  AdCreativeLinkDataChildAttachmentFields::LINK =>
    'https://www.link.com/coupon',
  AdCreativeLinkDataChildAttachmentFields::NAME => 'Coupon Static Card',
  AdCreativeLinkDataChildAttachmentFields::DESCRIPTION => '30% off',
  AdCreativeLinkDataChildAttachmentFields::IMAGE_HASH => '<IMAGE_HASH>',
  AdCreativeLinkDataChildAttachmentFields::CALL_TO_ACTION => array(
    'type' => AdCreativeCallToActionTypeValues::SHOP_NOW,
  ),
  AdCreativeLinkDataChildAttachmentFields::STATIC_CARD => true,
));

$dynamic_card_place_holder =
  (new AdCreativeLinkDataChildAttachment())->setData(array(
    AdCreativeLinkDataChildAttachmentFields::NAME =>
      'Headline {{product.price}}',
    AdCreativeLinkDataChildAttachmentFields::DESCRIPTION =>
      'Description {{product.description}}',
    AdCreativeLinkDataChildAttachmentFields::CALL_TO_ACTION => array(
      'type' => AdCreativeCallToActionTypeValues::SHOP_NOW,
    ),
  ));

$object_story_spec = new AdCreativeObjectStorySpec();
$object_story_spec->setData(array(
  AdCreativeObjectStorySpecFields::PAGE_ID => <PAGE_ID>,
  AdCreativeObjectStorySpecFields::TEMPLATE_DATA =>
    (new AdCreativeLinkData())->setData(array(
      AdCreativeLinkDataFields::MESSAGE => 'Test Message',
      AdCreativeLinkDataFields::LINK => '<LINK>',
      AdCreativeLinkDataFields::CHILD_ATTACHMENTS => array(
        $static_card,
        $dynamic_card_place_holder,
      ),
    )),
));

$creative = new AdCreative(null, 'act_<AD_ACCOUNT_ID>');
$creative->setData(array(
  AdCreativeFields::NAME => 'Dynamic Ad Template Creative Sample',
  AdCreativeFields::OBJECT_STORY_SPEC => $object_story_spec,
  AdCreativeFields::PRODUCT_SET_ID => <PRODUCT_SET_ID>,
));

$creative->create();
from facebookads.adobjects.adcreative import AdCreative
from facebookads.adobjects.adcreative'<LINK>'data import AdCreativeLinkData
from facebookads.adobjects.adcreativeobjectstoryspec \
    import AdCreativeObjectStorySpec
from facebookads.adobjects.adcreative'<LINK>'datachildattachment \
    import AdCreativeLinkDataChildAttachment

static_card = AdCreativeLinkDataChildAttachment()
static_card[AdCreativeLinkDataChildAttachment.Field.link] = '<LINK>'
static_card[AdCreativeLinkDataChildAttachment.Field.name] = \
    'Coupon Static Card'
static_card[AdCreativeLinkDataChildAttachment.Field.description] = '30% off'
static_card[AdCreativeLinkDataChildAttachment.Field.image_hash] = '<IMAGE_HASH>'
static_card[AdCreativeLinkDataChildAttachment.Field.call_to_action] = {
    'type': 'SHOP_NOW',
}
static_card[AdCreativeLinkDataChildAttachment.Field.static_card] = True

dynamic_card_place_holder = AdCreativeLinkDataChildAttachment()
dynamic_card_place_holder[AdCreativeLinkDataChildAttachment.Field.name] = \
    'Headline {{product.price}}'
dynamic_card_place_holder[AdCreativeLinkDataChildAttachment.Field.description] = \
    'Description {{product.description}}'
dynamic_card_place_holder[AdCreativeLinkDataChildAttachment.Field.call_to_action] = {
    'type': 'SHOP_NOW',
}

story = AdCreativeObjectStorySpec()
story[story.Field.page_id] = <PAGE_ID>
story[story.Field.template_data] = {
    AdCreativeLinkData.Field.message: 'Test Message',
    AdCreativeLinkData.Field.link: '<LINK>',
    AdCreativeLinkData.Field.child_attachments: [
        static_card,
        dynamic_card_place_holder,
    ],
}

creative = AdCreative(parent_id='act_<AD_ACCOUNT_ID>')
creative[AdCreative.Field.name] = 'Dynamic Ad Template Creative Sample'
creative[AdCreative.Field.object_story_spec] = story
creative[AdCreative.Field.product_set_id] = <PRODUCT_SET_ID>
creative.remote_create()
AdCreative adCreative = new AdAccount(act_<AD_ACCOUNT_ID>, context).createAdCreative()
  .setName("Dynamic Ad Template Creative Sample")
  .setObjectStorySpec(
    new AdCreativeObjectStorySpec()
      .setFieldPageId(<PAGE_ID>)
      .setFieldTemplateData(
        new AdCreativeLinkData()
          .setFieldCallToAction(
            new AdCreativeLinkDataCallToAction()
              .setFieldType(AdCreativeLinkDataCallToAction.EnumType.VALUE_SHOP_NOW)
          )
          .setFieldChildAttachments(Arrays.asList(
            new AdCreativeLinkDataChildAttachment()
              .setFieldDescription("30$ off")
              .setFieldImageHash(<IMAGE_HASH>)
              .setFieldLink("https://www.link.com/coupon")
              .setFieldName("Coupon Static Card")
              .setFieldStaticCard(true)
          , 
            new AdCreativeLinkDataChildAttachment()
              .setFieldDescription("place holder for dynamic product cards")
              .setFieldLink("https://www.link.com")
              .setFieldName("Dynamic Product Cards")
          ))
          .setFieldDescription("Description {{product.description}}")
          .setFieldLink(<LINK>)
          .setFieldMessage("Test {{product.name | titleize}}")
          .setFieldName("Headline {{product.price}}")
      )
  )
  .setProductSetId(<PRODUCT_SET_ID>)
  .execute();
String ad_creative_id = adCreative.getId();
curl \
  -F 'name=Dynamic Ad Template Creative Sample' \
  -F 'object_story_spec={ 
    "page_id": "<PAGE_ID>", 
    "template_data": { 
      "child_attachments": [ 
        { 
          "call_to_action": {"type":"SHOP_NOW"}, 
          "description": "30% off", 
          "image_hash": "<IMAGE_HASH>", 
          "link": "https:\/\/www.link.com\/coupon", 
          "name": "Coupon Static Card", 
          "static_card": true 
        }, 
        { 
          "call_to_action": {"type":"SHOP_NOW"}, 
          "description": "Description {{product.description}}", 
          "name": "Headline {{product.price}}" 
        } 
      ], 
      "link": "<LINK>", 
      "message": "Test Message" 
    } 
  }' \
  -F 'product_set_id=<PRODUCT_SET_ID>' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/adcreatives

Create a Carousel Slideshow from a Dynamic Ads Template (Example)

We render each dynamic card in the carousel as a slideshow. Each slideshow displays images from one dynamic item if the item has multiple images. If the dynamic item only has one image, we render a card as a static image.

curl \
  -F 'name=Dynamic Ad Template Creative Sample' \
  -F 'object_story_spec={
    "page_id": "PAGE_ID",
    "template_data": {
      "call_to_action": {"type":"SHOP_NOW"},
      "description": "Description {{product.description}}",
      "link": "LINK",
      "message": "Test {{product.name | titleize}}",
      "name": "Headline {{product.price}}",
      "format_option": "carousel_slideshows"
    }
  }' \
  -F 'product_set_id=PRODUCT_SET_ID' \
  -F 'access_token=ACCESS_TOKEN' \
  https://graph.facebook.com/VERSION/AD_ACCOUNT_ID/adcreatives

The response to these calls is the ID of a new Dynamic Ad template creative.

{"id":"creative_id"}

Upload a Catalog (Example)

When uploading a catalog, you can specify arbitrary alphanumeric string tags for each image in each property:

<listing>
 <hotel_id>hotel_1</hotel_id>
 ...
 <image>
 <url>https://media-cdn.tripadvisor.com/media/photo-o/05/ca/40/af/the-epiphany-a-joie-de.jpg (https://l.facebook.com/l.php?u=https%3A%2F%2Fmedia-cdn.tripadvisor.com%2Fmedia%2Fphoto-o%2F05%2Fca%2F40%2Faf%2Fthe-epiphany-a-joie-de.jpg&h=ATPTuLcCa7Vsnmn07cEVa0YseTFl1C2hOax9NezejmXDbR48w3CLdjLlwlpuGCRDQmuafQvk03ybGqfhk-2mBcH7xtuKAsnuuq9xKwBd8DwfuBMZkq3n1qX5MdychRKGy2bo2ax9BZQzgqVDY_AvC1EqE6aAdUEc)</url>
 <tag>exterior</tag>
 <tag>first image</tag>
 <tag>tree</tag>
 </image>
 <image>
 <url>http://www3.hilton.com/resources/media/hi/DFWANHH/en_US/img/shared/full_page_image_gallery/main/HH_exteriorview001_1270x560_FitToBoxSmallDimension_Center.jpg (http://l.facebook.com/l.php?u=http%3A%2F%2Fwww3.hilton.com%2Fresources%2Fmedia%2Fhi%2FDFWANHH%2Fen_US%2Fimg%2Fshared%2Ffull_page_image_gallery%2Fmain%2FHH_exteriorview001_1270x560_FitToBoxSmallDimension_Center.jpg&h=ATPTuLcCa7Vsnmn07cEVa0YseTFl1C2hOax9NezejmXDbR48w3CLdjLlwlpuGCRDQmuafQvk03ybGqfhk-2mBcH7xtuKAsnuuq9xKwBd8DwfuBMZkq3n1qX5MdychRKGy2bo2ax9BZQzgqVDY_AvC1EqE6aAdUEc)</url>
 <tag>skyline</tag>
 ...
 </image>
 ...
</listing>

Create an Ad Creative (Example)

When creating an ad creative, an array of preferred_image_tags can be passed in the object_story_spec; for example:

curl \
 -F 'name=Ad Creative Test'\
 -F 'object_story_spec={
     "page_id": '<PAGE_ID>',
     "template_data": {
       "preferred_image_tags": ["skyline","exterior"],
       "call_to_action": {"type":"BOOK_TRAVEL"},
       "description": "{{hotel.description}}",
       "link": "<URL>",
        "message": "Book your stay in {{hotel.city}}",
        "name": "{{hotel.name | titleize}}"
     }
    }' \
 -F 'product_set_id=<PRODUCT_SET_ID>' \
 -F 'access_token=<ACCESS_TOKEN>' \
 https://graph.facebook.com/<VERSION>/act_<AD_ACCOUNT_ID>/adcreatives

Click Tracking and Templates

If you track link clicks through a third-party click tracker before redirecting to the final product URL, you can use the template_url_spec field in the ad creative. template_url_spec allows adding a click tracker template to the ad level without the need to hard code it in your Product Feed. You can also use this field to create templates for Deeplinking.

In this field, you may use dynamic fields such as product URL or id, and those should be urlencoded if their values can contain characters that make the URL invalid.

Example to create a carousel dynamic ad template with template_url_spec setting:

use FacebookAds\Object\AdCreative;
use FacebookAds\Object\Fields\AdCreativeFields;
use FacebookAds\Object\Fields\AdCreativeLinkDataFields;
use FacebookAds\Object\Fields\AdCreativeObjectStorySpecFields;
use FacebookAds\Object\AdCreativeObjectStorySpec;
use FacebookAds\Object\AdCreativeLinkData;

$object_story_spec = new AdCreativeObjectStorySpec();
$object_story_spec->setData(array(
  AdCreativeObjectStorySpecFields::PAGE_ID => <PAGE_ID>,
  AdCreativeObjectStorySpecFields::TEMPLATE_DATA =>
    (new AdCreativeLinkData())->setData(array(
      AdCreativeLinkDataFields::MESSAGE => 'Test {{product.name | titleize}}',
      AdCreativeLinkDataFields::LINK => '<URL>',
      AdCreativeLinkDataFields::NAME => 'Headline {{product.price}}',
      AdCreativeLinkDataFields::DESCRIPTION =>
        'Description {{product.description}}',
    )),
));

$creative = new AdCreative(null, 'act_<AD_ACCOUNT_ID>');

$creative->setData(array(
  AdCreativeFields::NAME => 'Dynamic Ad Template Creative Sample',
  AdCreativeFields::OBJECT_STORY_SPEC => $object_story_spec,
  AdCreativeFields::TEMPLATE_URL_SPEC =>
    array(
      'ios' => array(
        'app_store_id' => '123',
        'url' => 'example://link/?nav=item.view'.
          '&id={{product.retailer_id | urlencode}}'.
          '&referrer=http://rover.example.com/rover/1/711-198453-24755-9/16'.
          '%3Fitemid={{product.retailer_id | urlencode | urlencode}}',
      ),
      'web' => array(
        'url' => 'http://clicktrack.com/cm325'.
          '?id={{product.retailer_id | urlencode}}'.
          '&redirect_url={{product.url | urlencode | urlencode}}',
      )
    ),
  AdCreativeFields::PRODUCT_SET_ID => <PRODUCT_SET_ID>,
));

$creative->create();
from facebookads.adobjects.adcreative import AdCreative
from facebookads.adobjects.adcreativeobjectstoryspec \
    import AdCreativeObjectStorySpec

story = AdCreativeObjectStorySpec()
story[story.Field.page_id] = <PAGE_ID>
story[story.Field.template_data] = {
    'message': 'Test {{product.name | titleize}}',
    'link': '<LINK>',
    'name': 'Headline {{product.price}}',
    'description': 'Description {{product.description}}',
}

creative = AdCreative(parent_id='act_<AD_ACCOUNT_ID>')
creative[AdCreative.Field.name] = 'Dynamic Ad Template Creative Sample'
creative[AdCreative.Field.object_story_spec] = story
template_url_spec = {
    'ios': {
        'app_store_id': '123',
        'url': 'example://sub/?nav=item.view' +
        '&id={{product.retailer_id | urlencode}}' +
        '&referrer=http://rover.example.com/rover/1/711-198453-24755-9/16' +
        '%3Fitemid={{product.retailer_id | urlencode | urlencode}}',
    },
    'web': {
        'url': 'http://clicktrack.com/cm325' +
        '?id={{product.retailer_id | urlencode}}' +
        '&redirect_url={{product.url | urlencode | urlencode}}',
    },
}
creative[AdCreative.Field.template_url_spec] = template_url_spec
creative[AdCreative.Field.product_set_id] = <PRODUCT_SET_ID>
creative.remote_create()
JsonObject templateUrlIosSpec = new JsonObject();
templateUrlIosSpec.addProperty("app_store_id","123");
templateUrlIosSpec.addProperty("url","example://link/?nav=item.view" +
  "&id={{product.retailer_id | <URL>encode}}" +
  "&referrer=http://rover.example.com/rover/1/711-198453-24755-9/16" +
  "%3Fitemid={{product.retailer_id | <URL>encode | <URL>encode}}");
JsonObject templateUrlWebSpec = new JsonObject();
templateUrlWebSpec.addProperty("url","http://clicktrack.com/cm325" +
  "?id={{product.retailer_id | <URL>encode}}" +
  "&redirect_url={{product.url | <URL>encode | <URL>encode}}");
JsonObject templateUrlSpec = new JsonObject();
templateUrlSpec.add("ios",templateUrlIosSpec);
templateUrlSpec.add("web",templateUrlWebSpec);
AdCreative adCreative = new AdAccount(act_<AD_ACCOUNT_ID>, context).createAdCreative()
  .setName("Dynamic Ad Template Creative Sample")
  .setObjectStorySpec(
    new AdCreativeObjectStorySpec()
      .setFieldPageId(<PAGE_ID>)
      .setFieldTemplateData(
        new AdCreativeLinkData()
          .setFieldDescription("Description {{product.description}}")
          .setFieldLink(<URL>)
          .setFieldMessage("Test {{product.name | titleize}}")
          .setFieldName("Headline {{product.price}}")
      )
  )
  .setTemplateUrlSpec(templateUrlSpec.toString())
  .setProductSetId(<PRODUCT_SET_ID>)
  .execute();
String ad_creative_id = adCreative.getId();
curl \
  -F 'name=Dynamic Ad Template Creative Sample' \
  -F 'object_story_spec={ 
    "page_id": "<PAGE_ID>", 
    "template_data": { 
      "description": "Description {{product.description}}", 
      "link": "<URL>", 
      "message": "Test {{product.name | titleize}}", 
      "name": "Headline {{product.price}}" 
    } 
  }' \
  -F 'template_url_spec={ 
    "ios": { 
      "app_store_id": "123", 
      "url": "example:\/\/link\/?nav=item.view&id={{product.retailer_id | urlencode}}&referrer=http:\/\/rover.example.com\/rover\/1\/711-198453-24755-9\/16%3Fitemid={{product.retailer_id | urlencode | urlencode}}" 
    }, 
    "web": { 
      "url": "http:\/\/clicktrack.com\/cm325?id={{product.retailer_id | urlencode}}&redirect_url={{product.url | urlencode | urlencode}}" 
    } 
  }' \
  -F 'product_set_id=<PRODUCT_SET_ID>' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/adcreatives

Use Product Feed Data in Your Template

When an ad is displays, Facebook replace the content in {{ }} section with the proper values from your Product Feed. Available template values are:

  • brand: The item's brand value from your Product Feed
  • current_price: The formatted sale price if the product has a specified sale price. Optionally you can specify sale start and end dates for a product and current_price will show the sale price while the item is on sale. If no sale price is specified or the sale dates have passed, this will show the price field.
  • description: The item's description value from your Product Feed
  • name: The item's title value from your Product Feed
  • price: The formatted price column (like $1,234.56)
  • retailer_id: The item's id value from your Product Feed
  • url: The item's link value from your Product Feed
  • custom_label_0: The item's custom_label_0 value from your Product Feed
  • custom_label_1: The item's custom_label_1 value from your Product Feed
  • custom_label_2: The item's custom_label_2 value from your Product Feed
  • custom_label_3: The item's custom_label_3 value from your Product Feed
  • custom_label_4: The item's custom_label_4 value from your Product Feed

Options

Some template values may receive options, in any order, in the following format:

{{field option1 option2 ...}}

The following options are available:

Option Description Supported by

raw

Omits the currency symbol

price, current_price

strip_zeros

Omits the cents part in currency if cents are zeros

price, current_price

round

Omits the cent amount of the currency while rounding up the price.

All price fields


Transforms

You can use template values with transformations which adjust your value based on this format

{{field | transform}}

Use one of these transformations:

Transform Description

number_format

Format the number in default format, using comma (",") as thousand separator, rounded to the nearest integer. E.g. 1234.56->"1,235". The value to format must be an unformatted number ("1234", not "1,234").

titleize

Capitalize the words for a better looking title, e.g. "box" -> "Box"

urlencode

Encode the value for URL.


When you display Dynamic Creative, you can specify the desired behavior when a someone clicks on the ad in the native Facebook app. There are two requirements to be able to use deep linking:

  1. The native mobile app where the user should be sent to supports deep linking (iOS or Android).
  2. The deep link information has been included in the Product Feed or deep link information is available through App Links.

If both these requirements are fulfilled, you can use the field applink_treatment while creating an ad creative to specify the desired behavior when a user clicks on an ad.

Field Name Description

web_only

Always send the user to the given web URL

deeplink_with_web_fallback

If the app is installed on the user's phone and we have corresponding deep link information, send the user to the app. If one of these conditions is not met, send them to the website.

deeplink_with_appstore_fallback

Default when app links are present for the product. If the app is installed on the user's phone and we have corresponding deep link information, send the user to the app. If the app is not installed, send them to the app store for the app.

Below is an example for creating a carousel dynamic ad template with a call to action that will deep link into a native app if available or fall back to the web:

use FacebookAds\Object\AdCreative;
use FacebookAds\Object\AdCreativeObjectStorySpec;
use FacebookAds\Object\AdCreativeLinkData;
use FacebookAds\Object\Fields\AdCreativeFields;
use FacebookAds\Object\Fields\AdCreativeLinkDataFields;
use FacebookAds\Object\Fields\AdCreativeObjectStorySpecFields;
use FacebookAds\Object\Values\AdCreativeCallToActionTypeValues;

$object_story_spec = new AdCreativeObjectStorySpec();
$object_story_spec->setData(array(
  AdCreativeObjectStorySpecFields::PAGE_ID => <PAGE_ID>,
  AdCreativeObjectStorySpecFields::TEMPLATE_DATA =>
    (new AdCreativeLinkData())->setData(array(
      AdCreativeLinkDataFields::CALL_TO_ACTION => array(
        'type' => AdCreativeCallToActionTypeValues::SHOP_NOW,
      ),
      AdCreativeLinkDataFields::MESSAGE => 'Test {{product.name | titleize}}',
      AdCreativeLinkDataFields::LINK => '<LINK>',
      AdCreativeLinkDataFields::NAME => 'Headline {{product.price}}',
      AdCreativeLinkDataFields::DESCRIPTION =>
        'Description {{product.description}}',
    )),
));

$creative = new AdCreative(null, 'act_<AD_ACCOUNT_ID>');

$creative->setData(array(
  AdCreativeFields::NAME => 'Dynamic Ad Template Creative Sample',
  AdCreativeFields::APPLINK_TREATMENT => 'deeplink_with_web_fallback',
  AdCreativeFields::OBJECT_STORY_SPEC => $object_story_spec,
  AdCreativeFields::PRODUCT_SET_ID => <PRODUCT_SET_ID>,
));

$creative->create();
from facebookads.adobjects.adcreative import AdCreative
from facebookads.adobjects.adcreativeobjectstoryspec \
    import AdCreativeObjectStorySpec

story = AdCreativeObjectStorySpec()
story[story.Field.page_id] = <PAGE_ID>
story[story.Field.template_data] = {
    'call_to_action': {'type': 'SHOP_NOW'},
    'message': 'Test {{product.name | titleize}}',
    'link': '<LINK>',
    'name': 'Headline {{product.price}}',
    'description': 'Description {{product.description}}',
}

creative = AdCreative(parent_id='act_<AD_ACCOUNT_ID>')
creative[AdCreative.Field.name] = 'Dynamic Ad Template Creative Sample'
creative[AdCreative.Field.applink_treatment] = 'deeplink_with_web_fallback'
creative[AdCreative.Field.object_story_spec] = story
creative[AdCreative.Field.product_set_id] = <PRODUCT_SET_ID>
creative.remote_create()
AdCreative adCreative = new AdAccount(act_<AD_ACCOUNT_ID>, context).createAdCreative()
  .setName("Dynamic Ad Template Creative Sample")
  .setApp<LINK>Treatment(AdCreative.EnumApp<LINK>Treatment.VALUE_DEEPLINK_WITH_WEB_FALLBACK)
  .setObjectStorySpec(
    new AdCreativeObjectStorySpec()
      .setFieldPageId(<PAGE_ID>)
      .setFieldTemplateData(
        new AdCreativeLinkData()
          .setFieldCallToAction(
            new AdCreativeLinkDataCallToAction()
              .setFieldType(AdCreativeLinkDataCallToAction.EnumType.VALUE_SHOP_NOW)
          )
          .setFieldDescription("Description {{product.description}}")
          .setFieldLink(<LINK>)
          .setFieldMessage("Test {{product.name | titleize}}")
          .setFieldName("Headline {{product.price}}")
      )
  )
  .setProductSetId(<PRODUCT_SET_ID>)
  .execute();
String ad_creative_id = adCreative.getId();
curl \
  -F 'name=Dynamic Ad Template Creative Sample' \
  -F 'applink_treatment=deeplink_with_web_fallback' \
  -F 'object_story_spec={ 
    "page_id": "<PAGE_ID>", 
    "template_data": { 
      "call_to_action": {"type":"SHOP_NOW"}, 
      "description": "Description {{product.description}}", 
      "link": "<LINK>", 
      "message": "Test {{product.name | titleize}}", 
      "name": "Headline {{product.price}}" 
    } 
  }' \
  -F 'product_set_id=<PRODUCT_SET_ID>' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/adcreatives

Example of creating a carousel dynamic ad template with URL tags enabled that will deep link into a native app if available or fall back to app store for the app:

use FacebookAds\Object\AdCreative;
use FacebookAds\Object\AdCreativeObjectStorySpec;
use FacebookAds\Object\AdCreativeLinkData;
use FacebookAds\Object\Fields\AdCreativeFields;
use FacebookAds\Object\Fields\AdCreativeLinkDataFields;
use FacebookAds\Object\Fields\AdCreativeObjectStorySpecFields;
use FacebookAds\Object\Values\AdCreativeCallToActionTypeValues;

$object_story_spec = new AdCreativeObjectStorySpec();
$object_story_spec->setData(array(
  AdCreativeObjectStorySpecFields::PAGE_ID => <PAGE_ID>,
  AdCreativeObjectStorySpecFields::TEMPLATE_DATA =>
    (new AdCreativeLinkData())->setData(array(
      AdCreativeLinkDataFields::CALL_TO_ACTION => array(
        'type' => AdCreativeCallToActionTypeValues::SHOP_NOW,
      ),
      AdCreativeLinkDataFields::MESSAGE => 'Test {{product.name | titleize}}',
      AdCreativeLinkDataFields::LINK => '<LINK>',
      AdCreativeLinkDataFields::NAME => 'Headline {{product.price}}',
      AdCreativeLinkDataFields::DESCRIPTION =>
        'Description {{product.description}}',
    )),
));

$creative = new AdCreative(null, 'act_<AD_ACCOUNT_ID>');

$creative->setData(array(
  AdCreativeFields::NAME => 'Dynamic Ad Template Creative Sample',
  AdCreativeFields::APPLINK_TREATMENT => 'deeplink_with_appstore_fallback',
  AdCreativeFields::OBJECT_STORY_SPEC => $object_story_spec,
  AdCreativeFields::PRODUCT_SET_ID => <PRODUCT_SET_ID>,
));

$creative->create();
curl \
  -F 'name=Dynamic Ad Template Creative Sample' \
  -F 'applink_treatment=deeplink_with_appstore_fallback' \
  -F 'object_story_spec={ 
    "page_id": "<PAGE_ID>", 
    "template_data": { 
      "call_to_action": {"type":"SHOP_NOW"}, 
      "description": "Description {{product.description}}", 
      "link": "<LINK>", 
      "message": "Test {{product.name | titleize}}", 
      "name": "Headline {{product.price}}" 
    } 
  }' \
  -F 'product_set_id=<PRODUCT_SET_ID>' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/adcreatives

Create Dynamic Ads in Multiple Languages and Countries

This functionality is provided on a limited basis. Please contact your Facebook representative for more details.

When building a template for Dynamic Ads, you can specify customizations to the creative that are in different languages. For example, you might want to show a different headline to viewers of your ad who speak another language.

In addition to the other fields in the creative's template data (within the object story spec), you can specify an array of customizations, in the field 'customization_rules_spec', where each customization has the form:

Field NameMandatory?DescriptionAccepts Template ParametersTypeExample

customization_ spec

Yes

Describes the language for the customization. Learn how to Create a Dynamic Ad for Multiple Languages and Countries.

No

Object

{'language' => 'en_XX'}

message

No

Message for your ad, visible on Instagram.

Yes

String

Test {{product.name | titleize}}

link

No

Link to your website, used to generate the caption of the ad. This field is always replaced with the link field from your product feed, except the end card of Carousel Ads which will link to this. This cannot be a URL on Facebook.com.

No

String

example: //link.com

name

No

Name or title for your ad, visible on Instagram.

Yes

String

Headline {{product.price}}

description

No

Description for your ad. Not visible on Instagram.

Yes

String

Description {{product. description}}

template_url_spec

No

Can be used to provide a web deep link, as detailed in Click Tracking and Templates. Note: We only support the web deeplink; for example, {'web' => {'url' => DEEP_LINK}}

Yes

Object

{'web' => {'url' => 'example://link/?id={{product. retailer_id}}'}}

When specifying the array of customizations, only one of the customizations should specify only the customization_spec. This identifies the language of the non-customized text that has been used in the template_data.

When the ad is rendered, the rendering language is chosen, based on the viewer's interface language and other signals. Facebook also uses product properties from the catalog language feed to match the rendering language, if available.

Create a Carousel Dynamic Ad Template With Multiple Languages (Example)


curl -X POST \ -F 'name="Dynamic Ad Template Creative Sample"' \ -F 'object_story_spec={ "page_id": "<PAGE_ID>", "template_data": { "message": "English Test {{product.name | titleize}}", "link": "http://www.example.com/englishurl", "name": "English Headline {{product.price}}", "description": "English Description {{product.description}}", "customization_rules_spec": [ { "customization_spec": { "language": "en_XX" } }, { "customization_spec": { "language": "fr_XX" }, "message": "French Test {{product.name | titleize}}", "link": "http://www.example.com/frenchurl", "name": "French Headline {{product.price}}", "description": "French Description {{product.description}}", "template_url_spec": { "web": { "url": "http://www.example.com/frenchdeeplink" } } } ] } }' \ -F 'product_set_id="<PRODUCT_SET_ID>"' \ -F 'template_url_spec={ "web": { "url": "http://www.example.com/englishdeeplink" } }' \ -F 'access_token=<ACCESS_TOKEN>' \ https://graph.facebook.com/v3.2/act_<AD_ACCOUNT_ID>/adcreatives
'use strict'; const bizSdk = require('facebook-nodejs-business-sdk'); const AdAccount = bizSdk.AdAccount; const AdCreative = bizSdk.AdCreative; const access_token = '<ACCESS_TOKEN>'; const app_secret = '<APP_SECRET>'; const app_id = '<APP_ID>'; const id = '<ID>'; const api = bizSdk.FacebookAdsApi.init(access_token); const showDebugingInfo = true; // Setting this to true shows more debugging info. if (showDebugingInfo) { api.setDebug(true); } const logApiCallResult = (apiCallName, data) => { console.log(apiCallName); if (showDebugingInfo) { console.log('Data:' + JSON.stringify(data)); } }; let fields, params; fields = [ ]; params = { 'name' : 'Dynamic Ad Template Creative Sample', 'object_story_spec' : {'page_id':'<pageID>','template_data':{'message':'English Test {{product.name | titleize}}','link':'http://www.example.com/englishurl','name':'English Headline {{product.price}}','description':'English Description {{product.description}}','customization_rules_spec':[{'customization_spec':{'language':'en_XX'}},{'customization_spec':{'language':'fr_XX'},'message':'French Test {{product.name | titleize}}','link':'http://www.example.com/frenchurl','name':'French Headline {{product.price}}','description':'French Description {{product.description}}','template_url_spec':{'web':{'url':'http://www.example.com/frenchdeeplink'}}}]}}, 'product_set_id' : '<productSetID>', 'template_url_spec' : {'web':{'url':'http://www.example.com/englishdeeplink'}}, }; const adcreatives = (new AdAccount(id)).createAdCreative( fields, params ); logApiCallResult('adcreatives api call complete.', adcreatives);
require __DIR__ . '/vendor/autoload.php'; use FacebookAds\Object\AdAccount; use FacebookAds\Object\AdCreative; use FacebookAds\Api; use FacebookAds\Logger\CurlLogger; $access_token = '<ACCESS_TOKEN>'; $app_secret = '<APP_SECRET>'; $app_id = '<APP_ID>'; $id = '<ID>'; $api = Api::init($app_id, $app_secret, $access_token); $api->setLogger(new CurlLogger()); $fields = array( ); $params = array( 'name' => 'Dynamic Ad Template Creative Sample', 'object_story_spec' => array('page_id' => '<pageID>','template_data' => array('message' => 'English Test array(array(product.name | titleize))','link' => 'http://www.example.com/englishurl','name' => 'English Headline array(array(product.price))','description' => 'English Description array(array(product.description))','customization_rules_spec' => array(array('customization_spec' => array('language' => 'en_XX')),array('customization_spec' => array('language' => 'fr_XX'),'message' => 'French Test array(array(product.name | titleize))','link' => 'http://www.example.com/frenchurl','name' => 'French Headline array(array(product.price))','description' => 'French Description array(array(product.description))','template_url_spec' => array('web' => array('url' => 'http://www.example.com/frenchdeeplink')))))), 'product_set_id' => '<productSetID>', 'template_url_spec' => array('web' => array('url' => 'http://www.example.com/englishdeeplink')), ); echo json_encode((new AdAccount($id))->createAdCreative( $fields, $params )->exportAllData(), JSON_PRETTY_PRINT);
from facebook_business.adobjects.adaccount import AdAccount from facebook_business.adobjects.adcreative import AdCreative from facebook_business.api import FacebookAdsApi access_token = '<ACCESS_TOKEN>' app_secret = '<APP_SECRET>' app_id = '<APP_ID>' id = '<ID>' FacebookAdsApi.init(access_token=access_token) fields = [ ] params = { 'name': 'Dynamic Ad Template Creative Sample', 'object_story_spec': {'page_id':'<pageID>','template_data':{'message':'English Test {{product.name | titleize}}','link':'http://www.example.com/englishurl','name':'English Headline {{product.price}}','description':'English Description {{product.description}}','customization_rules_spec':[{'customization_spec':{'language':'en_XX'}},{'customization_spec':{'language':'fr_XX'},'message':'French Test {{product.name | titleize}}','link':'http://www.example.com/frenchurl','name':'French Headline {{product.price}}','description':'French Description {{product.description}}','template_url_spec':{'web':{'url':'http://www.example.com/frenchdeeplink'}}}]}}, 'product_set_id': '<productSetID>', 'template_url_spec': {'web':{'url':'http://www.example.com/englishdeeplink'}}, } print AdAccount(id).create_ad_creative( fields=fields, params=params, )
import com.facebook.ads.sdk.*; import java.io.File; import java.util.Arrays; public class SAMPLE_CODE_EXAMPLE { public static void main (String args[]) throws APIException { String access_token = \"<ACCESS_TOKEN>\"; String app_secret = \"<APP_SECRET>\"; String app_id = \"<APP_ID>\"; String id = \"<ID>\"; APIContext context = new APIContext(access_token).enableDebug(true); new AdAccount(id, context).createAdCreative() .setName(\"Dynamic Ad Template Creative Sample\") .setObjectStorySpec( new AdCreativeObjectStorySpec() .setFieldPageId(\"<pageID>\") .setFieldTemplateData( new AdCreativeLinkData() .setFieldCustomizationRulesSpec(Arrays.asList( new AdCustomizationRuleSpec() .setFieldCustomizationSpec(\"{\\"language\\":\\"en_XX\\"}\") , new AdCustomizationRuleSpec() .setFieldCustomizationSpec(\"{\\"language\\":\\"fr_XX\\"}\") .setFieldDescription(\"French Description {{product.description}}\") .setFieldLink(\"http://www.example.com/frenchurl\") .setFieldMessage(\"French Test {{product.name | titleize}}\") .setFieldName(\"French Headline {{product.price}}\") .setFieldTemplateUrlSpec( new AdCreativeTemplateURLSpec() .setFieldWeb(\"{\\"url\\":\\"http://www.example.com/frenchdeeplink\\"}\") ) )) .setFieldDescription(\"English Description {{product.description}}\") .setFieldLink(\"http://www.example.com/englishurl\") .setFieldMessage(\"English Test {{product.name | titleize}}\") .setFieldName(\"English Headline {{product.price}}\") ) ) .setProductSetId(\"<productSetID>\") .setTemplateUrlSpec(\"{\\"web\\":{\\"url\\":\\"http://www.example.com/englishdeeplink\\"}}\") .execute(); } }
require 'facebook_ads' access_token = '<ACCESS_TOKEN>' app_secret = '<APP_SECRET>' app_id = '<APP_ID>' id = '<ID>' FacebookAds.configure do |config| config.access_token = access_token config.app_secret = app_secret end ad_account = FacebookAds::AdAccount.get(id) adcreatives = ad_account.adcreatives.create({ name: 'Dynamic Ad Template Creative Sample', object_story_spec: {'page_id':'<pageID>','template_data':{'message':'English Test {{product.name | titleize}}','link':'http://www.example.com/englishurl','name':'English Headline {{product.price}}','description':'English Description {{product.description}}','customization_rules_spec':[{'customization_spec':{'language':'en_XX'}},{'customization_spec':{'language':'fr_XX'},'message':'French Test {{product.name | titleize}}','link':'http://www.example.com/frenchurl','name':'French Headline {{product.price}}','description':'French Description {{product.description}}','template_url_spec':{'web':{'url':'http://www.example.com/frenchdeeplink'}}}]}}, product_set_id: '<productSetID>', template_url_spec: {'web':{'url':'http://www.example.com/englishdeeplink'}}, })

Learn more about how to Create a Dynamic Ad for Multiple Languages and Countries.

Finally, you can create a Dynamic Ad. The Ad references an Ad Creative.

For example:

curl -X POST \ -F 'name="My Ad"' \ -F 'adset_id="<AD_SET_ID>"' \ -F 'creative={ "creative_id": "<CREATIVE_ID>" }' \ -F 'status="PAUSED"' \ -F 'access_token=<ACCESS_TOKEN>' \ https://graph.facebook.com/v3.2/act_<AD_ACCOUNT_ID>/ads
'use strict'; const bizSdk = require('facebook-nodejs-business-sdk'); const AdAccount = bizSdk.AdAccount; const Ad = bizSdk.Ad; const access_token = '<ACCESS_TOKEN>'; const app_secret = '<APP_SECRET>'; const app_id = '<APP_ID>'; const id = '<ID>'; const api = bizSdk.FacebookAdsApi.init(access_token); const showDebugingInfo = true; // Setting this to true shows more debugging info. if (showDebugingInfo) { api.setDebug(true); } const logApiCallResult = (apiCallName, data) => { console.log(apiCallName); if (showDebugingInfo) { console.log('Data:' + JSON.stringify(data)); } }; let fields, params; fields = [ ]; params = { 'name' : 'My Ad', 'adset_id' : '<adSetID>', 'creative' : {'creative_id':'<adCreativeID>'}, 'status' : 'PAUSED', }; const ads = (new AdAccount(id)).createAd( fields, params ); logApiCallResult('ads api call complete.', ads);
require __DIR__ . '/vendor/autoload.php'; use FacebookAds\Object\AdAccount; use FacebookAds\Object\Ad; use FacebookAds\Api; use FacebookAds\Logger\CurlLogger; $access_token = '<ACCESS_TOKEN>'; $app_secret = '<APP_SECRET>'; $app_id = '<APP_ID>'; $id = '<ID>'; $api = Api::init($app_id, $app_secret, $access_token); $api->setLogger(new CurlLogger()); $fields = array( ); $params = array( 'name' => 'My Ad', 'adset_id' => '<adSetID>', 'creative' => array('creative_id' => '<adCreativeID>'), 'status' => 'PAUSED', ); echo json_encode((new AdAccount($id))->createAd( $fields, $params )->exportAllData(), JSON_PRETTY_PRINT);
from facebook_business.adobjects.adaccount import AdAccount from facebook_business.adobjects.ad import Ad from facebook_business.api import FacebookAdsApi access_token = '<ACCESS_TOKEN>' app_secret = '<APP_SECRET>' app_id = '<APP_ID>' id = '<ID>' FacebookAdsApi.init(access_token=access_token) fields = [ ] params = { 'name': 'My Ad', 'adset_id': '<adSetID>', 'creative': {'creative_id':'<adCreativeID>'}, 'status': 'PAUSED', } print AdAccount(id).create_ad( fields=fields, params=params, )
import com.facebook.ads.sdk.*; import java.io.File; import java.util.Arrays; public class SAMPLE_CODE_EXAMPLE { public static void main (String args[]) throws APIException { String access_token = \"<ACCESS_TOKEN>\"; String app_secret = \"<APP_SECRET>\"; String app_id = \"<APP_ID>\"; String id = \"<ID>\"; APIContext context = new APIContext(access_token).enableDebug(true); new AdAccount(id, context).createAd() .setName(\"My Ad\") .setAdsetId(<adSetID>L) .setCreative( new AdCreative() .setFieldId(\"<adCreativeID>\") ) .setStatus(Ad.EnumStatus.VALUE_PAUSED) .execute(); } }
require 'facebook_ads' access_token = '<ACCESS_TOKEN>' app_secret = '<APP_SECRET>' app_id = '<APP_ID>' id = '<ID>' FacebookAds.configure do |config| config.access_token = access_token config.app_secret = app_secret end ad_account = FacebookAds::AdAccount.get(id) ads = ad_account.ads.create({ name: 'My Ad', adset_id: '<adSetID>', creative: {'creative_id':'<adCreativeID>'}, status: 'PAUSED', })

Congratulations! You have created your first Dynamic Ad. Feel free to unpause it to start delivery.

What's Next

Preview Dynamic Ads

You can generate previews of your dynamic creative with Ad Previews API. Specifying the product_item_ids parameter or specify multiple product_item_ids in to preview a Carousel Ad.

use FacebookAds\Object\AdCreative;
use FacebookAds\Object\Fields\AdPreviewFields;
use FacebookAds\Object\Values\AdPreviewAdFormatValues;

// $creative = new AdCreative(<CREATIVE_ID>);
$creative = new AdCreative(<CREATIVE_ID>);
$preview = $creative->getPreviews(array(), array(
  AdPreviewFields::AD_FORMAT => AdPreviewAdFormatValues::DESKTOP_FEED_STANDARD,
  AdPreviewFields::PRODUCT_ITEM_IDS => array(
    'catalog:'.<CATALOG_ID>.':'.base64_encode('<RETAILER_ID>')
  ),
));
import base64
from facebookads.adobjects.adcreative import AdCreative
from facebookads.adobjects.adpreview import AdPreview

item_id = '<RETAILER_ID>'
b64_id = base64.urlsafe_b64encode(item_id.encode('utf8'))
b64_encoded_id = b64_id.decode('utf8')

creative = AdCreative(<CREATIVE_ID>)
params = {
    AdPreview.Field.ad_format:
        AdPreview.AdFormat.desktop_feed_standard,
    AdPreview.Field.product_item_ids: [
        "catalog:%s:%s" % (<CATALOG_ID>, b64_encoded_id),
    ],
}
preview = creative.get_previews(params=params)
curl -G \
  -d 'ad_format=DESKTOP_FEED_STANDARD' \
  -d 'product_item_ids=["catalog:1000005:MTIzNDU2"]' \
  -d 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/<CREATIVE_ID>/previews

Parameters:

Field Name Description Type

product_item_ids

List of Product FBID or Base64url-encoded Product ID tokens. Each token is of the form catalog:{catalog_id}:{base64urlencode(retailer_id)}

array[string]


Fetch Product Ad Statistics

You can fetch statistics per product by making a GET call to the insights endpoint. Add product_id in the fields parameter.

This shows statistics for all products in an account's product sets that displayed in dynamic ads.

For example:

use FacebookAds\Object\AdAccount;
use FacebookAds\Object\Fields\AdsInsightsFields;
use FacebookAds\Object\Values\AdsInsightsActionBreakdownsValues;
use FacebookAds\Object\Values\AdsInsightsDatePresetValues;
use FacebookAds\Object\Values\AdsInsightsBreakdownsValues;

$account = new AdAccount('act_<AD_ACCOUNT_ID>');

$fields = array(
  AdsInsightsFields::ACCOUNT_NAME,
  AdsInsightsFields::IMPRESSIONS,
  AdsInsightsFields::ACTIONS,
);

$params = array(
  'date_preset' => AdsInsightsDatePresetValues::LAST_WEEK,
  'action_breakdowns' => array(
    AdsInsightsActionBreakdownsValues::ACTION_TYPE,
  ),
  'breakdowns' => array(
    AdsInsightsBreakdownsValues::PRODUCT_ID,
  ),
);

$stats = $account->getInsights($fields, $params);
from facebookads.adobjects.adaccount import AdAccount
from facebookads.adobjects.adsinsights import AdsInsights

account = AdAccount('act_<AD_ACCOUNT_ID>')

fields = [
    AdsInsights.Field.account_name,
    AdsInsights.Field.impressions,
    AdsInsights.Field.actions,
]

params = {
    'date_preset': 'last_week',
    'actions_group_by': ['action_type'],
    'breakdowns': [
        AdsInsights.Breakdowns.product_id,
    ],
}

stats = account.get_insights(fields=fields, params=params)
APINodeList<AdsInsights> adsInsightss = new AdAccount(act_<AD_ACCOUNT_ID>, context).getInsights()
  .setDatePreset(AdsInsights.EnumDatePreset.VALUE_LAST_WEEK)
  .setActionBreakdowns("[\"action_type\"]")
  .setBreakdowns("[\"product_id\"]")
  .requestField("account_name")
  .requestField("impressions")
  .requestField("actions")
  .execute();
curl -G \
  -d 'date_preset=last_week' \
  -d 'action_breakdowns=["action_type"]' \
  -d 'breakdowns=["product_id"]' \
  -d 'fields=account_name,impressions,actions' \
  -d 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.8/act_<AD_ACCOUNT_ID>/insights

Sample Response:

{
 "data": [ 
   {
      "account_id": "123456", 
      "product_id": "60750", 
      "date_start": "2015-02-03", 
      "date_stop": "2015-02-03", 
      "impressions": 880, 
      "clicks": 8, 
      "actions": [ 
        {
          "action_type": "link_click", 
          "value": 6
        }, 
        {
          "action_type": "offsite_conversion.other", 
          "value": 5
        },  
        {
          "action_type": "offsite_conversion", 
          "value": 5
        }
      ], 
      "account_name": "My Account"
    }, 
 ], 
...
}

This example above report clicks, actions and impressions for each product_id.


Fetch Comments and Likes

You can retrieve the comments, likes, and the product_id for a dynamic ad post. Make a GET call as follows with a post_id. The post_id is the effective_object_story_id of an ad creative, in the format of "PageID_PostID".

curl -G \
  -d 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/<API_VERSION>/<POST_ID>/dynamic_posts

This API returns Dynamic Post objects.

Once you get dynamic posts, you can then fetch comments, instagram_comments, likes, product_id, and child_attachments for carousel format if applicable.

Previous: Build Product Audiences

< Build Product Audiences