Marketing API Version

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 or LINK_CLICKS 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.9/act_<AD_ACCOUNT_ID>/campaigns

Step 2. Create an Ad Set

Related Topics

In this section, we'll cover how to create 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.9/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 NameDescriptionTypeRequired

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

Yes

retention_seconds

The number of seconds to keep the person in the audience

int

Yes

rule

Website Custom Audience Rule referencing one event

object[]

Yes

exclusions

A set of events that remove a person from targeting

JSON object

No

retention_seconds

The number seconds to retain the exclusion

int

Yes if exclusion is specified

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.9/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 ad to existing users who have shown interest in shoes which 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.9/act_<AD_ACCOUNT_ID>/adsets

And set product_set_id in the creative as <PRODUCT_SET_1> i.e. 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.9/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, utiling age, gender and interest 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 of customers using basic age, gender and interest based targeting.
  • Consider excluding customers targeted by existing retargeting campaigns.
  • Use a broad product set.
  • Optimize for OFFSITE_CONVERSIONS on lower funnel events such as Purchase or Add To Cart.

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

curl \
-F 'name=Broad Audience Targeting' \
-F 'bid_amount=800' \
-F 'billing_event=IMPRESSIONS' \
-F 'status=ACTIVE' \
-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": "2592000", \
                     "rule": "{\"event\":{\"eq\":\"Purchase\"}}" \
                   } \
                 ] \
               } \
            ] \
        }' \
-F 'promoted_object={"product_set_id”:<PRODUCT_SET_ID>, "custom_event_type": "PURCHASE" }' \
-F 'optimization_goal=OFFSITE_CONVERSIONS' \
-F 'access_token=<ACCESS_TOKEN>’ \
https://graph.facebook.com/<API_VERSION>/act_<ACCOUNT_ID>/adsets

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 NameDescriptionAccepts Template ParametersType

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 the main product image will be used.

No

int

caption

Use this optional field to provide a caption on the last card in a carousel ad.

No

string

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

An example to create a Carousel dynamic ad template:

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.9/act_<AD_ACCOUNT_ID>/adcreatives

Example to create a single product dynamic ad template with a call to action:

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.9/act_<AD_ACCOUNT_ID>/adcreatives

Example to create a carousel dynamic ad template where the ad image will be using the first image from the additional images array:

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}}",
             "additional_image_index": 0
           }
         }' \
     -F 'product_set_id=<PRODUCT_SET_ID>' \
     -F 'access_token=<ACCESS_TOKEN>' \
https://graph.facebook.com/<API_VERSION>/act_<AD_ACCOUNT_ID>/adcreatives

Example to create a carousel dynamic ad template for a single product, where each image comes from the additional images array in the catalog:

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


Example to create a carousel dynamic ad template with first card as coupon static card:

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.9/act_<AD_ACCOUNT_ID>/adcreatives

The response to those calls is the id of a new Dynamic Ad Template Creative.

{"id":"creative_id"}

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.9/act_<AD_ACCOUNT_ID>/adcreatives

Product Feed Data in Templates

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:

OptionDescriptionSupported by

raw

Omits the currency symbol

price, current_price

strip_zeros

Omits the cents part in currency if cents are zeros

price, current_price


Transforms

Template values can also be used with transforms, in the following format:

{{field | transform}}

The following transforms are available:

TransformDescription

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 NameDescription

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.9/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:

curl -X POST \
     -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"
             },
             "message": "Test {{product.name | titleize}}",
             "link": "<<YOUR_LINK_URL>>",
             "name": "Headline {{product.price}}",
             "description": "Description {{product.description}}",
           }
         }' \
     -F 'url_tags="key1=val1&key2=val2"' \
     -F 'product_set_id=<PRODUCT_SET_ID>' \
     -F 'access_token=<ACCESS_TOKEN>' \
https://graph.facebook.com/<API_VERSION>/act_<AD_ACCOUNT_ID>/adcreatives

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

For example:

use FacebookAds\Object\Ad;
use FacebookAds\Object\Fields\AdFields;

$data = array(
  AdFields::NAME => 'My Ad',
  AdFields::ADSET_ID => <AD_SET_ID>,
  AdFields::CREATIVE => array(
    'creative_id' => <CREATIVE_ID>,
  ),
);

$ad = new Ad(null, 'act_<AD_ACCOUNT_ID>');
$ad->setData($data);
$ad->create(array(
  Ad::STATUS_PARAM_NAME => Ad::STATUS_PAUSED,
));
from facebookads.adobjects.ad import Ad

ad = Ad(parent_id='act_<AD_ACCOUNT_ID>')
ad[Ad.Field.name] = 'My Ad'
ad[Ad.Field.adset_id] = <AD_SET_ID>
ad[Ad.Field.creative] = {
    'creative_id': <CREATIVE_ID>,
}
ad.remote_create(params={
    'status': Ad.Status.paused,
})
Ad ad = new AdAccount(act_<AD_ACCOUNT_ID>, context).createAd()
  .setName("My Ad")
  .setAdsetId(<AD_SET_ID>)
  .setCreative(
    new AdCreative()
      .setFieldId(<CREATIVE_ID>)
  )
  .setStatus(Ad.EnumStatus.VALUE_PAUSED)
  .execute();
curl \
  -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/v2.9/act_<AD_ACCOUNT_ID>/ads

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.9/<CREATIVE_ID>/previews

Parameters:

Field NameDescriptionType

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