Advanced Targeting and Placement

Targeting Specs are ad set attributes that define who sees an ad.

Deprecated Targeting Terms

We continuously review the available targeting options as part of our ongoing efforts to provide relevant and quality ad experiences for advertisers and developers. As a result, certain targeting options may become deprecated and ad sets targeted at these objects may pause the delivery.

To identify ad sets targeted at deprecated targeting options, use the following API endpoint:

curl -G \
  -d 'type=<TYPE_VALUE>'
  'https://graph.facebook.com/<API_VERSION>/act_<AD_ACCOUNT_ID>/deprecatedtargetingadsets

The response

{"data":[{"id":"<ADSET_ID>"},{"id":"<ADSET_ID>"},{"id":"<ADSET_ID>"}]}

Note: Until May 11, 2018, this endpoint will be 1 day behind actual status.

The type parameter is optional. If not provided, the system returns deprecating ad sets by default.

  • deprecating - Default value. These ad sets continue to deliver, but can't be duplicated into new ad sets. When updated, ad sets with deprecating terms will be rejected unless the terms are removed.

  • delivery_paused - Ad sets with terms no longer valid for delivery, and have been paused by Facebook.

To verify the status of objects listed under ad set targeting specification, use the targeting_option_list parameter in Targeting Search.

You can filter ad account ad sets by their targeting state using the adset.targeting_state filter.

Sample call:

`<act_AD_ACCOUNT_ID>/adsets?filtering=[{"field":"adset.targeting_state","operator":"IN","value""deprecating"]}]`

The filter supports these values: normal, deprecating, delivery_affected, delivery_paused.

Advanced Targeting Options

Use these advanced options, your own in Custom Audiences and Lookalikes, or 3rd party Partner Categories. Use any combination of targeting; by default Facebook ORs combinations together. For "core", or basic targeting, see Targeting. Advanced targeting includes:

If you use flexible_spec, you must also provide one of the following under targeting:

  • geo_locations: geographical targeting field from country, region, city or zip
  • custom_audiences
  • product_audience_specs
  • dynamic_audience_ids

See Limits

Mobile

This is useful for Mobile App Install ads.

use FacebookAds\Object\AdSet;
use FacebookAds\Object\Fields\AdSetFields;
use FacebookAds\Object\Values\AdSetBillingEventValues;
use FacebookAds\Object\Values\AdSetOptimizationGoalValues;
use FacebookAds\Object\Fields\TargetingFields;
use FacebookAds\Object\Targeting;

$adset = new AdSet(null, 'act_<AD_ACCOUNT_ID>');
$adset->setData(array(
  AdSetFields::NAME => 'My AdSet',
  AdSetFields::OPTIMIZATION_GOAL => AdSetOptimizationGoalValues::REACH,
  AdSetFields::BILLING_EVENT => AdSetBillingEventValues::IMPRESSIONS,
  AdSetFields::BID_AMOUNT => 2,
  AdSetFields::DAILY_BUDGET => 1000,
  AdSetFields::CAMPAIGN_ID => <CAMPAIGN_ID>,
  AdSetFields::TARGETING => (new Targeting())->setData(array(
    TargetingFields::GEO_LOCATIONS => array(
      'countries' => array(
        'US',
      ),
    ),
    TargetingFields::USER_DEVICE => array(
      'Galaxy S6',
      'One m9',
    ),
    TargetingFields::USER_OS => array('android'),
  )),
));

$adset->create(array(
  AdSet::STATUS_PARAM_NAME => AdSet::STATUS_ACTIVE,
));
from facebookads.adobjects.adset import AdSet

adset = AdSet(parent_id='act_<AD_ACCOUNT_ID>')
adset.update({
    AdSet.Field.name: 'My AdSet',
    AdSet.Field.optimization_goal: AdSet.OptimizationGoal.reach,
    AdSet.Field.billing_event: AdSet.BillingEvent.impressions,
    AdSet.Field.bid_amount: 150,
    AdSet.Field.daily_budget: 2000,
    AdSet.Field.campaign_id: <CAMPAIGN_ID>,
    AdSet.Field.targeting: {
        'geo_locations': {
            'countries': ['US'],
        },
        'user_device': [
            'galaxy s6',
            'one m9',
        ],
        'user_os': ['android'],
    },
})
adset.remote_create(params={
    'status': AdSet.Status.active,
})
AdSet adSet = new AdAccount(act_<AD_ACCOUNT_ID>, context).createAdSet()
  .setName("My AdSet")
  .setOptimizationGoal(AdSet.EnumOptimizationGoal.VALUE_REACH)
  .setBillingEvent(AdSet.EnumBillingEvent.VALUE_IMPRESSIONS)
  .setBidAmount(2L)
  .setDailyBudget(1000L)
  .setCampaignId(<CAMPAIGN_ID>)
  .setTargeting(
    new Targeting()
      .setFieldGeoLocations(
        new TargetingGeoLocation()
          .setFieldCountries(Arrays.asList("US"))
      )
      .setFieldUserDevice(Arrays.asList("Galaxy S6", "One m9"))
      .setFieldUserOs(Arrays.asList("android"))
  )
  .setStatus(AdSet.EnumStatus.VALUE_ACTIVE)
  .execute();
String ad_set_id = adSet.getId();
curl \
  -F 'name=My AdSet' \
  -F 'optimization_goal=REACH' \
  -F 'billing_event=IMPRESSIONS' \
  -F 'bid_amount=2' \
  -F 'daily_budget=1000' \
  -F 'campaign_id=<CAMPAIGN_ID>' \
  -F 'targeting={ 
    "geo_locations": {"countries":["US"]}, 
    "user_device": ["Galaxy S6","One m9"], 
    "user_os": ["android"] 
  }' \
  -F 'status=ACTIVE' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/adsets

You can combine categories, such as iPod OR iPad OR iPhone.

These categories are not mutually exclusive. If you select iOS you target all devices running iOS, including iPhone and iPod, without specifying user_device.

For Brand Awareness Objective ads, you can't target based on mobile device type, such as feature phones or Samsung, or based on iOS version number. You can only choose Android or iOS, or all mobile phones.

Name: Type Description Mobile app ad

user_os: array

One or more values from OS option table below. Possible values are at Targeting Search API with type=adTargetingCategory and class=user_os. You cannot target the minimum version of one platform with the other platform. However you can target both platforms without specifying minimal versions of either.
Valid:
- ['iOS', 'Android']
- ['iOS']
- ['Android_ver_4.2_and_above']
- ['iOS_ver_8.0_to_9.0']
Invalid:
- ['Android', 'iOS_ver_8.0_and_above']
- ['iOS', 'Android_ver_4.0_and_above']

Required

user_device: array

Devices must match the value in user_os. Get possible values at Targeting Search API with type=adTargetingCategory and class=user_device.

Optional

excluded_user_device: array

Devices to exclude. Devices must match the value in user_os. Get possible values at Targeting Search API with type=adTargetingCategory and class=user_device.

Not Required

wireless_carrier: array

Allowed value is Wifi. Target mobile users currently on wifi networks.

Optional


OS option: Type Description

iOS: string

iOS devices, including iPhone, iPad, and iPod

iOS_ver_x.x_and_above: string

iOS devices running OS version x.x and above. Options: 2.0, 3.0, 4.0, 4.3, 5.0, 6.0, 7.0, 8.0, 9.0. e.g. iOS_ver_4.0_and_above

iOS_ver_x.x_to y.y: string

iOS devices running OS versions x.x to y.y. Options: 2.0, 3.0, 4.0, 4.3, 5.0, 6.0, 7.0, 8.0, 9.0. x.x must be less than y.y such as iOS_ver_8.0_to_9.0

Android: string

Android devices

Android_ver_x.x_and_above: string

Android devices running version x.x and above. Options: 2.0, 2.1, 2.2, 2.3, 3.0, 3.1, 3.2, 4.0, 4.1, 4.2., 4.3, 4.4, 5.0, 5.1, 6.0, 7.0, 7.1, and 8.0. e.g. Android_ver_4.0_and_above

Android_ver_x.x_to y.y: string

