Dynamic Ads For Travel - Building Audiences

Dynamic Ads for travel enable you to show people ads based on their cross-device travel intent. User intent is collected from website and mobile apps into a travel audience which will then be used to target your customers.

In this document we will walk you through how to create a travel audience:

Step 1: Setup User Signals for Travel Events

Standard events are a set of predefined event names you can send from your website or app that allow you to both measure the performance of your campaigns and to capture intent from your audiences.

Dynamic Ads for travel requires the following standard events to be sent from your website pixel and mobile app:

Pixel EventApp EventHotelFlightDestinationDescription

Search

fb_mobile_search

When someone has made a travel-related search

ViewContent

fb_mobile_content_view

When someone has viewed details of a specific travel entity, e.g. a hotel or a destination

InitiateCheckout

fb_mobile_initiated_checkout

When someone has begun the booking process

Purchase

fb_mobile_purchase

When someone has completed their travel booking

For example, to report a Search event for a hotel-listing using your FB pixel or the FB App SDK, you would place the following code on your search-results page:

<!-- Facebook Pixel Code -->
<script>
!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
document,'script','//connect.facebook.net/en_US/fbevents.js');

// Insert Your Facebook Pixel ID below.
fbq('init', '<FB_PIXEL_ID>');

fbq('track', 'Search', {
  content_type: 'hotel',
  content_ids: ['1234', '2345', '3456', '4567'], // Top search results
  checkin_date: '2016-02-12',
  checkout_date: '2016-02-19',
  city: 'New York City', //Required for Search event
  region: 'New York', // region is the state for the US. Required for Search event
  country: 'US', //Required for Search event
} );
</script>
<!-- End Facebook Pixel Code -->
Bundle parameters = new Bundle();
parameters.putString(AppEventsConstants.EVENT_PARAM_CONTENT_TYPE, "hotel");
parameters.putString(AppEventsConstants.EVENT_PARAM_CONTENT_ID, "[\"1234\", \"2345\", \"3456\", \"4567\"]"); // top search results

// we must prefix all travel-specific parameters with fb_
parameters.putString("fb_checkin_date", "2016-02-12");
parameters.putString("fb_checkout_date", "2016-02-19");
parameters.putString("fb_city", "New York City"); // Required for Search event
parameters.putString("fb_region", "New York"); // region is the state for the US. Required for Search event
parameters.putString("fb_country", "US"); // Required for Search event

logger.logEvent(
  AppEventsConstants.EVENT_NAME_SEARCHED,
  parameters
);
[FBSDKAppEvents logEvent:FBSDKAppEventNameSearched
  parameters:@{
    FBSDKAppEventParameterNameContentType : @"hotel",
      FBSDKAppEventParameterNameContentID : @"[\"1234\", \"2345\", \"3456\", \"4567\"]", // top search results

// we must prefix all travel-specific parameters with fb_

                       @"fb_checkin_date" : @"2016-02-12",
                      @"fb_checkout_date" : @"2016-02-19",
                               @"fb_city" : @"New York City", //Required for Search event
                             @"fb_region" : @"New York", // region is the state for the US. Required for Search event
                            @"fb_country" : @"US", // Required for Search event
  }
];

For more details on pixel setup, see Facebook Pixel Setup.

Once you have determined which events should be fired where, the next step is to fill out each event's parameters.

Event Parameters

Every travel event must have an associated content_type (or fb_content_type for mobile) parameter which designates the type of travel that is concerned. For example, on a hotel search listing page, you would send a Search event with a content_type parameter of hotel. On a flight booking confirmation page, you would send a Purchase event with a content_type parameter of flight.

To combine multiple types of travel intent together into one event fire (e.g. for package holidays), you would list all the relevant content_type in a JSON-encoded array. For example, if a customer starts booking a fight + hotel together, you would send a single InitiateCheckout event with a content_type parameter set to ['flight','hotel'].

Once you have determined the content_type of an event, next you must add any applicable parameters. The table below lists the parameters required for each content_type.

  • Required
    Key functionality will not work without these parameters present.
  • Recommended
    These parameters aren't strictly required but allow us to make better recommendations and enable more targeting options in your ads. Try to provide as many as possible.
  • Not Required
    These parameters aren't expected for this travel type and may be ignored.

Unless otherwise specified, the marker applies to all the events that you can send for that type (i.e. Search, ViewContent, InitiateCheckout & Purchase).

Pixel ParameterMobile Parameterhotelflightdestination

content_type

fb_content_type

content_ids

fb_content_id

checkin_date

fb_checkin_date

checkout_date

fb_checkout_date

departing_departure_date

fb_departing_departure_date

returning_departure_date

fb_returning_departure_date

origin_airport

fb_origin_airport

destination_airport

fb_destination_airport

value

_valueToSum

Purchase

Purchase

currency

fb_currency

Purchase

Purchase

destination_ids

fb_destination_ids

city

fb_city

Search

◎ otherwise

Search

◎ otherwise

region

fb_region

Search

◎ otherwise

