Dynamic Creative

Automatically experiment and deliver different variations of an ad's creative. This helps you find the best ad creative combination per impression by taking your ad's images, titles, descriptions, and other assets, then learning from outcomes of how these combinations perform across audiences.

Build and display the best creatives for groups of people in your broader target audience. This improves your ability to efficiently explore numerous creative combinations and audiences. Dynamic Creative can improve ads ROI by:

  • Automating workflow used to test creative
  • Choosing the effective combination of creative assets through learning across audiences

Dynamic creative supports the following Campaign Objectives:

To use this API:

  1. Create a campaign.
  2. Create an ad set.
  3. Create an ad and specify asset feed, or create an asset feed and reference it in your ad.

For Conversions

Creating a Dynamic Creative Campaign to optimize for conversions is the same as a normal campaign.

Requirements:

  • objective— Must be CONVERSIONS.
  • buying_type— Must be the default, AUCTION, or left blank.
curl 
-F "name=Dynamic Creative Sample Campaign" 
-F "objective=CONVERSIONS" 
-F "access_token=ACCESS_TOKEN" 
https://graph.facebook.com/API_VERSION/act_AD_ACCOUNT_ID/campaigns

On success, you get a new Campaign ID:

{"id":"23842500259110001"}

Create an Ad Set

Create an ad set you normally do. For Dynamic Creative, you must fulfill these requirements:

  • optimization_goal=CONVERSIONS or any other valid optimization goal for this objective
  • billing_event=OFFSITE_CONVERSIONS (default), LINK_CLICKS, REACH, IMPRESSIONS or any other valid billing event for this objective
  • promoted_object—For pixel conversion, must provide pixel_id and custom_event_type. For app engagement, must provide application_id, custom_event_type and object_store_url.
  • targeting'publisher_platforms':['facebook', 'audience_network']
  • lifetime_imps— Don't use.
  • is_autobid or bid_amount— Must specify one. You must also match bidding type and value for a non-DCO ad set if you want to compare regular ads against ads generated by dynamic creative.

For example:

curl -X POST \ -F 'name=Dynamic Creative Ad Set' \ -F 'campaign_id=<AD_CAMPAIGN_ID>' \ -F 'optimization_goal=OFFSITE_CONVERSIONS' \ -F 'billing_event=IMPRESSIONS' \ -F 'is_autobid=true' \ -F 'promoted_object={"pixel_id":"<PIXEL_ID>","custom_event_type":"PURCHASE"}' \ -F 'lifetime_budget=500000' \ -F 'start_time=2018-07-16T09:14:22-0700' \ -F 'end_time=2018-07-23T09:14:22-0700' \ -F 'targeting={"geo_locations":{"countries":["US"]},"publisher_platforms":["facebook","audience_network"],"custom_audiences":[{"id":"<CUSTOM_AUDIENCE_ID>"}]}' \ -F 'access_token=<ACCESS_TOKEN>' \ https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/adsets
const adsSdk = require('facebook-nodejs-ads-sdk'); const AdAccount = adsSdk.AdAccount; const AdSet = adsSdk.AdSet; let access_token = '<ACCESS_TOKEN>'; let app_secret = '<APP_SECRET>'; let app_id = '<APP_ID>'; let id = '<ID>'; const api = adsSdk.FacebookAdsApi.init(access_token); const showDebugingInfo = true; // Setting this to true shows more debugging info. if (showDebugingInfo) { api.setDebug(true); } const fields = [ ]; const params = { 'name' : 'Dynamic Creative Ad Set', 'campaign_id' : '<adCampaignConversionsID>', 'optimization_goal' : 'OFFSITE_CONVERSIONS', 'billing_event' : 'IMPRESSIONS', 'is_autobid' : 'true', 'promoted_object' : {'pixel_id':'<pixelID>','custom_event_type':'PURCHASE'}, 'lifetime_budget' : '500000', 'start_time' : '2018-07-09T20:28:35-0700', 'end_time' : '2018-07-16T20:28:35-0700', 'targeting' : {'geo_locations':{'countries':['US']},'publisher_platforms':['facebook','audience_network'],'custom_audiences':[{'id':'<customAudienceID>'}]}, }; (new AdAccount(id)).createAdSet( fields, params ) .then((result) => { adsets_id = result.id; console.log(adsets_id); }) .catch((error) => { console.log(error); });
require __DIR__ . '/vendor/autoload.php'; use FacebookAds\Object\AdAccount; use FacebookAds\Object\AdSet; 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 Creative Ad Set', 'campaign_id' => '<adCampaignConversionsID>', 'optimization_goal' => 'OFFSITE_CONVERSIONS', 'billing_event' => 'IMPRESSIONS', 'is_autobid' => 'true', 'promoted_object' => array('pixel_id' => '<pixelID>','custom_event_type' => 'PURCHASE'), 'lifetime_budget' => '500000', 'start_time' => '2018-07-09T20:28:35-0700', 'end_time' => '2018-07-16T20:28:35-0700', 'targeting' => array('geo_locations' => array('countries' => array('US')),'publisher_platforms' => array('facebook','audience_network'),'custom_audiences' => array(array('id' => '<customAudienceID>'))), ); echo json_encode((new AdAccount($id))->createAdSet( $fields, $params )->getResponse()->getContent(), JSON_PRETTY_PRINT);
from facebookads.adobjects.adaccount import AdAccount from facebookads.adobjects.adset import AdSet from facebookads.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 Creative Ad Set', 'campaign_id': '<adCampaignConversionsID>', 'optimization_goal': 'OFFSITE_CONVERSIONS', 'billing_event': 'IMPRESSIONS', 'is_autobid': 'true', 'promoted_object': {'pixel_id':'<pixelID>','custom_event_type':'PURCHASE'}, 'lifetime_budget': '500000', 'start_time': '2018-07-09T20:28:35-0700', 'end_time': '2018-07-16T20:28:35-0700', 'targeting': {'geo_locations':{'countries':['US']},'publisher_platforms':['facebook','audience_network'],'custom_audiences':[{'id':'<customAudienceID>'}]}, } print AdAccount(id).create_ad_set( 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).createAdSet() .setName(\"Dynamic Creative Ad Set\") .setCampaignId(\"<adCampaignConversionsID>\") .setOptimizationGoal(AdSet.EnumOptimizationGoal.VALUE_OFFSITE_CONVERSIONS) .setBillingEvent(AdSet.EnumBillingEvent.VALUE_IMPRESSIONS) .setIsAutobid(true) .setPromotedObject(\"{\\"pixel_id\\":\\"<pixelID>\\",\\"custom_event_type\\":\\"PURCHASE\\"}\") .setLifetimeBudget(500000L) .setStartTime(\"2018-07-09T20:28:35-0700\") .setEndTime(\"2018-07-16T20:28:35-0700\") .setTargeting( new Targeting() .setFieldCustomAudiences(Arrays.asList( new IDName() .setFieldId(\"<customAudienceID>\") )) .setFieldGeoLocations( new TargetingGeoLocation() .setFieldCountries(Arrays.asList(\"US\")) ) .setFieldPublisherPlatforms(Arrays.asList(\"facebook\", \"audience_network\")) ) .execute(); } }
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) ad_account.adsets.create({ name: 'Dynamic Creative Ad Set', campaign_id: '<adCampaignConversionsID>', optimization_goal: 'OFFSITE_CONVERSIONS', billing_event: 'IMPRESSIONS', is_autobid: 'true', promoted_object: {'pixel_id':'<pixelID>','custom_event_type':'PURCHASE'}, lifetime_budget: '500000', start_time: '2018-07-09T20:28:35-0700', end_time: '2018-07-16T20:28:35-0700', targeting: {'geo_locations':{'countries':['US']},'publisher_platforms':['facebook','audience_network'],'custom_audiences':[{'id':'<customAudienceID>'}]}, })

