Dynamic Ads for Travel - Creating Ads

This guide assumes you have a catalog and product set ready, and have set up the required travel events on your website or in your mobile app. You also need a Facebook Page and an ad account.

Targeting strategies

Dynamic Ads for Travel supports different targeting strategies. You can drive different business objectives by combining the right audience with the right product set:

Retargeting

Show relevant hotels, destinations or flights to people who have been to your website and/or app looking for hotels, destinations or flights.

Cross-sell and up-sell

Target people who have purchased a flight with relevant hotels, or up-sell priority boarding or seat selection.

Broad Audiences

Expand the reach of your ad and find new customers by leveraging broad audiences.

Creating Ads

Creating Dynamic Ads for Travel follows the same process you follow when you set up any other type of Facebook ad with the API.

Step 1. Create Campaign

Dynamic Ads for travel uses the PRODUCT_CATALOG_SALES objective. Specify a travel catalog in promoted_object at the campaign level:

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

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

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

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

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

Step 2. Create Ad Set

Once you have the campaign, and the campaign_id, you can create the ad set which defines the bidding and targeting options for your ads.

Retargeting

To retarget website and/or app visitors, use a dynamic audience of the same type as the product set you are promoting, i.e. promote a hotel set to a hotel audience, a flight set to a flight audience and a destination set to a destination audience.

Cross-sell and up-sell

To cross-sell and up-sell people that purchased on your website and/or app, use a dynamic audience that contains people that have made a purchase, and promote them travel options from another catalog, i.e. target a flight purchase audience with a hotel set or another flight set highlighting seat selection.

Broad Audiences

  • Create an audience using basic demographic targeting such as women in the US over 18.
  • Include customers targeted by existing retargeting campaigns, but consider excluding people who have purchased in the last 10 days.
  • Use a broad product set with over 100 hotels.
  • Optimize for OFFSITE_CONVERSIONS with stronger intent signals such as Purchase or InitiateCheckout.
  • See also Dynamic Ads, Broad Audience Targeting

Creating the Ad Set

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.adaccount import AdAccount
from facebookads.adobjects.adset import AdSet
from facebookads.adobjects.targeting import Targeting

ad_account = AdAccount(fbid=ad_account_id)

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

Unlike Dynamic Ads, Dynamic Ads for Travel does not support inline dynamic audience targeting specs in the Ad Set. You must separately create an audience first.

Step 3. Create Ad Creative

You can use template tags in your ad creatives for Dynamic Ads for Travel. When Facebook displays your ad, we replace template tags with someone's actual travel choices. You can use template tags in the ad itself, as well as in the URL someone sees once they click on the ad.

Use the template_url_spec field to specify the URL that appears after someone clicks on the ad. If you do not provide it, or we cannot derive it when we render an ad, we display the URL from the catalog. With Dynamic Ads for Flight this field is required if you do not provide a URL in the catalog.

You can show a single product or a carousel with multiple products. For single-product ads, you can show multiple images of the same product in the carousel, assuming your catalog contains multiple images for each product. You can also display static cards in combination with dynamic cards. For more information about creative options, see Dynamic Ads, Building a Creative Template.

You cannot show multiple flights in a carousel. However, you can add multiple images per flight in the catalog and show multiple images for the same flight.

Below is an example to create a carousel creative for Dynamic Ads for Hotels. Dynamic Ads for Destinations and Dynamic Ads for Flights will have a similar setup.