Search

◎ otherwise

country

fb_country

Search

◎ otherwise

Search

◎ otherwise

departing_arrival_date

fb_departing_arrival_date

returning_arrival_date

fb_returning_arrival_date

suggested_destinations

fb_suggested_destinations

travel_start

fb_travel_start

travel_end

fb_travel_end

num_adults

fb_num_adults

num_children

fb_num_children

num_infants

fb_num_infants

travel_class

fb_travel_class

suggested_hotels

fb_suggested_hotels

user_score

fb_user_score

hotel_score

fb_hotel_score

price

fb_price

preferred_star_ratings

fb_preferred_star_ratings

Search

preferred_price_range

fb_preferred_price_range

Search

preferred_neighborhoods

fb_preferred_neighborhoods

Search

preferred_num_stops

fb_preferred_num_stops

◎ (defaults to 0)

Parameter Details

Parameter Name & Data TypeDescription

checkin_date

type: string

The date the user is wanting to check-in to the hotel in the hotel's time-zone. We accept the following date-formats:

  • YYYYMMDD e.g. 20170623
  • YYYY-MM-DD e.g. 2017-06-23
  • YYYY-MM-DDThh:mmTZD e.g. 2017-06-23T15:30GMT
  • YYYY-MM-DDThh:mm:ssTZD e.g. 2017-06-23T15:30:00GMT

checkout_date

type: string

The date the user is wanting to check-out from the hotel in the hotel's time-zone. We accept the same date formats as listed for checkin_date.

city

type: string

Provide the city of the location from user intent, e.g. Auckland.

content_ids (where available)

type: string or string[]

Any relevant ID(s) as listed in your travel catalog, e.g. for ViewContent event you might send the ID of the item presented, or for Search event you might send an array of IDs for the top search results.

content_type

type: string or string[]

Value(s) must be hotel, flight or destination.

country

type: string

Provide the country of the location from user intent, e.g. New Zealand.

currency

type: string

Currency for the value. Specified using ISO 4217 currency format, e.g. USD.

departing_arrival_date

type: string

The date (and time) of arrival at the destination. We accept the same date formats as listed for checkin_date.

departing_departure_date

type: string

The date (and time) of the start of the outbound journey. We accept the same date formats as listed for checkin_date.

destination_airport

type: string

Destination airport using IATA code.

destination_ids (where available)

type: string or string[]

If you have a destination catalog, you can associate one or more destinations in your destination catalog with a specific hotel pixel event. For instance, a particular hotel may be linked to a nearby museum and a nearby beach, both of which are destinations in the destination catalog.

hotel_score

type: float

An indicator representing the relative value of this hotel to the advertiser compared to its other hotels.

num_adults

type: int

Number of adults that will be staying, e.g. 2.

num_children

type: int

Number of children that will be staying, e.g. 1.

num_infants

type: int

Number of infants travelling on this journey.

origin_airport

type: string

Origin airport using IATA code.

preferred_neighborhoods

type: string[]

A list of preferred neighborhoods that a user is filtering for.

preferred_num_stops

type: int

Set to 0 if the user is only looking for direct flights, 1 for up to one stop-over, etc.

preferred_price_range

type: [int(min), int(max)]

A tuple of minimum and maximum room rates that a user is filtering for.

preferred_star_ratings

type: [int(min), int(max)]

A tuple of minimum and maximum hotel star rating that a user is filtering for.

price

type: float

The price of the booking for ViewContent, InitiateCheckout and Purchase events. This will be the lowest price among the search results for Search event.

region

type: string

Provide the state/district/region of the location from user intent, e.g. North Island.

returning_arrival_date

type: string

The date (and time) when we have completed the return journey. We accept the same date formats as listed for checkin_date.

returning_departure_date

type: string

The date (and time) of the start of the return journey. This is required if you have return journey. We accept the same date-formats as listed for departing_departure_date.

suggested_destinations

type: string[]

A list of IDs representing destination suggestions for this user.

This parameter is NOT applicable for the Search event.

suggested_hotels

type: string[]

A list of IDs representing hotel suggestions for this user.

This parameter is NOT applicable for the Search event.

travel_class

type: string

Class of travel, which must be one of economy, premium, business or first.

travel_end

type: string

The end date of user's trip. We accept the same date-formats listed for checkin_date

travel_start

type: string

The start date of user's trip. We accept the same date formats as listed for checkin_date.

user_score

type: float

An indicator representing the relative value of this user to the advertiser.

value

type: float

A number that quantifies the value of this event to the advertiser.

Step 2: Associate User Signals to the Travel Catalog(s)

You next need to associate your event sources with each of your travel catalogs that will be consuming this data. You can do this by visiting your Business Manager's Catalog Page and clicking the 'Associate Sources' button. Make sure to select the pixel and app that will be receiving the DAT events. Alternatively, you can make a HTTP POST call to:

use FacebookAds\Object\ProductCatalog;