This returns a new ad set ID:

{"id":"23842500259260001"}

For App Installs

Creating a Dynamic Creative campaign is the same as a normal campaign with the objective of app installs. You must fulfill these requirements:

  • objectiveAPP_INSTALLS.
  • buying_type— Must be the default, AUCTION, or no value.
curl 
-F "name=Dynamic Creative Sample Campaign" 
-F "objective=APP_INSTALLS" 
-F "access_token=ACCESS_TOKEN" 
https://graph.facebook.com/API_VERSION/act_AD_ACCOUNT_ID/campaigns

On success, you get a new Campaign ID:

{"id":"23842500259110001"}

Create an Ad Set

Create an ad set as you ususally do for app installs. However you must meet these requirements:

  • optimization_goal - APP_INSTALLS, OFFSITE_CONVERSIONS, LINK_CLICKS or any other valid optimization goal for this objective
  • billing_event - IMPRESSIONS, APP_INSTALLS or any other valid billing event for this objective
  • promoted_object — Must provide object_store_url and application_id. URL must match asset feed's link_urls
  • targeting'publisher_platforms':['facebook', 'audience_network']
  • lifetime_imps— Do not use.
  • is_autobid or bid_amount— Must specify one, must match bidding type and value for regular ad set if you are comparing dynamic creative and regular ads.

For example, to create your ad set:

curl 
-F "name=Dynamic Creative AdSet" 
-F "campaign_id=CAMPAIGN_ID" 
-F "optimization_goal=APP_INSTALLS" 
-F "billing_event=IMPRESSIONS" 
-F "is_autobid=true" 
-F "promoted_object={'object_store_url':'https://itunes.apple.com/us/app/facebook/id284882215','application_id':ADVERTISED_APP_ID}"  // object_store_url must match what is provided in asset feed's link_urls 
-F "lifetime_budget=20000" 
-F "end_time=1461974400" 
-F "targeting={
     'geo_locations':{'countries':['US']},
     'age_min':18,
     'age_max':24,
     'publisher_platforms':['facebook', 'audience_network'],
     'user_os':['ios']
   }" 
-F "access_token=ACCESS_TOKEN" 
https://graph.facebook.com/API_VERSION/act_AD_ACCOUNT_ID/adsets

This returns a new ad set ID.

{"id":"23842500259260001"}

The asset_feed_id parameter was only available on the ad set level in v2.8 and earlier. For later releases, specify an ad creative level as described below. The asset_feed_id parameter on an ad set level remains as a read-only field for legacy ad sets.

link_url parameter in asset feed is required, and must match the ad set's promoted_object. Limit 1 for the APP_INSTALLS objective.

For Link Clicks

Creating your campaign is the same as a normal campaign with these additional requirements:

  • objective — Must be LINK_CLICKS.
  • buying_type — Must be the default, AUCTION, or left blank.
curl 
-F "name=Dynamic Creative Sample Campaign" 
-F "objective=LINK_CLICKS" 
-F "access_token=ACCESS_TOKEN" 
https://graph.facebook.com/API_VERSION/act_AD_ACCOUNT_ID/campaigns

On success, you get a new Campaign ID:

{"id":"23842500259110001"}