Android devices running versions x.x to y.y. Values are: 2.0, 2.1, 2.2, 2.3, 3.0, 3.1, 3.2, 4.0, 4.1, 4.2., 4.3, 4.4, 5.0, 5.1, 6.0, 7.0, 7.1, and 8.0. x.x must be less than y.y, such as Android_ver_4.2_to_8.0

Placement

Deliver ads on specific placements, such as desktop News Feed only, or mobile News Feed plus Audience Network Rewarded Video. You can only use certain placement options depending on your campaign objective. See Validation.

You can use device_platforms, publisher_platforms, facebook_positions, audience_network_positions, instagram_positions and messenger_positions, see Device, Publisher and Positions.

curl -X POST \ -F 'name="My AdSet"' \ -F 'optimization_goal="REACH"' \ -F 'billing_event="IMPRESSIONS"' \ -F 'bid_amount=2' \ -F 'daily_budget=1000' \ -F 'campaign_id="<AD_CAMPAIGN_ID>"' \ -F 'targeting={ "geo_locations": { "countries": [ "US" ] }, "publisher_platforms": [ "facebook" ] }' \ -F 'promoted_object={ "page_id": "<PAGE_ID>" }' \ -F 'access_token=<ACCESS_TOKEN>' \ https://graph.facebook.com/v3.2/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 logApiCallResult = (apiCallName, data) => { console.log(apiCallName); if (showDebugingInfo) { console.log('Data:' + JSON.stringify(data)); } }; let fields, params; fields = [ ]; params = { 'name' : 'My AdSet', 'optimization_goal' : 'REACH', 'billing_event' : 'IMPRESSIONS', 'bid_amount' : '2', 'daily_budget' : '1000', 'campaign_id' : '<adCampaignLinkClicksID>', 'targeting' : {'geo_locations':{'countries':['US']},'publisher_platforms':['facebook']}, 'promoted_object' : {'page_id':'<pageID>'}, }; let adsets = (new AdAccount(id)).createAdSet( fields, params ); logApiCallResult('adsets api call complete.', adsets);
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' => 'My AdSet', 'optimization_goal' => 'REACH', 'billing_event' => 'IMPRESSIONS', 'bid_amount' => '2', 'daily_budget' => '1000', 'campaign_id' => '<adCampaignLinkClicksID>', 'targeting' => array('geo_locations' => array('countries' => array('US')),'publisher_platforms' => array('facebook')), 'promoted_object' => array('page_id' => '<pageID>'), ); echo json_encode((new AdAccount($id))->createAdSet( $fields, $params )->exportAllData(), 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': 'My AdSet', 'optimization_goal': 'REACH', 'billing_event': 'IMPRESSIONS', 'bid_amount': '2', 'daily_budget': '1000', 'campaign_id': '<adCampaignLinkClicksID>', 'targeting': {'geo_locations':{'countries':['US']},'publisher_platforms':['facebook']}, 'promoted_object': {'page_id':'<pageID>'}, } 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(\"My AdSet\") .setOptimizationGoal(AdSet.EnumOptimizationGoal.VALUE_REACH) .setBillingEvent(AdSet.EnumBillingEvent.VALUE_IMPRESSIONS) .setBidAmount(2L) .setDailyBudget(1000L) .setCampaignId(\"<adCampaignLinkClicksID>\") .setTargeting( new Targeting() .setFieldGeoLocations( new TargetingGeoLocation() .setFieldCountries(Arrays.asList(\"US\")) ) .setFieldPublisherPlatforms(Arrays.asList(\"facebook\")) ) .setPromotedObject(\"{\\"page_id\\":\\"<pageID>\\"}\") .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) adsets = ad_account.adsets.create({ name: 'My AdSet', optimization_goal: 'REACH', billing_event: 'IMPRESSIONS', bid_amount: '2', daily_budget: '1000', campaign_id: '<adCampaignLinkClicksID>', targeting: {'geo_locations':{'countries':['US']},'publisher_platforms':['facebook']}, promoted_object: {'page_id':'<pageID>'}, })

If you do not specify anything for a particular placement field, Facebook considers all possible default positions for that field. For example, if you select facebook in publisher_platforms, but select nothing for facebook_positions, Facebook consider all default Facebook positions such as feed, right_hand_column, and so on. Or, if you do not select any publisher_platforms, Facebook considers all default publisher_platforms. Facebook may also automatically consider new positions or platforms as they become available.

On Audience Network, you can limit which publishers display your ads. Exclude publishers by category, or create a custom list of app store URLs or domain URLs to exclude.

You cannot use only right_hand_column alone as a placement for video, collection or canvas ads.

Name: Type Description

excluded_publisher_categories

Array of strings values, including: dating and gambling

excluded_publisher_list_ids: array

Array of numeric strings. Each string is a list ID for exclusions. Create custom lists in Ads Manager or Marketing API, Publisher Block List
Example "excluded_publisher_list_ids":["{block_list_id_1}","{block_list_id_2}"]

For In-Stream video, you can also exclude publishers by category:

Name: Type Description

excluded_publisher_categories: array

String values, including:
debated_social_issues
mature_audiences
tragedy_and_conflict
Example "excluded_publisher_categories": ["debated_social_issues", "mature_audiences"]

Device, Publisher and Positions

Use these targeting specs subfields: device_platforms, publisher_platforms, facebook_positions, audience_network_positions and instagram_positions. device_platforms are device types someone has who sees your ad. Use publisher_platforms for publishing channel such as Instagram. xxxxxx_positions are positions on a certain publishing channel if there are multiple:

Name: Options Default Comments

device_platforms: mobile, desktop

All

Optional

publisher_platforms: facebook, instagram, messenger, audience_network

Facebook, Instagram, Audience Network, Messenger

Optional

facebook_positions: feed, right_hand_column, instant_article, marketplace, and story.


If you select story, you must use Facebook feed or Instagram story and for device_platforms, you must use mobile since Facebook Stories is mobile-only.

All

Optional.


If provided, publisher_platforms must include facebook or do not provide to default to All. feed includes News Feed for Desktop and Mobile.


If you select instant_article, you must use feed and for device_platforms, you must use mobile because Instant Articles is mobile-only.


For campaigns targeting the United States (US), United Kingdom (GB), France (FR), Spain (ES), Germany (DE), Mexico (MX), India (IN) and Thailand (TH), you can use instream_video without feed for Video View and Post Engagement objectives. For the CONVERSIONS objective, instream_video is not supported.


If you select marketplace, you must use feed and for device_platforms, you must use mobile because ads in Marketplace only deliver on mobile.


As of v3.0, right_hand_column is only available for single image, single video, and carousel formats for the TRAFFIC, CONVERSIONS, and PRODUCT_CATALOG_SALES objectives.

instagram_positions: stream, story

All

Optional


You can target Instagram carousel ads for Instagram stream or story, but cannot select both options for the same ad set.

audience_network_positions: classic, instream_video, rewarded_video

All

Optional. By default, we don't return effective_audience_network_positions when you read the targeting spec for an ad set. This may differ from your configured audience_network_positions. If you specify a position that isn't supported for a given objective, it appears in the list of configured positions, but not in the list of effective positions.

messenger_positions: messenger_home, sponsored_messages, story

messenger_home, story

Optional. If you select messenger_home, you must also select Facebook publisher_platform and feed in facebook_positions.


messenger_home is available for single image, carousel, and video formats in LINK_CLICKS, CONVERSIONS, REACH, BRAND_AWARENESS, MESSAGES, PRODUCT_CATALOG_SALES, and APP_INSTALLS objectives for ads driving traffic to websites, apps, and Messenger.


If you select story, you must use Facebook feed or Instagram story.


For device_platforms, you must use mobile because Messenger Stories is mobile-only. story is available for single image and video formats in CONVERSIONS, and APP_INSTALLS objectives for ads driving traffic to websites and apps.


Note: sponsored_messages cannot be used with the other placements, including messenger_home and Facebook ones.

The logic for options in the same parameter is “OR”. For example, publisher_platforms=['facebook','instagram'] means deliver ads on Facebook and Instagram. The logic between parameters is “AND”. For example, publisher_platforms=['facebook']&device_platforms=['mobile'] means deliver these ads to Facebook Mobile only. If the logic results in targeting no one, such as publisher_platforms=['instagram']& device_platforms=['desktop'], you see an error.

All Facebook validations apply, for example, you cannot use Audience Network alone.

Stories

To use Facebook Stories as your placement:

curl \
  -F 'name=My Ad Set' 
  -F 'optimization_goal=CONVERSIONS' 
  -F 'billing_event=IMPRESSIONS' 
  -F 'bid_amount=2' 
  -F 'daily_budget=1000' 
  -F 'campaign_id=<AD_CAMPAIGN_ID>' 
  -F 'targeting={"geo_locations":{"countries":["US"]}, "publisher_platforms":["messenger", "facebook"], "facebook_positions":["feed"], "messenger_positions":["story"]}' 
  -F 'status=ACTIVE'
  -F 'access_token=<ACCESS_TOKEN>' 
  https://graph.facebook.com/API_VERSION/act_AD_ACCOUNT_ID/adsets

Instream Video

To create an ad set with only instream_video placement that targets a supported country listed above:

curl \
  -F 'name=My AdSet' \
  -F 'optimization_goal=REACH' \
  -F 'billing_event=IMPRESSIONS' \
  -F 'bid_amount=2' \
  -F 'daily_budget=1000' \
  -F 'campaign_id=CAMPAIGN_ID' \
  -F 'targeting={"geo_locations":{"countries":["US"]},"publisher_platforms":["facebook"], "facebook_positions":["instream_video"]}' \
  -F 'status=ACTIVE' \
  -F 'access_token=ACCESS_TOKEN' \
  https://graph.facebook.com/API_VERSION/act_AD_ACCOUNT_ID/adsets

Instant Articles

To use Instant Articles as your placement:

curl \
-F 'name=My Ad Set' \
-F 'optimization_goal=REACH' \
-F 'billing_event=IMPRESSIONS' \
-F 'bid_amount=2' \
-F 'daily_budget=1000' \
-F 'campaign_id=<AD_CAMPAIGN_ID>' \
-F 'targeting={"geo_locations":{"countries":["US"]}, "facebook_positions":["feed", "instant_article"]}' \
-F 'status=ACTIVE' \
-F 'access_token=<ACCESS_TOKEN>' \
https://graph.facebook.com/<APIVERSION>/act<AD_ACCOUNT_ID>/adsets

Audience Network

To target the Audience Network Rewarded Video placement:

curl \
-F 'name=My Ad Set' \
-F 'optimization_goal=OFFSITE_CONVERSIONS' \
-F 'billing_event=IMPRESSIONS' \
-F 'is_autobid=true' \
-F 'daily_budget=40000' \
-F 'campaign_id=<AD_CAMPAIGN_ID>' \
-F 'targeting={"app_install_state": "not_installed","geo_locations":{"countries":["US"]},"facebook_positions":["feed"],"device_platforms": ["mobile"],"audience_network_positions": ["classic","rewarded_video"],"user_device": ["Android_Smartphone","Android_Tablet"],"user_os": ["Android_ver_4.4_and_above"]}' \
-F 'promoted_object={"application_id": "<APPLICATION_ID>","custom_event_type": "PURCHASE","object_store_url": "<OBJECT_STORE_URL>"}' \
-F 'status=ACTIVE' \
-F 'access_token=<ACCESS_TOKEN>' \
https://graph.facebook.com/<APIVERSION>/<AD_ACCOUNT_ID>/adsets

This returns:

{
  "targeting": {
    "audience_network_positions": [
      "classic",
      "rewarded_video"
    ],
    "effective_audience_network_positions": [
      "classic",
      "rewarded_video"
    ]
  },
  "id": "<AD_SET_ID>"
}

Effective Placement with Targeting

You create ad sets with placements in target spec, however you did not always know if Facebook delivered your ad to the placements specified. This is because your selected placement may not apply to your chosen advertising objective. With the effective placements API for targeting, you can now determine which placements your ad will deliver to, given your targeting options, and receive validation messages to understand why some placements are filtered out. If you do not provide targeting, you can still determine the effective placement based on ad set and ad campaign settings, see Effective Placements.

To read an effective placement based on your targeting, simply put effective_ before the placement fields. For example:

curl -G \
-d "fields=targeting{effective_publisher_platforms,effective_facebook_positions,effective_device_platforms,effective_audience_network_positions,effective_instagram_positions}" \
-d "access_token=<access_token>" \
https://graph.facebook.com/<VERSION>/<AD_SET_ID>

To see why some placements got filtered out, in the recommendation field, get a filtering message:

curl -G \
-d "fields=recommendations" \
-d "access_token=<access_token>" \
https://graph.facebook.com/<VERSION>/23842573364570019

Facebook Connections

Target people who connected or did not connect with your brand.

Name: Type Description

app_install_state: String

Only for app-related objectives: mobile_app_*, canvas_app_*. You must use with the ad set's promoted_object. You can apply to both link and video app ads. Options:

  • installed: target people with promoted object/app installed.
  • not_installed: target people without promoted object/app installed

  • none: same as not specifying.

For example, 'app_install_state': 'not_installed'

connections: array of 'id' to value


[{'id':123}, {'id':456}, 789]

Array of Facebook IDs. Target fans of your Page, people who RSVP’d to your Event, people who logged into your app with Facebook Login, or authorized your Canvas app. To set this, you must be an admin of the page or event, or developer of the app you're advertising. You can't target on past events.

excluded_connections: array of 'id' to value. Limited to 100 values.


[{'id':123}, {'id':456}, 789]

Array of Facebook IDs. Target people who are not fans of your page, have not authorized your Canvas App or have not logged into your mobile app with Facebook Login. You can also target people who did not RSVP to a future event. If you have global page and you want to exclude page fans, you can only target people who are not fans of this global page, instead of people who are not fans of your local page. To set this, you need to be an admin of the Page or event, or developer of the app being advertised. For a 'Page Likes' campaign, you must exclude your page from targeting.

friends_of_connections: array of 'id's plus values, values or both


[{'id':123}, {'id':456}, 789]

Array of Facebook Object IDs. Target friends of people connected to your object. Connections are fans of your Page and people who interacted with your app. To set this, you must be to be an admin of the Page or a developer of the app being advertised. Limit is 100 IDs.

Education and Work

Use Targeting Search API for all options.

Name: Type Description

education_schools: array

Schools/colleges/institutions, such as [{id: 105930651606, 'name': 'Harvard University'}, {id: 105930651607}, 105930651608] Limit: 200 education schools.

education_statuses: array

Array of integers to target based on education level.

1: HIGH_SCHOOL

2: UNDERGRAD

3: ALUM

4: HIGH_SCHOOL_GRAD

5: SOME_COLLEGE

6: ASSOCIATE_DEGREE

7: IN_GRAD_SCHOOL

8: SOME_GRAD_SCHOOL

9: MASTER_DEGREE

10: PROFESSIONAL_DEGREE

11: DOCTORATE_DEGREE

12: UNSPECIFIED

13: SOME_HIGH_SCHOOL

college_years: array

Array of integers. College graduation. Earliest year: 1980

education_majors: array

Majors such as [{'id': 123, 'name': 'Computer Science'}, {'id': 456}, 789] Limit: 200

work_employers: array

Company, organization, or workplace such as [{'id':'50431654','name':'Microsoft'}, {'id':50431655}, 50431656] Limit: 200

work_positions: array

Self-declared work: [{'id':105763692790962, 'name':'Contractor'}, {'id':105763692790963}, 105763692790964] Limit: 200

Custom Audiences

Create a custom audience and add users. You can use the audience in targeting, either for inclusion or exclusion. Include up to 500 custom audiences in custom_audiences and 500 custom audiences in excluded_custom_audiences.

excluded_custom_audiences in targeting_specs is different than excluded_custom_audiences in APP_COMBINATION Custom Audience.

Name: Type Description

custom_audiences: array

Array of audience IDs or audience objects. 'id' field only: [123, 456] or [{'id': 123}, {'id': 456}]

excluded_custom_audiences: array

Array of audience IDs or audience objects. 'id' field only: [123, 456] or [{'id': 123}, {'id': 456}]

targeting:{
     "geo_locations":{
       "countries":["US"],
     },
     "age_min":25,
     "age_max":40,
     "custom_audiences":[{"id":6004192254512}]}
     "excluded_custom_audiences":
       [{"id":6004192252847}],
 }