$product_catalog = new ProductCatalog(<PRODUCT_CATALOG_ID>);
$product_catalog->createExternalEventSource(array(), array(
  <PIXEL_ID>,
  <APP_ID>,
));
from facebookads.adobjects.productcatalog import ProductCatalog

product_catalog = ProductCatalog(<PRODUCT_CATALOG_ID>)
product_catalog.add_external_event_sources([
    <PIXEL_ID>,
    <APP_ID>,
])
curl \
  -F '0=<PIXEL_ID>' \
  -F '1=<APP_ID>' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.10/<PRODUCT_CATALOG_ID>/external_event_sources

When making the API call, specify the following parameters:

Field NameData TypeDescription

external_event_sources (required)

int[]

A list of Pixel and App IDs to associate with the catalog.

Step 3: Create And Share Out A Travel Event Source Group

In order to build a travel audience, an admin for your business must create an event source group to group all of your sources for travel intent signal together. You do this by making an HTTP POST call to:

use FacebookAds\Object\EventSourceGroup;
use FacebookAds\Object\Fields\EventSourceGroupFields;

$event_source_group = new EventSourceGroup(null, <BUSINESS_ID>);
$event_source_group->setData(array(
  EventSourceGroupFields::NAME => 'My Travel Company Events',
  EventSourceGroupFields::EVENT_SOURCES => array(
    <PIXEL_ID>,
    <APP_ID>,
  ),
));

$event_source_group->create();
from facebookads.adobjects.eventsourcegroup import EventSourceGroup

event_source_group = EventSourceGroup(parent_id=<BUSINESS_ID>)
event_source_group[EventSourceGroup.Field.name] = 'My Travel Company Events'
event_source_group[EventSourceGroup.Field.event_sources] = [
    <PIXEL_ID>,
    <APP_ID>,
]

event_source_group.remote_create()
curl \
  -F 'name=My Travel Company Events' \
  -F 'event_sources=["<PIXEL_ID>","<APP_ID>"]' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.10/<BUSINESS_ID>/event_source_groups

You must then share this event source group out to any ad accounts that wish to create an audience backed by it. Again, this is done by making an HTTP POST call:

use FacebookAds\Object\EventSourceGroup;

$event_source_group = new EventSourceGroup(<EVENT_SOURCE_GROUP_ID>);
// ad account id without 'act_'
$event_source_group->createSharedAccount(array(), array(
  'accounts' => array(
    '<ACCOUNT_ID_WITHOUT_ACT>',
  ),
));
from facebookads.adobjects.eventsourcegroup import EventSourceGroup

event_source_group = EventSourceGroup(<EVENT_SOURCE_GROUP_ID>)
# ad account id without 'act_'
response = event_source_group.create_shared_account(
    params={
        'accounts': ['<ACCOUNT_ID_WITHOUT_ACT>'],
    },
)
print(response)
curl \
  -F 'accounts=["<ACCOUNT_ID_WITHOUT_ACT>"]' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.10/<EVENT_SOURCE_GROUP_ID>/shared_accounts

Step 4: Create Travel Audiences

At this point you should have your user signal (i.e. pixel and/or app events) set-up and associated with an event source group and your travel catalog(s).

To retarget people who have shown explicit traveler intent, you must create a dynamic travel audience of people who you would like to serve the ad to. You include/exclude people from the audience based on the set of traveler intent signals that they have demonstrated through sources such as your app or pixel event fires. You can also apply additional rule-based filters on top of the events like with Website Custom Audiences.

To set-up a new travel audience, make an HTTP POST to /act_<AD_ACCOUNT_ID>/customaudiences.

Required Parameters

Field NameData TypeDescription

name

string

A name given to identify the audience.

subtype

enum {CLAIM}

The type of custom audience.

Must be set to CLAIM for Dynamic Ads for travel.

claim_objective

enum {TRAVEL}

The objective of the audience when the subtype is CLAIM.

Must be set to TRAVEL for Dynamic Ads for travel.

content_type

enum {HOTEL, FLIGHT, DESTINATION}

Specify the type of signal that should be used to build this audience.

event_source_group

id

Specify the event source group whose events will back the audience.

inclusions

object[]

An array of JSON objects listing each intent signal that would make a person eligible for this audience.

event

(required)

enum {

Search,

ViewContent,

InitiateCheckout,

Purchase

}

The event name of a signal you want to consider for inclusion, e.g. {"event": "Search", …}.

retention

(required)

object

The minimum/maximum amount of time since the event was received for it to be considered for purposes of inclusion, e.g. {…, "retention": {"min_seconds": 0, "max_seconds": 259200}, …}. The retention window must be at least 4 hours.

booking_window

object

The minimum/maximum amount of time between the current date and the desired check-in date, e.g. {"booking_window": {"min_seconds": 0, "max_seconds": 259200}}. You can also use this to target people whose checkin_date has already passed, e.g. {"booking_window": {"max_seconds": 0}}.

count

JSON operators

The number of times that the event has been fired. You can use both equality and numeric comparison operators here, e.g. {…"count": {"lte": 3}, …}.

Optional Parameters