Create an Ad Set

Create an ad set as you would for any other campaign.

Requirements:

  • optimization_goal=LINK_CLICKS or any other valid optimization goal for this objective
  • billing_event=IMPRESSIONS, CLICKS or any other valid billing event for this objective
  • promoted_object—Not required. For app engagement, you should provide application_id and object_store_url.
  • targeting'publisher_platforms':['facebook', 'audience_network', 'instagram'], 'facebook_positions':['feed']
  • lifetime_imps—Don't use.
  • is_autobid or bid_amount—Must specify one, must match bidding type and value for regular ad set if you are comparing regular ad sets generated by dynamic creative.

For example for a plink clicks ad set:

curl 
-F "name=Dynamic Creative Ad Set" 
-F "campaign_id=CAMPAIGN_ID" 
-F "optimization_goal=LINK_CLICKS" 
-F "billing_event=IMPRESSIONS" 
-F "is_autobid=true" 
-F "lifetime_budget=500000" 
-F "end_time=1461974400" 
-F "targeting={
     'geo_locations':{'countries':['US']},
     'publisher_platforms':['facebook', 'audience_network', 'instagram']
   }" 
-F "tracking_specs=[
        {
          'action.type': [
            'offsite_conversion'
          ],
          'fb_pixel': [
            'PIXEL_ID'
          ]
        }
    ]" 
-F "access_token=ACCESS_TOKEN" 
https://graph.facebook.com/API_VERSION/act_AD_ACCOUNT_ID/adsets

This returns a new ad set ID:

{"id":"23842500259260001"}

Note: asset_feed_id was available on an ad set level; however, you should now specify asset_feed_id on an ad creative level. See Providing ad creative. The asset_feed_id on the ad set level remains as a read-only field for existing ad sets.

Provide Ad Creative

Specify asset_feed_id or asset_feed_spec, page_id, and instagram_actor_id, if applicable, on the ad creative.

  • asset_feed_spec allows you to create the asset feed inline with the creative.
  • asset_feed_id requires you create the asset feed first, then reference it in ad creative creation.

If you are using carousel ads for your ad format, you cannot use these features from carousel ads:

  • BODY_LABEL
  • CALL_TO_ACTION_TYPE_LABEL
  • LINK_URL_LABEL
  • CAPTION_LABEL
  • AD_FORMAT_LABEL

For example, create a dynamic creative ad creative with asset_feed_spec:

curl 
  -F 'access_token=ACCESS_TOKEN' 
  -F 'object_story_spec={
       "page_id": "YOUR_PAGE_ID"
       "instagram_actor_id" : "INSTAGRAM_ACTOR_ID", // only used for instagram placement
    }' 
  -F "asset_feed_spec={'images': [{'hash':'1cd8e1b5de5a76c24f989d94160bfb06'}, {'hash':'2cd8e1b5de5a76c24f989d94160bfb06'}], 'bodies': [{'text':'Begin Your Adventure'}, {'text':'Once a Trainer, always a Trainer.'}], 'titles': [{'text':'Level Up'}, {'text':'Swipe to evolve'}], 'descriptions': [{'text':'Begin Your Adventure'}], 'ad_formats': ['SINGLE_IMAGE'], 'link_urls': [{'website_url':'<WEBSITE_URL>'}]}" 
https://graph.facebook.com/API_VERSION/act_AD_ACCOUNT_ID/adcreatives

See also asset feed parameters for asset feed spec.

To create a ad creative with asset_feed_id: {#asset_feed_id}

curl 
  -F 'access_token=ACCESS_TOKEN' 
  -F 'object_story_spec={
       "page_id": "YOUR_PAGE_ID"
       "instagram_actor_id" : "INSTAGRAM_ACTOR_ID", // only used for instagram placement
    }' 
  -F 'asset_feed_id=<ASSET_FEED_ID>'
https://graph.facebook.com/API_VERSION/act_AD_ACCOUNT_ID/adcreatives

See Create Asset Feeds for details on asset feeds.

Because dynamic creative is a new system, it can be difficult to set up a baseline to compare dynamic creative ad performance with the performance of standard ads. We recommend that you use split testing to measure the performance of Ad sets generated by dynamic creative against the ads in our current system. You can cleanly split the user groups and avoid overlap. Once you've determined if it performs better for you, we recommend to shift all ads into a Dynamic Creative asset feed and stop running split tests.

When you create your dynamic creative ad, the ad set must be empty, and only one ad creation is allowed. Additional dynamic creative ads must be created in a new ad set. Once created, you cannot delete or archive your dynamic creative ad. Instead, you should delete or archive the associated ad set.

curl 
  -F 'name=Dynamic Creative Ad' 
  -F 'adset_id=ADSET_ID' 
  -F 'access_token=<ACCESS_TOKEN>' 
  -F 'creative={
      "creative_id": CREATIVE_ID,
   }' 
https://graph.facebook.com/API_VERSION/act_AD_ACCOUNT_ID/ads

On success:

Create Asset Feeds

Create your asset feed with different creative elements. You can create an asset feed at this endpoint:

POST https://graph.facebook.com/API_VERSION/act_AD_ACCOUNT_ID/adasset_feeds

On success, you get a new Asset Feed ID:

{"id":"23842500259010001"}

If it fails, you get an error; the asset feed does not conform to restrictions listed in asset feed restrictions.

Parameters

The following parameters represent the assets eligible for ad rendering. Facebook explores combinations of these assets across eligible ad formats and optimizes delivery of the best combination and best format for each user.

Property Name Description Type Required