use FacebookAds\Object\AdCreative;
use FacebookAds\Object\Fields\AdCreativeFields;
use FacebookAds\Object\Fields\AdCreativeLinkDataFields;
use FacebookAds\Object\Fields\AdCreativeObjectStorySpecFields;
use FacebookAds\Object\Values\AdCreativeCallToActionTypeValues;
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 =>
        'Book your upcoming stay in {{hotel.city}}',
      AdCreativeLinkDataFields::NAME => '{{hotel.name | titleize}}',
      AdCreativeLinkDataFields::LINK => '<LINK>',
      AdCreativeLinkDataFields::DESCRIPTION =>
        '{{hotel.description}}',
      AdCreativeLinkDataFields::ADDITIONAL_IMAGE_INDEX => 0,
      AdCreativeLinkDataFields::CALL_TO_ACTION => array(
        'type' => AdCreativeCallToActionTypeValues::BOOK_TRAVEL,
      ),
    )),
));

$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(
      'config' => array(
        'app_id' => '123456789012345',
      ),
      'ios' => array(
        'url' => 'example://home/hotel'.
          '?id={{hotel.hotel_id | urlencode}}'.
          '&startDate={{trip.checkin_date date_format:Y-m-d | urlencode}}'.
          '&endDate={{trip.checkout_date date_format:Y-m-d | urlencode}}',
      ),
      'web' => array(
        'url' => 'http://www.example.com/hotel'.
          '?id={{hotel.hotel_id | urlencode}}'.
          '&startDate={{trip.checkin_date date_format:Y-m-d | urlencode}}'.
          '&endDate={{trip.checkout_date date_format:Y-m-d | 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': 'Book your upcoming stay in {{hotel.city}}',
    'name': '{{hotel.name | titleize}}',
    'link': '<LINK>',
    'description': '{{hotel.description}}',
    'additional_image_index': 0,
    'call_to_action': {
        'type': 'BOOK_TRAVEL',
    },
}

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 = {
    'config': {
        'app_id': '123456789012345',
    },
    'ios': {
        'url': 'example://sub/?id={{hotel.hotel_id | urlencode}}' +
        '&startDate={{trip.checkin_date date_format:Y-m-d | urlencode}}' +
        '&endDate={{trip.checkout_date date_format:Y-m-d | urlencode}}',
    },
    'web': {
        'url': 'http://www.example.com/hotel.aspx?id={{hotel.hotel_id | urlencode}}' +
        '&startDate={{trip.checkin_date date_format:Y-m-d | urlencode}}' +
        '&endDate={{trip.checkout_date date_format:Y-m-d | urlencode}}',
    },
}
creative[AdCreative.Field.template_url_spec] = template_url_spec
creative[AdCreative.Field.product_set_id] = <PRODUCT_SET_ID>
creative.remote_create()
curl \
  -F 'name=Dynamic Ad Template Creative Sample' \
  -F 'object_story_spec={ 
    "page_id": "<PAGE_ID>", 
    "template_data": { 
      "additional_image_index": 0, 
      "call_to_action": {"type":"BOOK_TRAVEL"}, 
      "description": "{{hotel.description}}", 
      "link": "<LINK>", 
      "message": "Book your upcoming stay in {{hotel.city}}", 
      "name": "{{hotel.name | titleize}}" 
    } 
  }' \
  -F 'template_url_spec={ 
    "config": {"app_id":"123456789012345"}, 
    "ios": { 
      "url": "example:\/\/home\/hotel?id={{hotel.hotel_id | urlencode}}&startDate={{trip.checkin_date date_format:Y-m-d | urlencode}}&endDate={{trip.checkout_date date_format:Y-m-d | urlencode}}" 
    }, 
    "web": { 
      "url": "http:\/\/www.example.com\/hotel?id={{hotel.hotel_id | urlencode}}&startDate={{trip.checkin_date date_format:Y-m-d | urlencode}}&endDate={{trip.checkout_date date_format:Y-m-d | urlencode}}" 
    } 
  }' \
  -F 'product_set_id=<PRODUCT_SET_ID>' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/adcreatives

Flight Up-sell (API v2.10+ only)

To up-sell i.e. seat selection or priority boarding to a flight purchase audience, take note of the following:

  • Provide an audience by including only PURCHASE events.
  • In the ad creative's recommender_settings, specify PURCHASE events as the preferred way to recommend ads