Locales

Provide granular targeting on locale:

Name: Type Description

locales: array

Locales, see Targeting Search, Locales. Indices in a sub-array 'locales'. Target people with language other than common language for a location. Provide an ID for the language, such as 5 for German. Limit: 50. See mapping of virtual 'locales' to language sets at Targeting Search, Locale with type=adlocale.

Custom Broad Category Targeting

Use Broad Categories for custom targeting created or permissioned specifically for your account. To include the cooking category and small business owner category:

use FacebookAds\Object\AdSet;
use FacebookAds\Object\Fields\AdSetFields;
use FacebookAds\Object\Values\AdSetBillingEventValues;
use FacebookAds\Object\Values\AdSetOptimizationGoalValues;
use FacebookAds\Object\Fields\TargetingFields;
use FacebookAds\Object\Targeting;

$adset = new AdSet(null, 'act_<AD_ACCOUNT_ID>');
$adset->setData(array(
  AdSetFields::NAME => 'My AdSet',
  AdSetFields::OPTIMIZATION_GOAL => AdSetOptimizationGoalValues::REACH,
  AdSetFields::BILLING_EVENT => AdSetBillingEventValues::IMPRESSIONS,
  AdSetFields::BID_AMOUNT => 2,
  AdSetFields::DAILY_BUDGET => 1000,
  AdSetFields::CAMPAIGN_ID => <CAMPAIGN_ID>,
  AdSetFields::TARGETING => (new Targeting())->setData(array(
    TargetingFields::GEO_LOCATIONS => array(
      'countries' => array(
        'US',
      ),
    ),
    TargetingFields::USER_ADCLUSTERS => array(
      array(
        'id' => 6002714885172,
        'name' => 'Cooking',
      ),
      array(
        'id' => 6002714898572,
        'name' => 'Small Business Owners',
      ),
    ),
  )),
));
$adset->create(array(
  AdSet::STATUS_PARAM_NAME => AdSet::STATUS_ACTIVE,
));
from facebookads.adobjects.adset import AdSet