images

Array of eligible images. Images provided in this array should be included in the ad account's image library

array of list of {"url": "{IMAGE_URL}", "hash": "{IMAGE_HASH}", "url_tags": "{TAG}"}
where either url or hash is required

Required for SINGLE_IMAGE and CAROUSEL_IMAGE format

videos

Array of video_ids. video_ids provided in this array should belong to the ad account

array of list of {"video_id": "{VIDEO_ID}", "thumbnail_url": "{THUMBNAIL_URL}", "url_tags": "{TAG}"}

Required for SINGLE_VIDEO format

bodies

Array of bodies. The primary message or copy of the ad.

array of list of {"text": "{BODY_TEXT}", "url_tags": "{TAG}"}

No

call_to_action_types

Array of call-to-action-type values

array of list of {"{CALL_TO_ACTION}"}. You can provide multiple values up to 5 values.

Required for all objectives except REACH and BRAND AWARENESS

titles

Array of titles. A short headline in the ad, generally shown next to a link, image or video.

array of list of {"text": "{TITLE}", "url_tags": "{TAG}"}

No

descriptions

Array of secondary description text, displayed less prominently than bodies or titles. Generally appears next to a link, image or video. If not specified, Facebook scrapes the link you provide to generate a description just as we do for link ads. Use empty string with single space for blank description if you do not want to use the scraped text.

array of list of {"text": "{DESCRIPTION}", "url_tags": "{TAG}"}

No

link_urls

Array of link URLs

array of list of {"website_url": "{URL}"}

Required. Currently only 1 link url can be used.

ad_formats

Array of Facebook ad formats we should create the ads in. Supported formats are: SINGLE_IMAGE, CAROUSEL_IMAGE, SINGLE_VIDEO

array of strings ["{AD_FORMAT}"]

Yes

Asset Feed Restrictions

  • Ad Formats—Three ad_formats are supported: SINGLE_IMAGE, CAROUSEL_IMAGE, and SINGLE_VIDEO. Only one ad_format is allowed in one asset feed. ad_format counts as one asset in an asset feed.
  • Number of Assets in Asset Feed:
  • Asset feed: Must be a maximum of 30 total assets, such as 10 images + 5 bodies + 5 titles + 5 descriptions + 1 ad_format + 1 link_url + 1 call_to_action_types = 28 assets
  • Total number of images: < 10
  • Recommended image specs: 1.9:1
  • If Instagram placement is included, consider using square images for better performance
  • Recommended image size: 1,200 x 628 pixels
  • Total number of videos: < 10
  • If Instagram placement is included, only square videos or landscape videos are allowed
  • Total number of bodies limited to 5
  • Total number of call to actions limited to 5
  • Total number of titles limited to 5
  • Total number of links limited to 1.
  • Total number of descriptions limited to 5. If you do not specify any description, we will scrape the link you provided to retrieve the description as we now do for link ads
  • Title/Description text max length 255.
  • Body text max length 1024.
  • For CAROUSEL_IMAGE format, at least 2 images are required in the Asset Feed, while titles are optional.
  • Asset Feed: Read only; you can re-use asset feed ID, but not edit it. To change or re-use an asset feed, create a new one.
  • url_tags (Optional): Only available for IMAGES, VIDEOS, BODIES, DESCRIPTIONS, and TITLES fields. Facebook appends url_tags to the link URL as parameters for each asset in an ad.

Example of a valid asset feed combination setup for SINGLE_IMAGE format:

  • 5 images
  • 3 bodies
  • 3 titles
  • 3 descriptions
  • 1 format: SINGLE_IMAGE

Example

Create an asset feed with two alternate images, bodies, and titles:

curl 
-F "images=[{'hash':'1cd8e1b5de5a76c24f989d94160bfb06', 'url_tags':'image=image1'},{'hash':'2597fcfeab45e01d9393ce3fefd074e5', 'url_tags':'image=image2'}]" 
-F "bodies=[{'text':'Begin Your Adventure'}, {'text':'Once a Trainer, always a Trainer.'}]" 
-F "titles=[{'text':'Level Up'}, {'text':'Swipe to evolve'}]"
-F "descriptions=[{'text':'Begin Your Adventure'}]" 
-F "ad_formats=['SINGLE_IMAGE']" 
-F "link_urls=[{'website_url':'WEBSITE_URL'}]" 
-F "access_token=<ACCESS_TOKEN>" 
https://graph.facebook.com/API_VERSION/act_AD_ACCOUNT_ID/adasset_feeds

To verify you can use your asset feed, read it:

curl -G 
-d "access_token=ACCESS_TOKEN" 
-d "fields=images,titles,bodies,descriptions,ad_formats" 
https://graph.facebook.com/API_VERSION/ASSET_FEED_ID

The response contains:

{
    "ad_formats": [
        "SINGLE_IMAGE"
    ],
    "bodies": {
        "data": [
            {
                "id": "23842500259070001", 
                "text": "Begin Your Adventure"
            }, 
            {
                "id": "23842500259080001", 
                "text": "Once a Trainer, always a Trainer."
            }
        ], 
        "paging": {
            "cursors": {
                "after": "MjM4NDI1MDAyNTkwODAwMDEZD", 
                "before": "MjM4NDI1MDAyNTkwNzAwMDEZD"
            }
        }
    }, 
    "descriptions": {
        "data": [
            {
                "id": "23842500259060001", 
                "text": "Begin Your Adventure"
            }
        ], 
        "paging": {
            "cursors": {
                "after": "MjM4NDI1MDAyNTkwNjAwMDEZD", 
                "before": "MjM4NDI1MDAyNTkwNjAwMDEZD"
            }
        }
    }, 
    "id": "23842500259010001", 
    "images": {
        "data": [
            {
                "hash": "1cd8e1b5de5a76c24f989d94160bfb06", 
                "id": "23842500259040001"
            }, 
            {
                "hash": "2597fcfeab45e01d9393ce3fefd074e5", 
                "id": "23842500259050001"
            }
        ], 
        "paging": {
            "cursors": {
                "after": "MjM4NDI1MDAyNTkwNTAwMDEZD", 
                "before": "MjM4NDI1MDAyNTkwNDAwMDEZD"
            }
        }
    }, 
    "titles": {
        "data": [
            {
                "id": "23842500259020001", 
                "text": "Level Up"
            }, 
            {
                "id": "23842500259030001", 
                "text": "Swipe to evolve"
            }
        ], 
        "paging": {
            "cursors": {
                "after": "MjM4NDI1MDAyNTkwMzAwMDEZD", 
                "before": "MjM4NDI1MDAyNTkwMjAwMDEZD"
            }
        }
    }
}
Example

Set up valid asset feed combination SINGLE_VIDEO format:

  • 5 videos
  • 3 bodies
  • 3 titles
  • 3 descriptions
  • 1 format: SINGLE_VIDEO

Example

Create an asset feed with two alternate videos, bodies, and titles:

curl 
-F "videos=[{'video_id':'1611937202184324', 'thumbnail_url':'<thumnail_url>', 'url_tags':'video=video1'},{'video_id':'1611937188850991', 'thumbnail_url':'<thumnail_url>','url_tags':'video=video2'}]" 
-F "bodies=[{'text':'Begin Your Adventure'}, {'text':'Once a Trainer, always a Trainer.'}]" 
-F "titles=[{'text':'Level Up'}, {'text':'Swipe to evolve'}]" 
-F "descriptions=[{'text':'Begin Your Adventure'}]" 
-F "ad_formats=['SINGLE_VIDEO']" 
-F "link_urls=[{'website_url':'WEBSITE_URL'}]" 
-F "access_token=<ACCESS_TOKEN>" 
https://graph.facebook.com/API_VERSION/act_AD_ACCOUNT_ID/adasset_feeds

To verify you can use your asset feed, read it:

curl -G 
-d "access_token=ACCESS_TOKEN" 
-d "fields=videos,titles,bodies,descriptions,ad_formats" 
https://graph.facebook.com/API_VERSION/ASSET_FEED_ID

The response contains:

{
    "ad_formats": [
        "SINGLE_VIDEO"
    ],
    "bodies": {
        "data": [
            {
                "id": "23842500259070001", 
                "text": "Begin Your Adventure"
            }, 
            {
                "id": "23842500259080001", 
                "text": "Once a Trainer, always a Trainer."
            }
        ], 
        "paging": {
            "cursors": {
                "after": "MjM4NDI1MDAyNTkwODAwMDEZD", 
                "before": "MjM4NDI1MDAyNTkwNzAwMDEZD"
            }
        }
    }, 
    "descriptions": {
        "data": [
            {
                "id": "23842500259060001", 
                "text": "Begin Your Adventure"
            }
        ], 
        "paging": {
            "cursors": {
                "after": "MjM4NDI1MDAyNTkwNjAwMDEZD", 
                "before": "MjM4NDI1MDAyNTkwNjAwMDEZD"
            }
        }
    }, 
    "videos": {
        "data": [
            {
                "video_id": "1611937202184324", 
                "thumbnail_url": "<thumnail_url>"
                "id": "23842500159040001"
            }, 
            {
                "video_id": "1611937188850991", 
                "thumbnail_url": "<thumnail_url>"
                "id": "23842500359050001"
            }
        ], 
        "paging": {
            "cursors": {
                "after": "MjM4NDI1MDAyNTkwNTAwMDEZD", 
                "before": "MjM4NDI1MDAyNTkwNDAwMDEZD"
            }
        }
    }, 
    "titles": {
        "data": [
            {
                "id": "23842500259020001", 
                "text": "Level Up"
            }, 
            {
                "id": "23842500259030001", 
                "text": "Swipe to evolve"
            }
        ], 
        "paging": {
            "cursors": {
                "after": "MjM4NDI1MDAyNTkwMzAwMDEZD", 
                "before": "MjM4NDI1MDAyNTkwMjAwMDEZD"
            }
        }
    },
    "id": "23842500289010001"
}

Editing Ad Creative

You can edit ad creative; add, replace, or remove any of the assets. Provide a new creative with your new asset feed spec, and we deliver the new assets. For the same asset spec, such as image hashes, we report assets as the same ones. For new creatives, all restrictions have to be met just like for the creation part.

When you provide new creative assets, you must meet all the same restrictions that applied when you initially provided the ad creative.

curl 
  -F 'access_token=ACCESS_TOKEN' 
  -F 'creative={
      "creative_id": CREATIVE_ID,
   }' 
https://graph.facebook.com/VERSION/AD_ID

On success, you get the following response:

{"success": true}

Use Deep Links

You can use deeplinks with the App Installs, Conversions and Link Clicks objectives for dynamic creative ads. Add deeplink_url in LINK_URL when you create your asset feed:

curl 
-F "images=[{'hash':'image_hash'},]" 
-F "bodies=[{'text':'Body 1'}, {'text':'Body 2'}]" 
-F "titles=[{'text':'Title 1'}, {'text':'Title 2'}]" 
-F "descriptions=[{'text':' '}]" 
-F "ad_formats=['SINGLE_IMAGE']" 
-F "link_urls=[{'website_url':'App's object store URL','deeplink_url':'deeplink URL'}]" 
-F "call_to_action_types=['SHOP_NOW']" 
-F "access_token=<access_token>" 
https://graph.facebook.com/API_VERSION/act_XXXXX/adasset_feeds

Then use this asset feed for your ads.

Limitations:

  • Only one deeplink_url

Check the Ad Review Status

After you create your campaign, ad set, and ad, check your ad review status:

curl -G 
-d "access_token=ACCESS_TOKEN" 
-d 'fields=review_feedback' 
https://graph.facebook.com/API_VERSION/ADSET_ID

The result includes dynamic creative ad review feedback:

{
  "review_feedback":"[]",
  "id":"ADSET_ID"
}

An empty array means your ad passed review and will display when your ad set reaches its start date. Otherwise, if one of your creative assets does not meet review, you see the following:

{
  "__fb_trace_id__": "GGIjhVp6ka5",
  "review_feedback": {
    {"id":23842500258220001,"text":"Body 1","reason":["ALCOHOL"]},
    {"id":23842500258160001,"text":"Title 1","reason":["ALCOHOL"]},
    {"id":23842500258170001,"text":"Title 2","reason":["ALCOHOL"]}
  }",
  "id": "AD_ID"  
}

Insights

You can read Insights for dynamic creative ad set and ad objects. In Ads Manager, you can view your asset level breakdowns. Using the API, you can get the following breakdowns when you query for asset insights:

  • body_asset
  • description_asset
  • image_asset
  • title_asset
  • call_to_action_asset
  • link_url_asset

These breakdowns can also be combined with the following existing breakdowns:

  • age
  • gender
  • age, gender

Get the following fields when you query for dynamic creative asset insights:

Field Description

actions

Number of actions taken on your ad, broken down by action type

clicks

Total number of clicks on your ad

impressions

Number of times your ad was served

Facebook supports different values derived from the fields above. For example you can also retrieve ctr, actions_per_impressions, and so on.

Examples

To retrieve insights for an ad with the body_asset breakdown, make this call:

curl -G 
-d "breakdowns=body_asset" 
-d "fields=impressions" 
-d "access_token=ACCESS_TOKEN" 
https://graph.facebook.com/API_VERSION/AD_ID/insights

A sample response from this call looks like this:

{
  "data": [
    {
      "impressions": "8801",
      "date_start": "2016-04-29",
      "date_stop": "2016-05-13",
      "body_asset": {
        "text": "Test text",
        "id": "6051732675652"
      }
    },
    {
      "impressions": "7558",
      "date_start": "2016-04-29",
      "date_stop": "2016-05-13",
      "body_asset": {
        "text": "Test ext new",
        "id": "6051732676452"
      }
    },
  ],
  "paging": {
    "cursors": {
      "before": "MAZDZD",
      "after": "MgZDZD"
    }
  }}

To retrieve insights for ad set broken down by image_asset and age, make this call:

curl -G 
-d "breakdowns=image_asset,age" 
-d "fields=impressions" 
-d "access_token=ACCESS_TOKEN" 
https://graph.facebook.com/API_VERSION/ADSET_ID/insights

A sample response from this call looks like this:

{
  "data": [
    {
      "impressions": "5497",
      "date_start": "2016-04-29",
      "date_stop": "2016-05-13",
      "image_asset": {
        "hash": "<REDACTED>",
        "url": "<REDACTED>",
        "id": "6051732672052"
      }
    },
    {
      "impressions": "5962",
      "date_start": "2016-04-29",
      "date_stop": "2016-05-13",
      "image_asset": {
        "hash": "<REDACTED>",
        "url": "<REDACTED>",
        "id": "6051732672652"
      }
    },
  ],
  "paging": {
    "cursors": {
      "before": "MAZDZD",
      "after": "MwZDZD"
    }

Customize Assets

This enables you to customize images or videos, text, body for different segments of users in one ad. The goal is to take advantage of the benefits of broad targeting, such as cost efficiency, fewer delivery issues, and ease of setup, yet still deliver personalized creatives at scale.

Note: This feature is available in API version 2.10 and later only.

Placement Assets

Placement asset customization enables you to customize assets for different placements with one ad. You can take advantage of placement optimization and also providing different media for different placements.

Get Started

  • Create a campaign.
  • Create an ad set.
  • Create an ad and specify an asset feed when you create an ad OR create an asset feed and reference it in your ad.

Create Feed with Asset Rules

Create an asset feed with rules for custom assets by specifying asset_customization_rules. You can provide multiple asset customization rules. For each rule, you need to specify the customization_spec and the asset labels.

Property Name Description Type Required

customization_spec

Define the placements for the assets in the rule to deliver.

See table below for allowed fields.

Required.

image_label

Label attached to one of the image assets in the asset feed.

{"name": "{LABEL_NAME}"}`

Required for SINGLE_IMAGE format.

video_label

Label attached to one of the video assets in the asset feed.

{"name": "{LABEL_NAME}"}`

Required for SINGLE_VIDEO format.

Allowed fields in customization_spec:

Property Name Options Required

publisher_platforms

facebook, instagram, audience_network

Required.

facebook_positions

feed

Not required.

instagram_positions

stream, story

Not required.

audience_network_positions

classic

Not required.

device_platforms

mobile, desktop

Not required.

For example:

curl 
  -F 'object_story_spec={
       "page_id": "PAGE-ID",
       "instagram_actor_id": "INSTAGRAM-ID",
     }' 
  -F 'asset_feed_spec={
    "videos": [
      {
        "adlabels": [
          {
            "name": "labelfb",
          }
        ],
        "video_id": "10154618295707554"
      },
      {
        "adlabels": [
          {
            "name": "labelig",
          }
        ],
        "video_id": "10154618298562554"
      }
    ],
    "bodies": [
      {
        "text": "Begin Your Adventure"
      }
    ],
    "link_urls": [
      {
        "website_url": "WEBSITE_URL",
        "display_url": "DISPLAY_URL"
      }
    ],
    "titles": [
      {
        "text": "Level Up"
      }
    ],
    "ad_formats": [
      "SINGLE_VIDEO"
    ],
    "call_to_action_types": [
      "WATCH_MORE"
    ],
    "descriptions": [
      {
        "text": ""
      }
    ],
    "asset_customization_rules": [
      {
        "customization_spec": {          
          "publisher_platforms": [
            "facebook"
          ],          
          "facebook_positions": [
            "feed",
            "instream_video"
          ]
        },
        "video_label": {
          "name": "labelfb",
        }
      },
      {
        "customization_spec": {          
          "publisher_platforms": [
            "instagram"
          ],          
          "instagram_positions": [
            "stream"           
          ]
        },
        "video_label": {
          "name": "labelig",
        }
      }
    ]
  }' 