curl \
  -F 'name=Dynamic Ad Template Creative Up-sell Sample' \
  -F 'object_story_spec={ 
    "page_id": "<PAGE_ID>", 
    "template_data": { 
      "additional_image_index": 0, 
      "call_to_action": {"type":"LEARN_MORE"}, 
      "description": "{{flight.description}}", 
      "link": "<LINK>", 
      "message": "Book extra leg room on your flight from {{flight.origin_city}} to {{flight.destination_city}}", 
    } 
  }' \
  -F 'template_url_spec={ 
    "config": {"app_id":"<APP_ID>"}, 
    "ios": { 
      "url": "example:\/\/home\/flight?id={{flight.origin_airport}}&startDate={{trip.departing_departure_date date_format:Y-m-d | urlencode}}&endDate={{trip.returning_departure_date date_format:Y-m-d | urlencode}}" 
    }, 
    "web": { 
      "url": "http:\/\/www.example.com\/flight?id={{flight.origin_airport}}&startDate={{trip.checkin_date date_format:Y-m-d | urlencode}}&endDate={{trip.returning_departure_date date_format:Y-m-d | urlencode}}" 
    } 
  }' \
  -F 'product_set_id=<FLIGHT_SET_ID>' \
  -F 'recommender_settings'={"preferred_events":["Purchase"]}\ 
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/VERSION/act_<AD_ACCOUNT_ID>/adcreatives

Use the ad_set_id and the creative_id to create the ad.

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.11/act_<AD_ACCOUNT_ID>/ads

Next Steps

Preview the ad

You can generate a preview of your dynamic creative with the Ad Previews API. Include the product_item_ids parameter to specify which catalog items will show up in the preview.

Generate a preview of your ad with the Ad Previews API. Include the product_item_ids to specify which catalog items appears in the preview, and start_date and end_date to specify specific dates.

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

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

creative = AdCreative(<CREATIVE_ID>)
params = {
    'ad_format':
        AdPreview.AdFormat.desktop_feed_standard,
    'product_item_ids': [
        '<HOTEL_FBID>',
    ],
}
preview = creative.get_previews(params=params)
curl -G \
  -d 'ad_format=DESKTOP_FEED_STANDARD' \
  -d 'product_item_ids=["<HOTEL_FBID>"]' \
  -d 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.10/<CREATIVE_ID>/previews

Parameters:

Field Name & Type Description

product_item_ids

type: array[string]

  • Hotel: List of hotel FBID or Base64url-encoded hotel ID tokens. Each token is of the form hotel_catalog:{catalog_id}:{base64urlencode(hotel_id)}
  • Destination: List of destination FBID or Base64url-encoded destination ID tokens. Each token is of the form destination_catalog:{catalog_id}:{base64urlencode(destination_id)}
  • Flight: Flight FBID or Base64url-encoded flight ID token. Each token is of the form flight_catalog:{catalog_id}:{base64urlencode(destination_id)}

start_date

type: string

Render the preview with user's intent signal, e.g. 2016-12-24.

  • For hotel, this would be the value of trip.checkin_date
  • For destination, this would be the value of trip.travel_start
  • For flight, this would be the value of trip.departing_departure_date

end_date

type: string

Render the preview with user's intent signal, e.g. 2017-01-01.

  • For hotel, this would be the value of trip.checkout_date
  • For destination, this would be the value of trip.travel_end
  • For flight, this would be the value of trip.returning_departure_date

Fetch Travel Ad Insights & Statistics

To fetch ad Insights for a travel object, such as hotel, make a GET call to /insights. Remember to add product_id to the breakdown parameter. For hotel and destination, product id breakdown will be shown for each hotel_id or destination_id. For flight, product id breakdown will show origin_airport:destination_airport.

Fetch Comments and Likes

To retrieve comments or "Likes" of a Dynamic Ad, use the Dynamic Post API.