Field NameData TypeDescription

description

string

A further description of the audience.

exclusions

object[]

An array of JSON objects listing each intent signal that would exclude an eligible person from this audience.

event

(required)

enum {

Search

ViewContent

InitiateCheckout

Purchase

}

The event name of a signal you want to be considered for exclusion, e.g. {"event": "Purchase", …}.

retention

(required)

object

The minimum/maximum amount of time since the event was received for it to be considered for the purposes of exclusion, e.g. {…, "retention": {"min_seconds": 0, "max_seconds": 259200}, …}. The retention window must be at least 4 hours.

rule

object

A classical audience rule to be applied to the event stream before any inclusions and exclusions are processed.

Expand for the list of DAT-specific fields that are available for which you can use with any of the standard JSON operators.

hotel_set_id

int

The ID of hotel sets that contain hotels that match with the event's content_ids parameter, e.g. {…, "hotel_set_id": {"eq": 123456789}, …}.

destination_set_id

int

The ID of destination sets that contain destinations that match with the event's content_ids parameter, e.g. {…, "destination_set_id": {"eq": 123456789}, …}.

flight_set_id

int

The ID of flight sets that contain flights that match with the event's origin_airport and destination_airport parameters, e.g. {…, "flight_set_id": {"eq": 123456789}, …}.

length_of_stay

int

Number of nights spent during the trip, e.g. {… "length_of_stay": {"eq": 1}, …}.

number_of_weekends

int

Number of weekends between the start and end date, e.g. {…, "number_of_weekends": {"gte": 5}, …}.

num_travelers

int

Total number of travelers, e.g. {…, "num_travelers": {"gt": 1}, …}.

  • For a content_type of hotel this is num_adults + num_children.
  • For a content_type of flight this is num_adults + num_infants + num_children.

Date fields: e.g.

  • checkin_date
  • checkout_date
  • departing_departure_date
  • departing_arrival_date
  • returning_departure_date
  • returning_arrival_date
  • travel_start
  • travel_end

string

Depending on the content_type, The appropriate date fields can be used to create travel audience, e.g. {"checkin_date": {"gte": "2016-09-01"}}.

itinerary_contains_date

string

The trip contains a specific date, e.g. {"itinerary_contains_date": {"eq": "2016-12-25"}}.

For example, here we create a travel audience that targets lone travelers who have searched at least 3 times in the last 5 days but haven't booked yet:

use FacebookAds\Object\CustomAudience;
use FacebookAds\Object\Fields\CustomAudienceFields;
use FacebookAds\Object\Values\CustomAudienceSubtypeValues;
use FacebookAds\Object\Values\CustomAudienceClaimObjectiveValues;
use FacebookAds\Object\Values\CustomAudienceContentTypeValues;

$custom_audience = new CustomAudience(null, 'act_<AD_ACCOUNT_ID>');
$custom_audience->setData(array(
  CustomAudienceFields::NAME => 'Travel Audience',
  CustomAudienceFields::SUBTYPE => CustomAudienceSubtypeValues::CLAIM,
  CustomAudienceFields::CLAIM_OBJECTIVE =>
    CustomAudienceClaimObjectiveValues::TRAVEL,
  CustomAudienceFields::CONTENT_TYPE => CustomAudienceContentTypeValues::HOTEL,
  CustomAudienceFields::EVENT_SOURCE_GROUP => <EVENT_SOURCE_GROUP_ID>,
  CustomAudienceFields::RULE => array(
    'num_travelers' => array('eq' => 1),
  ),
  'inclusions' => array(
    array(
      'event' => 'Search',
      'count' => array('gt' => 3),
      'retention' => array('min_seconds'=> 0, 'max_seconds'=> 432000),
    ),
  ),
  'exclusions' => array(
    array(
      'event' => 'Purchase',
      'retention' => array('min_seconds'=> 0, 'max_seconds'=> 172800),
    ),
  ),
));
$custom_audience->create();
from facebookads.adobjects.customaudience import CustomAudience
from facebookads.adobjects.adaccount import AdAccount

ad_account = AdAccount(fbid='act_<AD_ACCOUNT_ID>')

params = {
    CustomAudience.Field.name: 'Travel Audience',
    CustomAudience.Field.subtype: CustomAudience.Subtype.claim,
    CustomAudience.Field.claim_objective: CustomAudience.ClaimObjective.travel,
    CustomAudience.Field.content_type: CustomAudience.ContentType.hotel,
    CustomAudience.Field.event_source_group: <EVENT_SOURCE_GROUP_ID>,
    CustomAudience.Field.rule: {'num_travelers': {'eq': 1}},
    CustomAudience.Field.inclusions: [
        {
            'event': 'Search',
            'count': {'gt': 3},
            'retention': {'min_seconds': 0, 'max_seconds': 432000},
        },
    ],
    CustomAudience.Field.exclusions: [
        {
            'event': 'Purchase',
            'retention': {'min_seconds': 0, 'max_seconds': 432000},
        },
    ],
}
audience = ad_account.create_custom_audience(params=params)
curl \
  -F 'name=Travel Audience' \
  -F 'subtype=CLAIM' \
  -F 'claim_objective=TRAVEL' \
  -F 'content_type=HOTEL' \
  -F 'event_source_group=<EVENT_SOURCE_GROUP_ID>' \
  -F 'rule={"num_travelers":{"eq":1}}' \
  -F 'inclusions=[ 
    { 
      "event": "Search", 
      "count": {"gt":3}, 
      "retention": {"min_seconds":0,"max_seconds":432000} 
    } 
  ]' \
  -F 'exclusions=[{"event":"Purchase","retention":{"min_seconds":0,"max_seconds":172800}}]' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.10/act_<AD_ACCOUNT_ID>/customaudiences