https://graph.facebook.com/API_VERSION/act_AD_ACCOUNT_ID/adcreatives

To verify you can use your asset feed, read it:

curl -G 
  -d "access_token=ACCESS_TOKEN" 
  -d "fields=videos,titles,bodies,descriptions,ad_formats,asset_customization_rules" 
https://graph.facebook.com/API_VERSION/ASSET_FEED_ID

Other Customizations

You can also customize assets based on other targeting types in a single ad. Different creatives can be specified for different segments of your audience defined at the adset level. Each of these types along with associated creative is specified as rules.

Supported customization types, listed by priority are:

  1. Age Min
  2. Age Max
  3. Gender
  4. Interest
  5. Behavior
  6. Custom Audience - Custom Audience IDs from mobile, web or CRM software. We do not support Lookalike Audiences.
  7. Relationship Status
  8. Education level
  9. Life Events
  10. Family Status
  11. Household Composition
  12. Moms
  13. Geo-location

The format you use for each of these types is similar to the format for core targeting, see Targeting.

Rule Priority

When you set up rules, you can specify the priority of each rule. If you do not set a priority for each rule, we give each rule a priority number based on its position on the rules list above. For example, the first rule on the list is assigned 1 and the last one gets priority number equal to the total number of rules.

Default Rule

Individual rules should result in targeting at the ad set level which avoids delivering a random combination of assets to people who do not match any of the rules.

To support avoid this scenario, you should set up a default rule. We evaluate each rule in the ascending order of priority assigned to match a given user. You must add a default rule with an empty customization spec, with only opening and closing curly braces at the end of your rules, {}. You whould assign this rule the highest priority number.

This rule maps a creative asset to users who do not satisfy any preceding rules, so we can deliver a sufficient amount of your ads. In general, you should set up rules so that a high percentage of targeted audience matches your non-default rules.

Get Started

  • Create a campaign.
  • Create an ad set.
  • Create an ad and specify an asset feed when you create an ad OR create an asset feed and reference it in your ad.

Create Feed with Customization Rules

Create an asset feed with asset customization rules by specifying asset_customization_rules fields in the API spec. You can provide multiple asset customization rules. For each rule, you need to specify the customization_spec, priority and the asset labels.

curl \
-F "images=[{'hash':'e112c41fe807944dea195220e975f766', 'adlabels':[{'name':'image1'}]}, {'hash':'7df15c5f50ec5d90b3094c5eab3fcc16', 'adlabels':[{'name':'image2'}]}, {'hash':'xxxxxxxxxx', 'adlabels':[{'name':'image3'}]}]" \
-F "bodies=[
    {'text':'Motor City Mission Corps', 'adlabels':[{'name':'body1'}]}
]" \
-F "titles=[
    {'text':'Link title 1 goes here', <b>'adlabels':[{'name':'title1'}]},
    {'text':'Link title 2 goes here', <b>'adlabels':[{'name':'title2'}]</b>},
   {'text':'Link title 3 goes here', <b>'adlabels':[{'name':'title3'}]</b>}]" \
-F "call_to_action_types=['LEARN_MORE']" \
-F "descriptions=[
    {'text':'Link description goes here', 'adlabels':[{'name':'description1'}]}
    ]" \
-F "ad_formats=['SINGLE_IMAGE']" \
-F "link_urls=[{'website_url':'https://www.yourwebsite.com/'}]" \
-F "asset_customization_rules=[
{ 
    'customization_spec': {
        'age_min': 18,
        'age_max': 24
    },
   'image_label': {'name': 'image1'},
   'title_label': {'name': 'title1'},
   'priority': 1
},
{
    'customization_spec': {
       'age_min': 25,
       'age_max': 34
    }, 
    'image_label': {'name': 'image2'},
    'title_label': {'name': 'title2'},
    'priority': 2
},
{
    'customization_spec': {
        'publisher_platforms': ['facebook']
    }, 
    'image_label': {'name': 'image3'},
    'title_label': {'name': 'title3'},
    'priority': 3
},
{
 'customization_spec': {
    }, 
  'image_label': {'name':'image4'},
  'title_label': {'name':'title4'},
  'priority': 4}
]" \