adset = AdSet(parent_id='act_<AD_ACCOUNT_ID>')
adset.update({
    AdSet.Field.name: 'My AdSet',
    AdSet.Field.optimization_goal: AdSet.OptimizationGoal.reach,
    AdSet.Field.billing_event: AdSet.BillingEvent.impressions,
    AdSet.Field.bid_amount: 150,
    AdSet.Field.daily_budget: 2000,
    AdSet.Field.campaign_id: <CAMPAIGN_ID>,
    AdSet.Field.targeting: {
        'geo_locations': {
            'countries': ['US'],
        },
        'user_adclusters': [
            {
                'id': 6002714885172,
                'name': 'Cooking',
            },
            {
                'id': 6002714898572,
                'name': 'Small Business Owners',
            },
        ],
    },
})
adset.remote_create(params={
    'status': AdSet.Status.active,
})
AdSet adSet = new AdAccount(act_<AD_ACCOUNT_ID>, context).createAdSet()
  .setName("My AdSet")
  .setOptimizationGoal(AdSet.EnumOptimizationGoal.VALUE_REACH)
  .setBillingEvent(AdSet.EnumBillingEvent.VALUE_IMPRESSIONS)
  .setBidAmount(2L)
  .setDailyBudget(1000L)
  .setCampaignId(<CAMPAIGN_ID>)
  .setTargeting(
    new Targeting()
      .setFieldGeoLocations(
        new TargetingGeoLocation()
          .setFieldCountries(Arrays.asList("US"))
      )
      .setFieldUserAdclusters(Arrays.asList(
        new IDName()
          .setFieldId("6002714885172")
          .setFieldName("Cooking")
      , 
        new IDName()
          .setFieldId("6002714898572")
          .setFieldName("Small Business Owners")
      ))
  )
  .setStatus(AdSet.EnumStatus.VALUE_ACTIVE)
  .execute();
String ad_set_id = adSet.getId();
curl \
  -F 'name=My AdSet' \
  -F 'optimization_goal=REACH' \
  -F 'billing_event=IMPRESSIONS' \
  -F 'bid_amount=2' \
  -F 'daily_budget=1000' \
  -F 'campaign_id=<CAMPAIGN_ID>' \
  -F 'targeting={ 
    "geo_locations": {"countries":["US"]}, 
    "user_adclusters": [ 
      {"id":6002714885172,"name":"Cooking"}, 
      {"id":6002714898572,"name":"Small Business Owners"} 
    ] 
  }' \
  -F 'status=ACTIVE' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/adsets

To exclude the cooking category and small business owner category:

use FacebookAds\Object\AdSet;
use FacebookAds\Object\Fields\AdSetFields;
use FacebookAds\Object\Values\AdSetBillingEventValues;
use FacebookAds\Object\Values\AdSetOptimizationGoalValues;
use FacebookAds\Object\Fields\TargetingFields;
use FacebookAds\Object\Targeting;

$adset = new AdSet(null, 'act_<AD_ACCOUNT_ID>');
$adset->setData(array(
  AdSetFields::NAME => 'My AdSet',
  AdSetFields::OPTIMIZATION_GOAL => AdSetOptimizationGoalValues::REACH,
  AdSetFields::BILLING_EVENT => AdSetBillingEventValues::IMPRESSIONS,
  AdSetFields::BID_AMOUNT => 2,
  AdSetFields::DAILY_BUDGET => 1000,
  AdSetFields::CAMPAIGN_ID => <CAMPAIGN_ID>,
  AdSetFields::TARGETING => (new Targeting())->setData(array(
    TargetingFields::GEO_LOCATIONS => array(
      'countries' => array(
        'US',
      ),
    ),
    TargetingFields::EXCLUSIONS => array(
      TargetingFields::USER_ADCLUSTERS => array(
        array(
         'id' => 6002714885172,
         'name' => 'Cooking',
        ),
        array(
         'id' => 6002714898572,
         'name' => 'Small Business Owners',
        ),
      ),
    ),
  )),
));
$adset->create(array(
  AdSet::STATUS_PARAM_NAME => AdSet::STATUS_ACTIVE,
));
from facebookads.adobjects.adset import AdSet

adset = AdSet(parent_id='act_<AD_ACCOUNT_ID>')
adset.update({
    AdSet.Field.name: 'My AdSet',
    AdSet.Field.optimization_goal: AdSet.OptimizationGoal.reach,
    AdSet.Field.billing_event: AdSet.BillingEvent.impressions,
    AdSet.Field.bid_amount: 150,
    AdSet.Field.daily_budget: 2000,
    AdSet.Field.campaign_id: <CAMPAIGN_ID>,
    AdSet.Field.targeting: {
        'geo_locations': {
            'countries': ['US'],
        },
        'exclusions': {
            'user_adclusters': [
                {
                    'id': 6002714885172,
                    'name': 'Cooking',
                },
                {
                    'id': 6002714898572,
                    'name': 'Small Business Owners',
                },
            ],
        },
    },
})
adset.remote_create(params={
    'status': AdSet.Status.active,
})
AdSet adSet = new AdAccount(act_<AD_ACCOUNT_ID>, context).createAdSet()
  .setName("My AdSet")
  .setOptimizationGoal(AdSet.EnumOptimizationGoal.VALUE_REACH)
  .setBillingEvent(AdSet.EnumBillingEvent.VALUE_IMPRESSIONS)
  .setBidAmount(2L)
  .setDailyBudget(1000L)
  .setCampaignId(<CAMPAIGN_ID>)
  .setTargeting(
    new Targeting()
      .setFieldExclusions(
        new FlexibleTargeting()
          .setFieldUserAdclusters(Arrays.asList(
            new IDName()
              .setFieldId("6002714885172")
              .setFieldName("Cooking")
          , 
            new IDName()
              .setFieldId("6002714898572")
              .setFieldName("Small Business Owners")
          ))
      )
      .setFieldGeoLocations(
        new TargetingGeoLocation()
          .setFieldCountries(Arrays.asList("US"))
      )
  )
  .setStatus(AdSet.EnumStatus.VALUE_ACTIVE)
  .execute();