And in this example, we create a travel audience that targets people who viewed or started booking a hotel in a hotel set in the last 2 days but never completed their booking:

use FacebookAds\Object\CustomAudience;
use FacebookAds\Object\Fields\CustomAudienceFields;
use FacebookAds\Object\Values\CustomAudienceSubtypeValues;
use FacebookAds\Object\Values\CustomAudienceClaimObjectiveValues;
use FacebookAds\Object\Values\CustomAudienceContentTypeValues;

$custom_audience = new CustomAudience(null, 'act_<AD_ACCOUNT_ID>');
$custom_audience->setData(array(
  CustomAudienceFields::NAME => 'Travel Audience',
  CustomAudienceFields::SUBTYPE => CustomAudienceSubtypeValues::CLAIM,
  CustomAudienceFields::CLAIM_OBJECTIVE =>
    CustomAudienceClaimObjectiveValues::TRAVEL,
  CustomAudienceFields::CONTENT_TYPE => CustomAudienceContentTypeValues::HOTEL,
  CustomAudienceFields::EVENT_SOURCE_GROUP => <EVENT_SOURCE_GROUP_ID>,
  CustomAudienceFields::RULE => array(
    'hotel_set_id' => array('eq' => <HOTEL_SET_ID>),
  ),
  'inclusions' => array(
    array(
      'event' => 'ViewContent',
      'retention' => array('min_seconds'=> 0, 'max_seconds'=> 172800),
    ),
    array(
      'event' => 'InitiateCheckout',
      'retention' => array('min_seconds'=> 0, 'max_seconds'=> 172800),
    ),
  ),
  'exclusions' => array(
    array(
      'event' => 'Purchase',
      'retention' => array('min_seconds'=> 0, 'max_seconds'=> 172800),
    ),
  ),
));
$custom_audience->create();
from facebookads.adobjects.customaudience import CustomAudience
from facebookads.adobjects.adaccount import AdAccount

ad_account = AdAccount(fbid='act_<AD_ACCOUNT_ID>')

params = {
    CustomAudience.Field.name: 'Travel Audience',
    CustomAudience.Field.subtype: CustomAudience.Subtype.claim,
    CustomAudience.Field.claim_objective: CustomAudience.ClaimObjective.travel,
    CustomAudience.Field.content_type: CustomAudience.ContentType.hotel,
    CustomAudience.Field.event_source_group: <EVENT_SOURCE_GROUP_ID>,
    CustomAudience.Field.rule: {
        'hotel_set_id': {'eq': <HOTEL_SET_ID>},
    },
    CustomAudience.Field.inclusions: [
        {
            'event': 'ViewContent',
            'retention': {'min_seconds': 0, 'max_seconds': 172800},
        },
        {
            'event': 'InitiateCheckout',
            'retention': {'min_seconds': 0, 'max_seconds': 172800},
        },
    ],
    CustomAudience.Field.exclusions: [
        {
            'event': 'Purchase',
            'retention': {'min_seconds': 0, 'max_seconds': 172800},
        },
    ],
}
audience = ad_account.create_custom_audience(params=params)
curl \
  -F 'name=Travel Audience' \
  -F 'subtype=CLAIM' \
  -F 'claim_objective=TRAVEL' \
  -F 'content_type=HOTEL' \
  -F 'event_source_group=<EVENT_SOURCE_GROUP_ID>' \
  -F 'rule={"hotel_set_id":{"eq":"<HOTEL_SET_ID>"}}' \
  -F 'inclusions=[ 
    {"event":"ViewContent","retention":{"min_seconds":0,"max_seconds":172800}}, 
    { 
      "event": "InitiateCheckout", 
      "retention": {"min_seconds":0,"max_seconds":172800} 
    } 
  ]' \
  -F 'exclusions=[{"event":"Purchase","retention":{"min_seconds":0,"max_seconds":172800}}]' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.10/act_<AD_ACCOUNT_ID>/customaudiences

In this example, we create a travel audience that targets people who have initiated check out or purchased the flight tickets in the last 5 days and their flight booking window is between 2 to 7 days:

use FacebookAds\Object\CustomAudience;
use FacebookAds\Object\Fields\CustomAudienceFields;
use FacebookAds\Object\Values\CustomAudienceSubtypeValues;
use FacebookAds\Object\Values\CustomAudienceClaimObjectiveValues;
use FacebookAds\Object\Values\CustomAudienceContentTypeValues;

$custom_audience = new CustomAudience(null, 'act_<AD_ACCOUNT_ID>');
$custom_audience->setData(array(
  CustomAudienceFields::NAME => 'Travel Audience',
  CustomAudienceFields::SUBTYPE => CustomAudienceSubtypeValues::CLAIM,
  CustomAudienceFields::CLAIM_OBJECTIVE =>
    CustomAudienceClaimObjectiveValues::TRAVEL,
  CustomAudienceFields::CONTENT_TYPE => CustomAudienceContentTypeValues::FLIGHT,
  CustomAudienceFields::EVENT_SOURCE_GROUP => <EVENT_SOURCE_GROUP_ID>,
  'inclusions' => array(
    array(
      'event' => 'InitiateCheckout',
      'retention' => array('min_seconds'=> 0, 'max_seconds'=> 432000),
      'booking_window' => array('min_seconds'=> 172800, 'max_seconds'=> 604800),
    ),
    array(
      'event' => 'Purchase',
      'retention' => array('min_seconds'=> 0, 'max_seconds'=> 432000),
      'booking_window' => array('min_seconds'=> 172800, 'max_seconds'=> 604800),
    ),
  ),
));
$custom_audience->create();
from facebookads.adobjects.customaudience import CustomAudience
from facebookads.adobjects.adaccount import AdAccount

ad_account = AdAccount(fbid='act_<AD_ACCOUNT_ID>')

params = {
    CustomAudience.Field.name: 'Travel Audience',
    CustomAudience.Field.subtype: CustomAudience.Subtype.claim,
    CustomAudience.Field.claim_objective: CustomAudience.ClaimObjective.travel,
    CustomAudience.Field.content_type: CustomAudience.ContentType.flight,
    CustomAudience.Field.event_source_group: <EVENT_SOURCE_GROUP_ID>,
    CustomAudience.Field.inclusions: [
        {
            "event": "InitiateCheckout",
            "retention": {"min_seconds": 0, "max_seconds": 432000},
            "booking_window": {"min_seconds": 172800, "max_seconds": 604800},
        },
        {
            "event": "Purchase",
            "retention": {"min_seconds": 0, "max_seconds": 432000},
            "booking_window": {"min_seconds": 172800, "max_seconds": 604800},
        },
    ],
}
audience = ad_account.create_custom_audience(params=params)
curl \
  -F 'name=Travel Audience' \
  -F 'subtype=CLAIM' \
  -F 'claim_objective=TRAVEL' \
  -F 'content_type=FLIGHT' \
  -F 'event_source_group=<EVENT_SOURCE_GROUP_ID>' \
  -F 'inclusions=[ 
    { 
      "event": "InitiateCheckout", 
      "retention": {"min_seconds":0,"max_seconds":432000}, 
      "booking_window": {"min_seconds":172800,"max_seconds":604800} 
    }, 
    { 
      "event": "Purchase", 
      "retention": {"min_seconds":0,"max_seconds":432000}, 
      "booking_window": {"min_seconds":172800,"max_seconds":604800} 
    } 
  ]' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.10/act_<AD_ACCOUNT_ID>/customaudiences

In this example, we create a travel audience that targets people who have searched hotels in 'New York City' more than 3 times in the past 2 days but haven't booked yet:

use FacebookAds\Object\CustomAudience;
use FacebookAds\Object\Fields\CustomAudienceFields;
use FacebookAds\Object\Values\CustomAudienceSubtypeValues;
use FacebookAds\Object\Values\CustomAudienceClaimObjectiveValues;
use FacebookAds\Object\Values\CustomAudienceContentTypeValues;

$custom_audience = new CustomAudience(null, 'act_<AD_ACCOUNT_ID>');
$custom_audience->setData(array(
  CustomAudienceFields::NAME => 'Travel Audience',
  CustomAudienceFields::SUBTYPE => CustomAudienceSubtypeValues::CLAIM,
  CustomAudienceFields::CLAIM_OBJECTIVE =>
    CustomAudienceClaimObjectiveValues::TRAVEL,
  CustomAudienceFields::CONTENT_TYPE => CustomAudienceContentTypeValues::HOTEL,
  CustomAudienceFields::EVENT_SOURCE_GROUP => <EVENT_SOURCE_GROUP_ID>,
  CustomAudienceFields::RULE => array(
    'destination' => array('i_contains' => 'New York City'),
  ),
  'inclusions' => array(
    array(
      'event' => 'Search',
      'count' => array('gt' => 3),
      'retention' => array('min_seconds'=> 0, 'max_seconds'=> 172800),
    ),
  ),
  'exclusions' => array(
    array(
      'event' => 'Purchase',
      'retention' => array('min_seconds'=> 0, 'max_seconds'=> 172800),
    ),
  ),
));
$custom_audience->create();
from facebookads.adobjects.customaudience import CustomAudience
from facebookads.adobjects.adaccount import AdAccount

