Creating Travel Ads

This guide assumes:

  • You have a catalog and product set ready.
  • You have set up the required travel events on your website or in your mobile app.
  • (Required) You have created a Facebook Page and an ad account.

Targeting Strategies

Travel Ads support 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 or app looking for hotels, destinations or flights.

  • Cross-sell and upsell—Target people who have purchased a flight with relevant hotels, or upsell priority boarding or seat selection.

  • Prospecting—Expand the reach of your ad and find new customers by targeting prospecting audiences.

Set Up Travel Ads

When you create Travel Ads, you follow the same process as you do when you set up any other type of Facebook ad with the API:

Step 1. Create Campaign

Travel Ads use 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>');
  CampaignFields::NAME => 'Product Catalog Sales Campaign',
  CampaignFields::OBJECTIVE => CampaignObjectiveValues::PRODUCT_CATALOG_SALES,
  CampaignFields::PROMOTED_OBJECT => array(
    'product_catalog_id' => <PRODUCT_CATALOG_ID>,

from facebookads.adobjects.campaign import Campaign

campaign = Campaign(parent_id='act_<AD_ACCOUNT_ID>')
campaign[] = '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>,

    'status': Campaign.Status.paused,
Campaign campaign = new AdAccount(act_<AD_ACCOUNT_ID>, context).createCampaign()
  .setName("Product Catalog Sales Campaign Group")
  .setPromotedObject("{\"product_catalog_id\":\"" + <PRODUCT_CATALOG_ID> + "\"}")
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>' \<AD_ACCOUNT_ID>/campaigns

Step 2. Create Ad Set

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


To retarget the website or app visitors, use a dynamic audience of the same type as the product set you are promoting; for example, 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 Upsell

To cross-sell and upsell 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; for example, target a flight purchase audience with a hotel set or another flight set, highlighting seat selection.


  • Create an audience using basic demographic targeting, such as women in the U.S. over the age of 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

Create Ad Set Example

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>');

  AdSetFields::NAME => 'Product Catalog Sales Adset',
  AdSetFields::BID_AMOUNT => 3000,
  AdSetFields::BILLING_EVENT => AdSetBillingEventValues::IMPRESSIONS,
  AdSetFields::DAILY_BUDGET => 15000,
  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>,

from facebookads.adobjects.adset import AdSet
from facebookads.adobjects.targeting import Targeting

adset = AdSet(parent_id=ad_account_id)
adset[] = 'Product Catalog Sales Adset'
adset[AdSet.Field.bid_amount] = 3000
adset[AdSet.Field.billing_event] = AdSet.BillingEvent.impressions
adset[AdSet.Field.optimization_goal] = \
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: [
adset[AdSet.Field.promoted_object] = {
    'product_set_id': product_set_id,

AdSet adSet = new AdAccount(act_<AD_ACCOUNT_ID>, context).createAdSet()
  .setName("Product Catalog Sales Adset")
    new Targeting()
        new TargetingGeoLocation()
  .setPromotedObject("{\"product_set_id\":\"" + <PRODUCT_SET_ID> + "\"}")
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>' \<AD_ACCOUNT_ID>/adsets

Travel Ads 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 Travel Ads. When Facebook displays your ad, we replace template tags with someone's actual travel choices. You can use template tags in the ad itself and in the URL someone sees once they click the ad.

Use the template_url_spec field to specify the URL that appears after someone clicks the ad. If you don't provide it, or we can't derive it when we render an ad, we display the URL from the catalog. For Flight Ads, this field is required if you don't provide a URL in the catalog.

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

The following example shows how to create a carousel creative for Dynamic Ads for Hotels. Dynamic Ads for Destinations and Dynamic Ads for Flights 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();
  AdCreativeObjectStorySpecFields::PAGE_ID => <PAGE_ID>,
  AdCreativeObjectStorySpecFields::TEMPLATE_DATA =>
    (new AdCreativeLinkData())->setData(array(
      AdCreativeLinkDataFields::MESSAGE =>
        'Book your upcoming stay in {{}}',
      AdCreativeLinkDataFields::NAME => '{{ | titleize}}',
      AdCreativeLinkDataFields::LINK => '<LINK>',
      AdCreativeLinkDataFields::DESCRIPTION =>
      AdCreativeLinkDataFields::ADDITIONAL_IMAGE_INDEX => 0,
      AdCreativeLinkDataFields::CALL_TO_ACTION => array(
        'type' => AdCreativeCallToActionTypeValues::BOOK_TRAVEL,

$creative = new AdCreative(null, 'act_<AD_ACCOUNT_ID>');
  AdCreativeFields::NAME => 'Dynamic Ad Template Creative Sample',
  AdCreativeFields::OBJECT_STORY_SPEC => $object_story_spec,
  AdCreativeFields::TEMPLATE_URL_SPEC =>
      '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' => ''.
          '?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>,

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 {{}}',
    '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[] = 'Dynamic Ad Template Creative Sample'
creative[AdCreative.Field.object_story_spec] = story
template_url = ('{{hotel.hotel_id}}'
                '&startDate={{trip.checkin_date date_format:Y-m-d}}'
                '&endDate={{trip.checkout_date date_format:Y-m-d}}')
creative[AdCreative.Field.template_url] = template_url
creative[AdCreative.Field.product_set_id] = <PRODUCT_SET_ID>
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 {{}}", 
      "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:\/\/\/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>' \<AD_ACCOUNT_ID>/adcreatives

Flight Upsell (API v2.10+ only)

To upsell options, such as seat selection or priority boarding, to an audience that purchased flights:

  1. Provide an audience by including only PURCHASE events.
  2. (Preferred) In the ad creative's recommender_settings, specify PURCHASE events 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:\/\/\/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>' \<AD_ACCOUNT_ID>/adcreatives

Flight Ads for Prospecting

This enables you to reach people who have intent to travel, even if they have not visited your actual website or app. With this option, you can automatically display the most relevant ad creative and drive flight purchases.

This API is currently available on a limited basis. Please contact your Facebook Representative for access.

For the Flight Ads for Prospecting creative, in addition to catalogs, we recommend that you provide an universal creative (static images) that appears when there are no suitable flights to show from your product set.

curl \
  -F 'name=Dynamic Ad Template Creative Sample' \
  -F 'object_story_spec={ 
    "page_id": "<PAGE_ID>", 
      "call_to_action": {"type":"BOOK_TRAVEL"},
      "description":"Fly to {{flight.destination_city}}",
        "name":"Best Deals",
        "message":"Great prices",
        "description" : "Fly now",
        "call_to_action": {"type":"LEARN_MORE"},
  }' \
  -F 'product_set_id=<PRODUCT_SET_ID>' \
  -F 'access_token=<ACCESS_TOKEN>' \<API_VERSION>/act_<AD_ACCOUNT_ID>/adcreatives

You can upload the universal creative (static images) to your ad account like this:

curl \
  -F 'filename=@test.jpg' \
  -F 'access_token=<ACCESS_TOKEN>' \"<API_VERSION>/act_<ACCOUNT_ID>/adimages"

Once you provide the image hash, you can use it in your ad creative. See Ad Image, Reference.

curl \
  -F 'filename=@test.jpg' \
  -F 'access_token=<ACCESS_TOKEN>' \

At this point, you can preview your universal creative:

curl -G \
  -d 'ad_format=DESKTOP_FEED_STANDARD' \
  -d 'render_type=FALLBACK' \
  -d 'access_token=<ACCESS_TOKEN>' \<API_VERSION>/<CREATIVE_ID>/previews 

Overlay Design

Overlays allow advertisers to add pricing information (as a direct price or percentage off) for each item within a Dynamic Ad.

Overlay Options by Catalog Type

You can use the following overlay types, depending on the catalog type you use in the ad set:

  • Hotel: price, strikethrough and % off
  • Destination: price
  • Flight: price

Note: All price-related template tags for each catalog type are supported for the overlay options above. To view template tags for each catalog type, see hotels, destinations, and flights.

Overlay Design Options

The pricing information is dynamically pulled from the price and sale price columns of the feed. Advertisers can select from the following customizations for their dynamic ads overlay:

  • Shapes: Pill, Circle and Triangle.
  • Positions: 4 fixed corners: TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, and BOTTOM_RIGHT. For triangle, only the TOP_LEFT and TOP_RIGHT are supported.
  • Fonts: A list of preset fonts, such as Droid Serif, Open Sans, and so on.
  • Overlay types supported: price, strikethrough and % off. Note: strikethrough and % off are available for hotels only.

Learn more about how to add overlays.

Example—Price Overlay with Strikethrough for a Hotel Ad

curl \
  -F 'name=Test Templates in Overlay' \
  -F 'object_story_spec={
    "page_id": "<PAGE_ID>",
    "template_data": {
      "description": "Description",
      "link": "<LINK>", 
      "name": "Name: {{}}",
      "message" : "Come visit {{}}!",
      "image_overlay_spec": {
        "text_template_tags": ["{{hotel.price round}}", "{{hotel.sale_price round}}"],
  }' \
  -F 'product_set_id=<PRODUCT_SET_ID>' \
  -F 'template_url=' \
  -F 'access_token=<ACCESS_TOKEN>' \

To create the ad, use ad_set_id and creative_id.

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

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 display 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, 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(
from facebookads.adobjects.adcreative import AdCreative
from facebookads.adobjects.adpreview import AdPreview

creative = AdCreative(<CREATIVE_ID>)
params = {
    'product_item_ids': [
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>' \<CREATIVE_ID>/previews


Field Name & Type Description


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)}


type: string

Render the preview with user's intent signal; ex: 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


type: string

Render the preview with user's intent signal; ex: 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. Note: Remember to add product_id to the breakdown parameter.

For hotel and destination, the product id breakdown is shown for each hotel_id or destination_id. For flight, the product id breakdown shows origin_airport:destination_airport.

Fetch Comments and Likes

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