String ad_set_id = adSet.getId();
curl \
  -F 'name=My AdSet' \
  -F 'optimization_goal=REACH' \
  -F 'billing_event=IMPRESSIONS' \
  -F 'bid_amount=2' \
  -F 'daily_budget=1000' \
  -F 'campaign_id=<CAMPAIGN_ID>' \
  -F 'targeting={ 
    "exclusions": { 
      "user_adclusters": [ 
        {"id":6002714885172,"name":"Cooking"}, 
        {"id":6002714898572,"name":"Small Business Owners"} 
      ] 
    }, 
    "geo_locations": {"countries":["US"]} 
  }' \
  -F 'status=ACTIVE' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/adsets

To target based on BCT plus location and demographics:

use FacebookAds\Object\AdSet;
use FacebookAds\Object\Fields\AdSetFields;
use FacebookAds\Object\Values\AdSetBillingEventValues;
use FacebookAds\Object\Values\AdSetOptimizationGoalValues;
use FacebookAds\Object\Fields\TargetingFields;
use FacebookAds\Object\Targeting;

$adset = new AdSet(null, 'act_<AD_ACCOUNT_ID>');
$adset->setData(array(
  AdSetFields::NAME => 'My AdSet',
  AdSetFields::OPTIMIZATION_GOAL => AdSetOptimizationGoalValues::REACH,
  AdSetFields::BILLING_EVENT => AdSetBillingEventValues::IMPRESSIONS,
  AdSetFields::BID_AMOUNT => 2,
  AdSetFields::DAILY_BUDGET => 1000,
  AdSetFields::CAMPAIGN_ID => <CAMPAIGN_ID>,
  AdSetFields::TARGETING => (new Targeting())->setData(array(
    TargetingFields::GEO_LOCATIONS => array(
      'countries' => array(
        'US',
      ),
    ),
    TargetingFields::RELATIONSHIP_STATUSES => array (2),
    TargetingFields::USER_ADCLUSTERS => array(
      array(
        'id' => 6002714886772,
        'name' => 'Food & Dining',
      ),
    ),
  )),
));
$adset->create(array(
  AdSet::STATUS_PARAM_NAME => AdSet::STATUS_ACTIVE,
));
from facebookads.adobjects.adset import AdSet

adset = AdSet(parent_id='act_<AD_ACCOUNT_ID>')
adset.update({
    AdSet.Field.name: 'My AdSet',
    AdSet.Field.optimization_goal: AdSet.OptimizationGoal.reach,
    AdSet.Field.billing_event: AdSet.BillingEvent.impressions,
    AdSet.Field.bid_amount: 150,
    AdSet.Field.daily_budget: 2000,
    AdSet.Field.campaign_id: <CAMPAIGN_ID>,
    AdSet.Field.targeting: {
        'geo_locations': {
            'countries': ['US'],
        },
        'relationship_statuses': [2],
        'user_adclusters': [
            {
                'id': 6002714886772,
                'name': 'Food & Dining',
            },
        ],
    },
})
adset.remote_create(params={
    'status': AdSet.Status.active,
})
AdSet adSet = new AdAccount(act_<AD_ACCOUNT_ID>, context).createAdSet()
  .setName("My AdSet")
  .setOptimizationGoal(AdSet.EnumOptimizationGoal.VALUE_REACH)
  .setBillingEvent(AdSet.EnumBillingEvent.VALUE_IMPRESSIONS)
  .setBidAmount(2L)
  .setDailyBudget(1000L)
  .setCampaignId(<CAMPAIGN_ID>)
  .setTargeting(
    new Targeting()
      .setFieldGeoLocations(
        new TargetingGeoLocation()
          .setFieldCountries(Arrays.asList("US"))
      )
      .setFieldRelationshipStatuses(Arrays.asList(2L))
      .setFieldUserAdclusters(Arrays.asList(
        new IDName()
          .setFieldId("6002714886772")
          .setFieldName("Food & Dining")
      ))
  )
  .setStatus(AdSet.EnumStatus.VALUE_ACTIVE)
  .execute();
String ad_set_id = adSet.getId();
curl \
  -F 'name=My AdSet' \
  -F 'optimization_goal=REACH' \
  -F 'billing_event=IMPRESSIONS' \
  -F 'bid_amount=2' \
  -F 'daily_budget=1000' \
  -F 'campaign_id=<CAMPAIGN_ID>' \
  -F 'targeting={ 
    "geo_locations": {"countries":["US"]}, 
    "relationship_statuses": [2], 
    "user_adclusters": [{"id":6002714886772,"name":"Food & Dining"}] 
  }' \
  -F 'status=ACTIVE' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/adsets

You have options:

Name: Type Description

user_adclusters: array

Array of ID-name pairs for BCT clusters. See below for information on retrieving BCT's. Limit: 50 ID-name pairs.

To query this targeting for Ad account, make an HTTP GET:

https://graph.facebook.com/<API_VERSION>/act_<AD_ACCOUNT_ID>/broadtargetingcategories

The response is an array of JSON key-value pairs:

Name: Type Description

id: long

ID of broad category is used for ad targeting spec

name: string

Name of broad category

parent_category: string

Parent category of broad category

size: int

Audience size of broad category

type: int

6=BCT

type_name: string

BCT

Targeting Expansion

Enable Facebook to expand interests when this increases results at a lower cost per result. Targeting expansion does not create lookalike audiences. Expanding interests does not change your targeting specifications for location, demographic targeting, such as age or gender, or exclusions.

Note that campaigns with supported objectives are not enabled by default.

  • To opt in, set the targeting_optimization parameter to expansion_all.

  • To opt out, set targeting_optimization parameter to none.

If you use the targeting_optimization parameter for an unsupported objective, you will see an error. The supported objectives are Web Conversion, App Installs, Lead Generation, Link Click and Post Engagement. For example:

curl \
-F "name=relaxation null test" \
-F "promoted_object={'application_id': '<APP_ID>', 'object_store_url': 'https://itunes.apple.com/app/id1111111'}" \
-F "is_autobid=true" \
-F "daily_budget=100" \
-F "billing_event=IMPRESSIONS" \
-F "campaign_id=<CAMPAIGN_ID>" \
-F "access_token=XXX" \
-F "targeting={'geo_locations': {'countries': ['US', 'GB']}, 'user_os': ['iOS'], 'user_device': ['iPad', 'iPhone', 'iPod'], 'targeting_optimization': 'expansion_all'}" \
https://graph.facebook.com/<VERSION>/act_XXX/adsets

Flexible Targeting

Combine or exclude different targeting options to reach a specific set of users in the flexible_spec with AND and OR statements. Facebook evaluates targeting in flexible_spec via AND with all segments outside the spec such as age, gender, geo locations. We also evaluate each top level array element in flexible_spec with AND; we evaluate second-level array elements with OR.

Targeting segments such as interests/behaviors specified inside flexible_spec are not available for use outside of flexible_spec.

To target people who live in the U.S, aged between 18-43, who are not single or married and have not recently moved and are travelers or like soccer or movies and are newlyweds or like music:

use FacebookAds\Object\AdSet;
use FacebookAds\Object\Fields\AdSetFields;
use FacebookAds\Object\Values\AdSetBillingEventValues;
use FacebookAds\Object\Values\AdSetOptimizationGoalValues;
use FacebookAds\Object\Fields\TargetingFields;
use FacebookAds\Object\Targeting;