ad_account = AdAccount(fbid='act_<AD_ACCOUNT_ID>')

params = {
    CustomAudience.Field.name: 'Travel Audience',
    CustomAudience.Field.subtype: CustomAudience.Subtype.claim,
    CustomAudience.Field.claim_objective: CustomAudience.ClaimObjective.travel,
    CustomAudience.Field.content_type: CustomAudience.ContentType.hotel,
    CustomAudience.Field.event_source_group: <EVENT_SOURCE_GROUP_ID>,
    CustomAudience.Field.rule: {
        'destination': {'i_contains': 'New York City'},
    },
    CustomAudience.Field.inclusions: [
        {
            'event': 'Search',
            'count': {'gt': 3},
            'retention': {'min_seconds': 0, 'max_seconds': 172800},
        },
    ],
    CustomAudience.Field.exclusions: [
        {
            'event': 'Purchase',
            'retention': {'min_seconds': 0, 'max_seconds': 172800},
        },
    ],
}
audience = ad_account.create_custom_audience(params=params)
curl \
  -F 'name=Travel Audience' \
  -F 'subtype=CLAIM' \
  -F 'claim_objective=TRAVEL' \
  -F 'content_type=HOTEL' \
  -F 'event_source_group=<EVENT_SOURCE_GROUP_ID>' \
  -F 'rule={"destination":{"i_contains":"New York City"}}' \
  -F 'inclusions=[ 
    { 
      "event": "Search", 
      "count": {"gt":3}, 
      "retention": {"min_seconds":0,"max_seconds":172800} 
    } 
  ]' \
  -F 'exclusions=[{"event":"Purchase","retention":{"min_seconds":0,"max_seconds":172800}}]' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.10/act_<AD_ACCOUNT_ID>/customaudiences

In this example, we create a travel audience that targets people who have searched hotels between specific checkin_date and checkout_date in the past 2 days but haven't booked yet:

use FacebookAds\Object\CustomAudience;
use FacebookAds\Object\Fields\CustomAudienceFields;
use FacebookAds\Object\Values\CustomAudienceSubtypeValues;
use FacebookAds\Object\Values\CustomAudienceClaimObjectiveValues;
use FacebookAds\Object\Values\CustomAudienceContentTypeValues;

$custom_audience = new CustomAudience(null, 'act_<AD_ACCOUNT_ID>');
$custom_audience->setData(array(
  CustomAudienceFields::NAME => 'Travel Audience',
  CustomAudienceFields::SUBTYPE => CustomAudienceSubtypeValues::CLAIM,
  CustomAudienceFields::CLAIM_OBJECTIVE =>
    CustomAudienceClaimObjectiveValues::TRAVEL,
  CustomAudienceFields::CONTENT_TYPE => CustomAudienceContentTypeValues::HOTEL,
  CustomAudienceFields::EVENT_SOURCE_GROUP => <EVENT_SOURCE_GROUP_ID>,
  CustomAudienceFields::RULE => array(
    'and' => array(
      array(
        'checkin_date' => array(
          'gte' => (new \DateTime("+3 day"))->format('Y-m-d')
        ),
      ),
      array(
        'checkout_date' => array(
          'lte' => (new \DateTime("+6 day"))->format('Y-m-d')
        ),
      ),
    ),
  ),
  'inclusions' => array(
    array(
      'event' => 'Search',
      'retention' => array('min_seconds'=> 0, 'max_seconds'=> 172800),
    ),
  ),
  'exclusions' => array(
    array(
      'event' => 'Purchase',
      'retention' => array('min_seconds'=> 0, 'max_seconds'=> 172800),
    ),
  ),
));
$custom_audience->create();
from facebookads.adobjects.customaudience import CustomAudience
from facebookads.adobjects.adaccount import AdAccount
from datetime import date, timedelta

ad_account = AdAccount(fbid='act_<AD_ACCOUNT_ID>')

params = {
    CustomAudience.Field.name: 'Travel Audience',
    CustomAudience.Field.subtype: CustomAudience.Subtype.claim,
    CustomAudience.Field.claim_objective: CustomAudience.ClaimObjective.travel,
    CustomAudience.Field.content_type: CustomAudience.ContentType.hotel,
    CustomAudience.Field.event_source_group: <EVENT_SOURCE_GROUP_ID>,
    CustomAudience.Field.rule: {
        'and': [
            {
                "checkin_date": {
                    "gte": str(date.today() + timedelta(days=3)),
                },
            },
            {
                "checkout_date": {
                    "gte": str(date.today() + timedelta(days=6)),
                },
            },
        ],
    },
    CustomAudience.Field.inclusions: [
        {
            'event': 'Search',
            'retention': {'min_seconds': 0, 'max_seconds': 172800},
        },
    ],
    CustomAudience.Field.exclusions: [
        {
            'event': 'Purchase',
            'retention': {'min_seconds': 0, 'max_seconds': 172800},
        },
    ],
}
audience = ad_account.create_custom_audience(params=params)
curl \
  -F 'name=Travel Audience' \
  -F 'subtype=CLAIM' \
  -F 'claim_objective=TRAVEL' \
  -F 'content_type=HOTEL' \
  -F 'event_source_group=<EVENT_SOURCE_GROUP_ID>' \
  -F 'rule={ 
    "and": [ 
      {"checkin_date":{"gte":"2017-08-18"}}, 
      {"checkout_date":{"lte":"2017-08-21"}} 
    ] 
  }' \
  -F 'inclusions=[{"event":"Search","retention":{"min_seconds":0,"max_seconds":172800}}]' \
  -F 'exclusions=[{"event":"Purchase","retention":{"min_seconds":0,"max_seconds":172800}}]' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.10/act_<AD_ACCOUNT_ID>/customaudiences