-F "access_token=XXXXXXXXX" \
https://graph.facebook.com/v2.11/act_AD_ACCOUNT_ID/adasset_feeds

Then create ad creative with asset feed. Specify the asset feed ID with adcreative.

curl \
-F 'access_token=XXXXXXXXXX' \
-F 'object_story_spec={
"page_id": "XXXXX"
}' \
-F 'asset_feed_id=XXXXX' \
https://graph.facebook.com/v2.11/act_AD_ACCOUNT_ID/adcreatives

Create an ad with the ad creative.

curl \
-F "name=Asset Customization Rules Test" \
-F "adset_id=XXXXXXXXX" \
-F "creative={\"creative_id\":\"&lt;Adcreative ID from above&gt;\"}" \
-F "access_token=XXXXXXXXX" \
https://graph.facebook.com/v2.11/act_1516221108450274/ads

Restrictions

  • ObjectivesBRAND_AWARENESS, REACH, LINK_CLICKS, APP_INSTALLS, CONVERSIONS, and VIDEO_VIEWS. For LINK_CLICKS and CONVERSIONS, app engagement is unsupported.
  • Placements—Facebook Feed; Instagram Feed; Instagram Story; Audience Network Native, Banner and Interstitial; Audience Network Rewarded Video; Audience Network In-stream Video.
  • Buying typeReach and Frequency OR AUCTION.
  • Asset Feed Restrictions are the same as Dynamic Creative Ad, except for the following:
    1. Each image or video should have a label attached.
    2. Only one image or video should be eligible for each asset_customization_rule.
    3. Ad Formats—Two ad_formats are supported—SINGLE_IMAGE and SINGLE_VIDEO. Only one ad_format is allowed in one asset feed.
    4. At most one item can be provided in the call_to_actions_types fields.
    5. For any placement at L2 targeting, there should be at least one asset_customization_rule covering it.

FAQs

Common Pitfalls

The following scenario can cause issues with Dynamic Creative ads:

  • Create a Dynamic Creative with 10% budget and compare with baseline. Try to compare CTR and CPA.

Why is this wrong?

  • Budget needs to be equal between the two ad sets.
  • Both campaigns need similar number of delivered impressions for comparison.

Q: Is ads delivery optimization different from dynamic creative and normal ads? If we adjusted image and title ourselves and created regular ads with possible combinations, would the outcome be any different?

A: Yes, the optimization is different between dynamic creative and the ads in our current system. If you create various image/title combinations today, our delivery system picks the best performing, fully formed ad and puts the majority of spend behind that ad. Creative optimization is happening at a fixed, and fully formed ad within the ad set. With dynamic creative, we are doing creative optimization at the individual creative asset level such as image, title, body, and converging on the best creative asset combination per impression.

For dynamic creative ads insights, you can retrieve creative asset level insights, and group data by age range, gender.

Q: How should I use dynamic creative? As a testing tool for figuring out the best creative concepts, or do we replace regular campaigns with them?

A: Dynamic creative is a new primary workflow to run actual ad campaigns and determine the best performing creatives. It is ideal for evergreen campaigns, or campaigns that run longer than 5 days. However, we ask that you split test Dynamic Creative against your existing campaign strategies to see which approach performs better for your needs.

We believe that this ads optimization model gets trained with more advertiser data over time, you should be able to consistently get higher ROI using dynamic creative compared to the existing delivery system.

Q: Can I view insights on the full, delivered ad? What about creative asset level breakdowns?

Currently, we only show creative asset level breakdowns such as metrics by image, title, body, and so on. These metrics are available on Ads Manager under the 'By Delivery' breakdown.

Q: For regular ads we create a mix of single, carousel, image, or video ads under a single ad set. How can I do that with dynamic creative?

A: We are currently only support a single format. Selected format can be a single image, video or carousel image. We are working on multiple format support in one ad set.

Q: Can we use daily budget feature, or it has to be lifetime only?

A: You can use both daily and lifetime budget.

Q: Do ads insights work the same way for dynamic creative as they do for non-dynamic creative fields?

A: Dynamic creative does not support the ad-level specific insights field: 'relevance_score'.

Q: How does dynamic creative work for CAROUSEL_IMAGE ad format?

A: Dynamic creative delivers the best combination of the assets in carousel ad format. The number of cards is the number of images in the asset feed if less than 10, otherwise we display 10. In asset insights breakdown, for in-card assets, such as image, title, and description, we aggregate metrics when the asset is in the first card. We recommend square sizes for images.

Q: Can I edit my creative?

A: You can change ad creative by providing it with a new asset feed ID or asset feed spec. If you send the same spec, we report results for new assets under the older, existing asset name. We reuse assets based on asset value and type. For example, if you have two asset feeds with the same image hash, and you update one feed with another in your ad, you see combined impressions for that asset in the asset breakdowns. You can add new assets, remove existing assets and replace assets with completely new ones. However, you cannot change formats such as SINGLE IMAGE to VIDEO. You also cannot switch a dynamic creative ad to a non-dynamic creative ad which has no asset feed in the creative.

Q: What placements does dynamic creative support?

A: Dynamic creative supports all the placements except Instagram Stories and Sponsored Messages on Messenger. The other restrictions that are in place for regular ads, still apply for dynamic creative ads.

Q: Can I crop my images in dynamic creative?

A: Dynamic creative supports image cropping. Specify cropping for your image definition in images. You can provide only one crop per image. We apply specified crops to all placements of your image. See Marketing API, Image Cropping.