$adset = new AdSet(null, 'act_<AD_ACCOUNT_ID>');
$adset->setData(array(
  AdSetFields::NAME => 'My AdSet',
  AdSetFields::OPTIMIZATION_GOAL => AdSetOptimizationGoalValues::REACH,
  AdSetFields::BILLING_EVENT => AdSetBillingEventValues::IMPRESSIONS,
  AdSetFields::BID_AMOUNT => 150,
  AdSetFields::DAILY_BUDGET => 2000,
  AdSetFields::CAMPAIGN_ID => <CAMPAIGN_ID>,
  AdSetFields::TARGETING => (new Targeting())->setData(array(
    TargetingFields::GEO_LOCATIONS => array(
      'countries' => array(
        'US',
      ),
    ),
    TargetingFields::AGE_MIN => 18,
    TargetingFields::AGE_MAX => 43,
    TargetingFields::FLEXIBLE_SPEC => array(
      array(
        TargetingFields::BEHAVIORS => array(
          array(
            'id' => 6002714895372,
            'name' => 'All travelers',
          ),
        ),
        TargetingFields::INTERESTS => array(
          array(
            'id' => 6003107902433,
            'name' => 'Association football (Soccer)',
          ),
          array(
            'id' => 6003139266461,
            'name' => 'Movies',
          ),
        ),
      ),
      array(
        TargetingFields::INTERESTS => array(
          array(
            'id' => 6003020834693,
            'name' => 'Music',
          ),
        ),
        TargetingFields::LIFE_EVENTS => array(
          array(
            'id' => 6002714398172,
            'name' => 'Newlywed (1 year)',
          ),
        ),
      ),
    ),
    TargetingFields::EXCLUSIONS => array(
      TargetingFields::RELATIONSHIP_STATUSES => array(1, 3),
      TargetingFields::LIFE_EVENTS => array(
        array(
          'id' => 6003054185372,
          'name' => 'Recently moved',
        ),
      ),
    ),
  )),
));
$adset->create(array(
  AdSet::STATUS_PARAM_NAME => AdSet::STATUS_ACTIVE,
));
from facebookads.adobjects.adset import AdSet

adset = AdSet(parent_id='act_<AD_ACCOUNT_ID>')
adset.update({
    AdSet.Field.name: 'My AdSet',
    AdSet.Field.optimization_goal: AdSet.OptimizationGoal.reach,
    AdSet.Field.billing_event: AdSet.BillingEvent.impressions,
    AdSet.Field.bid_amount: 150,
    AdSet.Field.daily_budget: 2000,
    AdSet.Field.campaign_id: <CAMPAIGN_ID>,
    AdSet.Field.targeting: {
        'geo_locations': {
            'countries': ['US'],
        },
        'age_min': 18,
        'age_max': 43,
        'flexible_spec': [
            {
                'behaviors': [
                    {
                        'id': 6002714895372,
                        'name': 'All travelers',
                    },
                ],
                'interests': [
                    {
                        'id': 6003107902433,
                        'name': 'Association football (Soccer)',
                    },
                    {
                        'id': 6003139266461,
                        'name': 'Movies',
                    },
                ],
            },
            {
                'interests': [
                    {
                        'id': 6003020834693,
                        'name': 'Music',
                    },
                ],
                'life_events': [
                    {
                        'id': 6002714398172,
                        'name': 'Newlywed (1 year)',
                    },
                ],
            },
        ],
        'exclusions': {
            'relationship_statuses': [1, 3],
            'life_events': [
                {
                    'id': 6003054185372,
                    'name': 'Recently moved',
                },
            ],
        },
    },
})
adset.remote_create(params={
    'status': AdSet.Status.active,
})
AdSet adSet = new AdAccount(act_<AD_ACCOUNT_ID>, context).createAdSet()
  .setName("My AdSet")
  .setOptimizationGoal(AdSet.EnumOptimizationGoal.VALUE_REACH)
  .setBillingEvent(AdSet.EnumBillingEvent.VALUE_IMPRESSIONS)
  .setBidAmount(150L)
  .setDailyBudget(2000L)
  .setCampaignId(<CAMPAIGN_ID>)
  .setTargeting(
    new Targeting()
      .setFieldAgeMax(43L)
      .setFieldAgeMin(18L)
      .setFieldExclusions(
        new FlexibleTargeting()
          .setFieldLifeEvents(Arrays.asList(
            new IDName()
              .setFieldId("6003054185372")
              .setFieldName("Recently moved")
          ))
          .setFieldRelationshipStatuses(Arrays.asList(1L, 3L))
      )
      .setFieldFlexibleSpec(Arrays.asList(
        new FlexibleTargeting()
          .setFieldBehaviors(Arrays.asList(
            new IDName()
              .setFieldId("6002714895372")
              .setFieldName("All travelers")
          ))
          .setFieldInterests(Arrays.asList(
            new IDName()
              .setFieldId("6003107902433")
              .setFieldName("Association football (Soccer)")
          , 
            new IDName()
              .setFieldId("6003139266461")
              .setFieldName("Movies")
          ))
      , 
        new FlexibleTargeting()
          .setFieldInterests(Arrays.asList(
            new IDName()
              .setFieldId("6003020834693")
              .setFieldName("Music")
          ))
          .setFieldLifeEvents(Arrays.asList(
            new IDName()
              .setFieldId("6002714398172")
              .setFieldName("Newlywed (1 year)")
          ))
      ))
      .setFieldGeoLocations(
        new TargetingGeoLocation()
          .setFieldCountries(Arrays.asList("US"))
      )
  )
  .setStatus(AdSet.EnumStatus.VALUE_ACTIVE)
  .execute();
String ad_set_id = adSet.getId();
curl \
  -F 'name=My AdSet' \
  -F 'optimization_goal=REACH' \
  -F 'billing_event=IMPRESSIONS' \
  -F 'bid_amount=150' \
  -F 'daily_budget=2000' \
  -F 'campaign_id=<CAMPAIGN_ID>' \
  -F 'targeting={ 
    "age_max": 43, 
    "age_min": 18, 
    "exclusions": { 
      "relationship_statuses": [1,3], 
      "life_events": [{"id":6003054185372,"name":"Recently moved"}] 
    }, 
    "flexible_spec": [ 
      { 
        "behaviors": [{"id":6002714895372,"name":"All travelers"}], 
        "interests": [ 
          {"id":6003107902433,"name":"Association football (Soccer)"}, 
          {"id":6003139266461,"name":"Movies"} 
        ] 
      }, 
      { 
        "interests": [{"id":6003020834693,"name":"Music"}], 
        "life_events": [{"id":6002714398172,"name":"Newlywed (1 year)"}] 
      } 
    ], 
    "geo_locations": {"countries":["US"]} 
  }' \
  -F 'status=ACTIVE' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/adsets

With this flexible spec, the resulting audience is:

(segment 1 or segment2 or segment3) and (segment 4 or segment 5) and segment 6

flexible_spec=
[
  {
    'segment_type':[segment1, segment2], 
    'segment_type':[segment3]
  },
  { 
    'segment_type':[segment4, segment5]
  },
  { 
    'segment_type':[segment6]
  }
]

Specify flexible_spec and exclusions as follows:

Name: Type Description

flexible_spec: JSON Object

Array of arrays. Each contains a targeting segment in appropriate format, such as interests, behaviors, partner categories and demographics. The top level array has a limit of 25 and secondary level array has a limit of 1,000.

exclusions: JSON Object

Contains a targeting segment in its appropriate format such as interests, behaviors, partner categories and demographics.

For example, create an audience who lives in the U.S, aged 20-24, who are not single or married and have not recently moved and are travelers or like soccer or movies and are newlyweds or like music:

targeting=
{'geo_locations':{ 
  'countries': ['US'], 
}, 
'age_min':20, 
'age_max':24, 
'flexible_spec': [ 
  {
    'behaviors':[{'id':6002714895372,'name':'All travelers'},], 
    'interests':[ 
      {'id':6003107902433,'name':'Association football (Soccer)'}, 
      {'id':6003139266461, 'name': 'Movies'},],  
  }, 
  {
    'life_events':[{'id': 6002714398172, 'name': 'Newlywed (1 year)'}],
    'interests':[{'id':6003020834693,'name':'Music'},], 
  },   
], 
'exclusions': { 
  'relationship_statuses':[1,3], 
  'life_events':[{'id':6003054185372,'name':'Recently moved'},], 
}, 
} 

The targeting spec for this ad set:

{
  "targeting": { 
    "age_min": 20, 
    "age_max": 24,
    "exclusions": {
      "life_events": [
        {
          "id": "6003054185372", 
          "name": "Recently moved"
        }
      ], 
      "relationship_statuses": [
        1, 
        3
      ]
    }, 
    "flexible_spec": [
      {
        "interests": [
          {
            "id": "6003107902433", 
            "name": "Association football (Soccer)"
          }, 
          {
            "id": "6003139266461", 
            "name": "Movies"
          }
        ], 
        "behaviors": [
          {
            "id": "6002714895372", 
            "name": "All travelers"
          }
        ]
      }, 
      {
        "interests": [
          {
            "id": "6003020834693", 
            "name": "Music"
          }
        ],       
        "life_events": [
          {
            "id": "6002714398172", 
            "name": "Newlywed (1 year)"
          }
        ]
      }
    ], 
    "geo_locations": {
      "countries": [
        "US"
      ]
    }
  }, 
  "id": "6015417075447"
}

Use these fields in flexible targeting:

  • connections
  • friends_of_connections
  • custom_audiences
  • interests
  • user_adclusters
  • behaviors
  • college_years
  • education_majors
  • education_schools
  • education_statuses
  • family_statuses
  • generation
  • home_type
  • home_ownership
  • home_value
  • household_composition
  • interested_in
  • income
  • industries
  • life_events
  • moms
  • net_worth
  • office_type
  • politics
  • relationship_statuses
  • work_positions
  • work_employers

Partner Categories

Exclusion targeting is not supported for partner categories.

As you do with Facebook targeting, you find partner categories with Targeting Search API. You can also find them under several targeting classes and they appear with Facebook categories. To view only Partner Categories, see Targeting Search, Partner Categories, By Account Id.

To target ads with partner categories, provide type from search results in your targeting_spec:

targeting={
  'behaviors':[
    {id: 6006142989425, 'name': 'Full-size SUV'},
  ],
  'household_composition':[
    {id: 6009218313499, 'name': 'Children in home'},
  ],
  'user_adclusters':[
    {id: 6006371326532, 'name': 'Recent homebuyer'},
  ],
}

If you get categories with class=uncategorized, type is user_adclusters. To target people who are recent home buyers and in household size bigger than 3:

use FacebookAds\Object\AdSet;
use FacebookAds\Object\Fields\AdSetFields;
use FacebookAds\Object\Values\AdSetBillingEventValues;
use FacebookAds\Object\Values\AdSetOptimizationGoalValues;
use FacebookAds\Object\Fields\TargetingFields;
use FacebookAds\Object\Targeting;

$adset = new AdSet(null, 'act_<AD_ACCOUNT_ID>');
$adset->setData(array(
  AdSetFields::NAME => 'My AdSet',
  AdSetFields::OPTIMIZATION_GOAL => AdSetOptimizationGoalValues::REACH,
  AdSetFields::BILLING_EVENT => AdSetBillingEventValues::IMPRESSIONS,
  AdSetFields::BID_AMOUNT => 2,
  AdSetFields::DAILY_BUDGET => 1000,
  AdSetFields::CAMPAIGN_ID => <CAMPAIGN_ID>,
  AdSetFields::TARGETING => (new Targeting())->setData(array(
    TargetingFields::GEO_LOCATIONS => array(
      'countries' => array(
        'US',
      ),
    ),
    TargetingFields::FLEXIBLE_SPEC => array(
      array(
        TargetingFields::USER_ADCLUSTERS => array(
          array(
            'id' => 6006371340132,
            'name' => 'Demographic > Household Size > 3',
          ),
        ),
      ),
      array(
        TargetingFields::USER_ADCLUSTERS => array(
          array(
            'id' => 6006371326532,
            'name' => 'Demographic > Home > Home Owner > Recent Buyer',
          ),
        ),
      ),
    ),
  )),
));
$adset->create(array(
  AdSet::STATUS_PARAM_NAME => AdSet::STATUS_ACTIVE,
));
from facebookads.adobjects.adset import AdSet

adset = AdSet(parent_id='act_<AD_ACCOUNT_ID>')
adset.update({
    AdSet.Field.name: 'My AdSet',
    AdSet.Field.optimization_goal: AdSet.OptimizationGoal.reach,
    AdSet.Field.billing_event: AdSet.BillingEvent.impressions,
    AdSet.Field.bid_amount: 150,
    AdSet.Field.daily_budget: 2000,
    AdSet.Field.campaign_id: <CAMPAIGN_ID>,
    AdSet.Field.targeting: {
        'geo_locations': {
            'countries': ['US'],
        },
        'flexible_spec': [
            {
                'user_adclusters': [
                    {
                        'id': 6006371340132,
                        'name': 'Demographic > Household Size > 3',
                    },
                ],
            },
            {
                'user_adclusters': [
                    {
                        'id': 6006371326532,
                        'name':
                            'Demographic > Home > Home Owner > Recent Buyer',
                    },
                ],
            },
        ],
    },
})
adset.remote_create(params={
    'status': AdSet.Status.active,
})
AdSet adSet = new AdAccount(act_<AD_ACCOUNT_ID>, context).createAdSet()
  .setName("My AdSet")
  .setOptimizationGoal(AdSet.EnumOptimizationGoal.VALUE_REACH)
  .setBillingEvent(AdSet.EnumBillingEvent.VALUE_IMPRESSIONS)
  .setBidAmount(2L)
  .setDailyBudget(1000L)
  .setCampaignId(<CAMPAIGN_ID>)
  .setTargeting(
    new Targeting()
      .setFieldFlexibleSpec(Arrays.asList(
        new FlexibleTargeting()
          .setFieldUserAdclusters(Arrays.asList(
            new IDName()
              .setFieldId("6006371340132")
              .setFieldName("Demographic > Household Size > 3")
          ))
      , 
        new FlexibleTargeting()
          .setFieldUserAdclusters(Arrays.asList(
            new IDName()
              .setFieldId("6006371326532")
              .setFieldName("Demographic > Home > Home Owner > Recent Buyer")
          ))
      ))
      .setFieldGeoLocations(
        new TargetingGeoLocation()
          .setFieldCountries(Arrays.asList("US"))
      )
  )
  .setStatus(AdSet.EnumStatus.VALUE_ACTIVE)
  .execute();
String ad_set_id = adSet.getId();
curl \
  -F 'name=My AdSet' \
  -F 'optimization_goal=REACH' \
  -F 'billing_event=IMPRESSIONS' \
  -F 'bid_amount=2' \
  -F 'daily_budget=1000' \
  -F 'campaign_id=<CAMPAIGN_ID>' \
  -F 'targeting={ 
    "flexible_spec": [ 
      { 
        "user_adclusters": [{"id":6006371340132,"name":"Demographic > Household Size > 3"}] 
      }, 
      { 
        "user_adclusters": [ 
          { 
            "id": 6006371326532, 
            "name": "Demographic > Home > Home Owner > Recent Buyer" 
          } 
        ] 
      } 
    ], 
    "geo_locations": {"countries":["US"]} 
  }' \
  -F 'status=ACTIVE' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/adsets

Targeting BCT & Partner Categories:

use FacebookAds\Object\AdSet;
use FacebookAds\Object\Fields\AdSetFields;
use FacebookAds\Object\Values\AdSetBillingEventValues;
use FacebookAds\Object\Values\AdSetOptimizationGoalValues;
use FacebookAds\Object\Fields\TargetingFields;
use FacebookAds\Object\Targeting;

$adset = new AdSet(null, 'act_<AD_ACCOUNT_ID>');
$adset->setData(array(
  AdSetFields::NAME => 'My AdSet',
  AdSetFields::OPTIMIZATION_GOAL => AdSetOptimizationGoalValues::REACH,
  AdSetFields::BILLING_EVENT => AdSetBillingEventValues::IMPRESSIONS,
  AdSetFields::BID_AMOUNT => 2,
  AdSetFields::DAILY_BUDGET => 1000,
  AdSetFields::CAMPAIGN_ID => <CAMPAIGN_ID>,
  AdSetFields::TARGETING => (new Targeting())->setData(array(
    TargetingFields::GEO_LOCATIONS => array(
      'countries' => array(
        'US',
      ),
    ),
    TargetingFields::FLEXIBLE_SPEC => array(
      array(
        TargetingFields::USER_ADCLUSTERS => array(
          array(
           'id' => 6002714885172,
            'name' => 'Cooking',
          ),
        ),
      ),
      array(
        TargetingFields::USER_ADCLUSTERS => array(
          array(
            'id' => 6006371326532,
            'name' => 'Demographic > Home > Home Owner > Recent Buyer',
          ),
        ),
      ),
    ),
  )),
));
$adset->create(array(
  AdSet::STATUS_PARAM_NAME => AdSet::STATUS_ACTIVE,
));
from facebookads.adobjects.adset import AdSet