In this example, we create a travel audience that targets people who have searched hotel stays containing a specific date (e.g. Christmas) in the past 2 days but haven't booked yet:

use FacebookAds\Object\CustomAudience;
use FacebookAds\Object\Fields\CustomAudienceFields;
use FacebookAds\Object\Values\CustomAudienceSubtypeValues;
use FacebookAds\Object\Values\CustomAudienceClaimObjectiveValues;
use FacebookAds\Object\Values\CustomAudienceContentTypeValues;

$custom_audience = new CustomAudience(null, 'act_<AD_ACCOUNT_ID>');
$custom_audience->setData(array(
  CustomAudienceFields::NAME => 'Travel Audience',
  CustomAudienceFields::SUBTYPE => CustomAudienceSubtypeValues::CLAIM,
  CustomAudienceFields::CLAIM_OBJECTIVE =>
    CustomAudienceClaimObjectiveValues::TRAVEL,
  CustomAudienceFields::CONTENT_TYPE => CustomAudienceContentTypeValues::HOTEL,
  CustomAudienceFields::EVENT_SOURCE_GROUP => <EVENT_SOURCE_GROUP_ID>,
  CustomAudienceFields::RULE => array(
    'itinerary_contains_date' => array(
      'eq' => (new \DateTime())->setDate(Date('Y'), 12, 25)->format('Y-m-d')
    ),
  ),
  'inclusions' => array(
    array(
      'event' => 'Search',
      'retention' => array('min_seconds'=> 0, 'max_seconds'=> 172800),
    ),
  ),
  'exclusions' => array(
    array(
      'event' => 'Purchase',
      'retention' => array('min_seconds'=> 0, 'max_seconds'=> 172800),
    ),
  ),
));
$custom_audience->create();
from facebookads.adobjects.customaudience import CustomAudience
from facebookads.adobjects.adaccount import AdAccount
import datetime

ad_account = AdAccount(fbid='act_<AD_ACCOUNT_ID>')

params = {
    CustomAudience.Field.name: 'Travel Audience',
    CustomAudience.Field.subtype: CustomAudience.Subtype.claim,
    CustomAudience.Field.claim_objective: CustomAudience.ClaimObjective.travel,
    CustomAudience.Field.content_type: CustomAudience.ContentType.hotel,
    CustomAudience.Field.event_source_group: <EVENT_SOURCE_GROUP_ID>,
    CustomAudience.Field.rule: {
        "itinerary_contains_date": {
            "eq": str(datetime.date(datetime.date.today().year, 12, 25)),
        },
    },
    CustomAudience.Field.inclusions: [
        {
            'event': 'Search',
            'retention': {'min_seconds': 0, 'max_seconds': 172800},
        },
    ],
    CustomAudience.Field.exclusions: [
        {
            'event': 'Purchase',
            'retention': {'min_seconds': 0, 'max_seconds': 172800},
        },
    ],
}
audience = ad_account.create_custom_audience(params=params)
curl \
  -F 'name=Travel Audience' \
  -F 'subtype=CLAIM' \
  -F 'claim_objective=TRAVEL' \
  -F 'content_type=HOTEL' \
  -F 'event_source_group=<EVENT_SOURCE_GROUP_ID>' \
  -F 'rule={"itinerary_contains_date":{"eq":"2017-12-25"}}' \
  -F 'inclusions=[{"event":"Search","retention":{"min_seconds":0,"max_seconds":172800}}]' \
  -F 'exclusions=[{"event":"Purchase","retention":{"min_seconds":0,"max_seconds":172800}}]' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.10/act_<AD_ACCOUNT_ID>/customaudiences

Once you have created your audience(s), they can then be added to the targeting spec in your Dynamic Ads for travel campaign.

For Dynamic Ads for Travel, you do not need to provide hotel_set_id to create an audience. If hotel_set_id is specified, it can also be different from the one you specified in the ad set and ad creative.

This enables the following use cases:

  • Create a travel audience of people who searched, viewed or purchased any hotels from an entire catalog, and show them hotels from a specific hotel set.
  • Create a travel audience of people who searched, viewed or purchased flight tickets where there is no hotel set, and show them hotels from a specific hotel set.