adset = AdSet(parent_id='act_<AD_ACCOUNT_ID>')
adset.update({
    AdSet.Field.name: 'My AdSet',
    AdSet.Field.optimization_goal: AdSet.OptimizationGoal.reach,
    AdSet.Field.billing_event: AdSet.BillingEvent.impressions,
    AdSet.Field.bid_amount: 150,
    AdSet.Field.daily_budget: 2000,
    AdSet.Field.campaign_id: <CAMPAIGN_ID>,
    AdSet.Field.targeting: {
        'geo_locations': {
            'countries': ['US'],
        },
        'flexible_spec': [
            {
                'user_adclusters': [
                    {
                        'id': 6002714885172,
                        'name': 'Cooking',
                    },
                ],
            },
            {
                'user_adclusters': [
                    {
                        'id': 6006371326532,
                        'name':
                            'Demographic > Home > Home Owner > Recent Buyer',
                    },
                ],
            },
        ],
    },
})
adset.remote_create(params={
    'status': AdSet.Status.active,
})
AdSet adSet = new AdAccount(act_<AD_ACCOUNT_ID>, context).createAdSet()
  .setName("My AdSet")
  .setOptimizationGoal(AdSet.EnumOptimizationGoal.VALUE_REACH)
  .setBillingEvent(AdSet.EnumBillingEvent.VALUE_IMPRESSIONS)
  .setBidAmount(2L)
  .setDailyBudget(1000L)
  .setCampaignId(<CAMPAIGN_ID>)
  .setTargeting(
    new Targeting()
      .setFieldFlexibleSpec(Arrays.asList(
        new FlexibleTargeting()
          .setFieldUserAdclusters(Arrays.asList(
            new IDName()
              .setFieldId("6002714885172")
              .setFieldName("Cooking")
          ))
      , 
        new FlexibleTargeting()
          .setFieldUserAdclusters(Arrays.asList(
            new IDName()
              .setFieldId("6006371326532")
              .setFieldName("Demographic > Home > Home Owner > Recent Buyer")
          ))
      ))
      .setFieldGeoLocations(
        new TargetingGeoLocation()
          .setFieldCountries(Arrays.asList("US"))
      )
  )
  .setStatus(AdSet.EnumStatus.VALUE_ACTIVE)
  .execute();
String ad_set_id = adSet.getId();
curl \
  -F 'name=My AdSet' \
  -F 'optimization_goal=REACH' \
  -F 'billing_event=IMPRESSIONS' \
  -F 'bid_amount=2' \
  -F 'daily_budget=1000' \
  -F 'campaign_id=<CAMPAIGN_ID>' \
  -F 'targeting={ 
    "flexible_spec": [ 
      {"user_adclusters":[{"id":6002714885172,"name":"Cooking"}]}, 
      { 
        "user_adclusters": [ 
          { 
            "id": 6006371326532, 
            "name": "Demographic > Home > Home Owner > Recent Buyer" 
          } 
        ] 
      } 
    ], 
    "geo_locations": {"countries":["US"]} 
  }' \
  -F 'status=ACTIVE' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/adsets

Targeting Custom Audience & Partner Categories:

To target people who bought games from you directly or are in the "Gamers" partner category.

use FacebookAds\Object\AdSet;
use FacebookAds\Object\Fields\AdSetFields;
use FacebookAds\Object\Values\AdSetBillingEventValues;
use FacebookAds\Object\Values\AdSetOptimizationGoalValues;
use FacebookAds\Object\Fields\TargetingFields;
use FacebookAds\Object\Targeting;

$adset = new AdSet(null, 'act_<AD_ACCOUNT_ID>');
$adset->setData(array(
  AdSetFields::NAME => 'My AdSet',
  AdSetFields::OPTIMIZATION_GOAL => AdSetOptimizationGoalValues::REACH,
  AdSetFields::BILLING_EVENT => AdSetBillingEventValues::IMPRESSIONS,
  AdSetFields::BID_AMOUNT => 2,
  AdSetFields::DAILY_BUDGET => 1000,
  AdSetFields::CAMPAIGN_ID => <CAMPAIGN_ID>,
  AdSetFields::TARGETING => (new Targeting())->setData(array(
    TargetingFields::GEO_LOCATIONS => array(
      'countries' => array('US'),
    ),
    TargetingFields::CUSTOM_AUDIENCES => array(
      array(
        'id' => <AUDIENCE_ID>,
        'name' => <AUDIENCE_NAME>,
      ),
    ),
  )),
));
$adset->create(array(
  AdSet::STATUS_PARAM_NAME => AdSet::STATUS_ACTIVE,
));
from facebookads.adobjects.adset import AdSet

adset = AdSet(parent_id='act_<AD_ACCOUNT_ID>')
adset.update({
    AdSet.Field.name: 'My AdSet',
    AdSet.Field.optimization_goal: AdSet.OptimizationGoal.reach,
    AdSet.Field.billing_event: AdSet.BillingEvent.impressions,
    AdSet.Field.bid_amount: 150,
    AdSet.Field.daily_budget: 2000,
    AdSet.Field.campaign_id: <CAMPAIGN_ID>,
    AdSet.Field.targeting: {
        'geo_locations': {
            'countries': ['US'],
        },
        'custom_audiences': [
            {
                'id': <CUSTOM_AUDIENCE_ID>,
                'name': <AUDIENCE_NAME>,
            },
        ],
    },
})
adset.remote_create(params={
    'status': AdSet.Status.active,
})
AdSet adSet = new AdAccount(act_<AD_ACCOUNT_ID>, context).createAdSet()
  .setName("My AdSet")
  .setOptimizationGoal(AdSet.EnumOptimizationGoal.VALUE_REACH)
  .setBillingEvent(AdSet.EnumBillingEvent.VALUE_IMPRESSIONS)
  .setBidAmount(2L)
  .setDailyBudget(1000L)
  .setCampaignId(<CAMPAIGN_ID>)
  .setTargeting(
    new Targeting()
      .setFieldCustomAudiences(Arrays.asList(
        new IDName()
          .setFieldId(<AUDIENCE_ID>)
          .setFieldName(<AUDIENCE_NAME>)
      ))
      .setFieldGeoLocations(
        new TargetingGeoLocation()
          .setFieldCountries(Arrays.asList("US"))
      )
  )
  .setStatus(AdSet.EnumStatus.VALUE_ACTIVE)
  .execute();
String ad_set_id = adSet.getId();
curl \
  -F 'name=My AdSet' \
  -F 'optimization_goal=REACH' \
  -F 'billing_event=IMPRESSIONS' \
  -F 'bid_amount=2' \
  -F 'daily_budget=1000' \
  -F 'campaign_id=<CAMPAIGN_ID>' \
  -F 'targeting={ 
    "custom_audiences": [{"id":"<AUDIENCE_ID>","name":"<AUDIENCE_NAME>"}], 
    "geo_locations": {"countries":["US"]} 
  }' \
  -F 'status=ACTIVE' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/adsets

Limits

Limitations on ad targeting:

Area Limit

Minimum age of a user to target ad

13 years old

Maximum age of a user to target ad?

65 years old

Languages targeted per ad

50

Interests targeted

400

Colleges targeted

200

Workplaces targeted

200

Majors targeted

200

Cities targeted

250

Connections targeted

50

Latest graduation year targeted

1980

Targeting by zip code

50,000. Past limit was 2500 zip codes. If you use more than this amount we create an object which represents a set of zip code. You can view this object in the ad set's targeting_spec.

Resources