Custom Audiences

The two ways to define who gets your ad are targeting or audiences. With targeting, provide attributes such as demographics or location and we deliver ads to people on Facebook who meet those attributes. See Targeting.

With audiences, you build a group of people who receive your ad. You can create audiences based on customer data, conversion data such as activity in your app or website, and so on.

Customer File Custom Audiences

Our API allows you to build the target Custom Audiences from customer information. This includes email addresses, phone numbers, names, dates of birth, gender, locations, App User IDs, Page Scoped User IDs, Apple's Advertising Identifier (IDFA), or Android Advertising ID.

As the owner of your business' data, you are responsible for creating and managing this data. This includes information from your Customer Relationship Management (CRM) systems. To create audiences, you must share your data in an hashed format to maintain privacy. See Hashing and Normalizing Data. Facebook compares this with our hashed data to see if we should add someone on Facebook to your ad's audience.

You can add an unlimited number of records to an audience, but only up to 10000 at a time. It may take up to 1 hour before Facebook adds users to an audience, and up to 24 hours for deleting users from an audience.

This document covers how to:

Build a Custom Audience

To build a custom audience:

  1. Create an empty Custom Audience subtype=CUSTOM and customer_file_source.
  2. Update audience members at Users with IDs and hashed identifying data.

Example — Create an empty audience

curl -X POST \ -F 'name="My new Custom Audience"' \ -F 'subtype="CUSTOM"' \ -F 'description="People who purchased on my website"' \ -F 'customer_file_source="USER_PROVIDED_ONLY"' \ -F 'access_token=<ACCESS_TOKEN>' \ https://graph.facebook.com/v5.0/act_<AD_ACCOUNT_ID>/customaudiences
'use strict'; const bizSdk = require('facebook-nodejs-business-sdk'); const AdAccount = bizSdk.AdAccount; const CustomAudience = bizSdk.CustomAudience; const access_token = '<ACCESS_TOKEN>'; const app_secret = '<APP_SECRET>'; const app_id = '<APP_ID>'; const id = '<ID>'; const api = bizSdk.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 new Custom Audience', 'subtype' : 'CUSTOM', 'description' : 'People who purchased on my website', 'customer_file_source' : 'USER_PROVIDED_ONLY', }; const customaudiences = (new AdAccount(id)).createCustomAudience( fields, params ); logApiCallResult('customaudiences api call complete.', customaudiences);
require __DIR__ . '/vendor/autoload.php'; use FacebookAds\Object\AdAccount; use FacebookAds\Object\CustomAudience; 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 new Custom Audience', 'subtype' => 'CUSTOM', 'description' => 'People who purchased on my website', 'customer_file_source' => 'USER_PROVIDED_ONLY', ); echo json_encode((new AdAccount($id))->createCustomAudience( $fields, $params )->exportAllData(), JSON_PRETTY_PRINT);
from facebook_business.adobjects.adaccount import AdAccount from facebook_business.adobjects.customaudience import CustomAudience from facebook_business.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 new Custom Audience', 'subtype': 'CUSTOM', 'description': 'People who purchased on my website', 'customer_file_source': 'USER_PROVIDED_ONLY', } print AdAccount(id).create_custom_audience( 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).createCustomAudience() .setName(\"My new Custom Audience\") .setSubtype(CustomAudience.EnumSubtype.VALUE_CUSTOM) .setDescription(\"People who purchased on my website\") .setCustomerFileSource(CustomAudience.EnumCustomerFileSource.VALUE_USER_PROVIDED_ONLY) .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) customaudiences = ad_account.customaudiences.create({ name: 'My new Custom Audience', subtype: 'CUSTOM', description: 'People who purchased on my website', customer_file_source: 'USER_PROVIDED_ONLY', })

NameDescription

customer_file_source

type: enum string

Describes how the customer information in your Custom Audience was originally collected. Possible values include:

  • USER_PROVIDED_ONLY: Advertisers collected information directly from customers.
  • PARTNER_PROVIDED_ONLY: Advertisers sourced information directly from partners (e.g. agencies or data providers).

  • BOTH_USER_AND_PARTNER_ PROVIDED: Advertisers collected information directly from customers and it was also sourced from partners (ex: agencies).

name

type: string

Custom Audience name

description

type: string

Custom Audience description

subtype

type: string

Type of Custom Audience


Facebook compares your data with our encrypted user data. If we find a match, we add people to your custom audience and deliver ads to them. A successful return includes:

  • audience_id: numeric string
  • session_id: numeric string
  • num_received: int32
  • num_invalid_entries: int32
  • invalid_entry_samples: Map { string: string }

The num_invalid_entries indicates a number of users that did not match and are not in the custom audience. This number is not exact but represent the number range of users which do not match.

Share your custom audience with business objects. Learn more here.

Remove Audience Members

Use the same data you used to create an audience:

curl -X DELETE \
  --data-urlencode 'payload={ 
    "schema": "EMAIL_SHA256", 
    "data": [ 
      "<HASH>", 
      "<HASH>", 
      "<HASH>" 
    ] 
  }' \
  -d 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/<VERSION>/<CUSTOM_AUDIENCE_ID>/users

You can also remove people from a list with EXTERN_ID, if available:

curl -X DELETE \
  --data-urlencode 'payload={ 
    "schema": "EXTERN_ID", 
    "data": [ 
      "<ID>", 
      "<ID>", 
      "<ID>" 
    ] 
  }' \
  -d 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/<VERSION>/<CUSTOM_AUDIENCE_ID>/users

If a person opts out of being targeted, remove them from all custom audiences. To do so, send us the person and Facebook will delete them from your audiences. This removes people you specify from ALL custom audiences belonging to the specified ad account.

To opt-out a person, include the same fields as in user update and make a HTTP DELETE call to:

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

Multi-Key Matching

To increase the match rate for your records, provide multiple keys in an array of individual keys, for example [EXTERN_ID, LN, FN, EMAIL]. While you do not need to hash EXTERN_ID, you must hash all personally identifying information, such as emails and names. For details see Hashing and Normalizing Data.

You can provide some or all multi-keys for a record. For details, see multi-key extern id matching.

Add users with multi-key matches

curl \
  -F 'payload={ 
    "schema": [ 
      "FN", 
      "LN", 
      "EMAIL" 
    ], 
    "data": [ 
      [ 
        "<HASH>", 
        "<HASH>", 
        "<HASH>" 
      ], 
      [ 
        "<HASH>", 
        "<HASH>", 
        "<HASH>" 
      ] 
    ] 
  }' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/<VERSION>/<CUSTOM_AUDIENCE_ID>/users

If you use the APPUID or PAGEUID key, you must also include a list of App IDs or Page IDs for your apps or pages that people used.

curl -X POST \
  -F 'payload={
       "schema": [
         "EMAIL",
         "MADID",
         "APPUID",
         "LOOKALIKE_VALUE"
       ],
       "app_ids": [
         "<APP_ID>"
       ],
       "data": [
         [
           "<HASH>",
           "<ID>",
           "<ID>",
           "<VALUE>"
         ],
         [
           "<HASH>",
           "<ID>",
           "<ID>",
           "<VALUE>"
         ],
         [
           "<HASH>",
           "<ID>",
           "<ID>",
           "<VALUE>"
         ]
       ]
     }' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/<VERSION>/<CUSTOM_AUDIENCE_ID>/users

Hashing and Normalization for Multi-Key

You must hash data as SHA256. We don't support other hashing mechanisms. This is required for all data except External Identifiers, App User IDs, Page Scoped User IDs and Mobile Advertiser IDs.

Before you hash your data, normalize it so we can handle it. Only First name FN and Last Name LN support special characters and non-Roman alphabet. For best match results, provide the Roman alphabet translation with no special characters.

KeyGuidelines

EMAIL

criteria: email addresses

Hashing required.

Trim leading, trail whitespace, and convert all characters to lowercase.

PHONE

criteria: phone numbers

Hashing required.

Remove symbols, letters, and any leading zeroes. You should prefix the country code if COUNTRY field is not specified.

GEN

criteria: gender

Hashing required.

Use these values: m for male and f for female.

DOBY

criteria: birth year

Hashing required.

Use the YYYY format from 1900 to current year.

DOBM

criteria: birth month

Hashing required.

Use the MM format: 01 to 12.

DOBD

criteria: birthday

Hashing required.

Use the DD format: 01 to 31.

LN and FN

criteria: last and first names

Hashing required.

Use a-z only. Lowercase only, no punctuation. Special characters in UTF8 format.

ST

criteria: U.S. states

Hashing required.

Use the 2-character ANSI abbreviation code, lowercase. Normalize states outside U.S. in lowercase, no punctuation, no special characters, no white space.

CT

criteria: city

Hashing required.

Use a-z only. Lowercase only, no punctuation, no special characters, no white space.

ZIP

criteria: zip code

Hashing required.

Use lowercase, no white space. Use only the first 5 digits for U.S. Use Area/District/Sector format for the UK.

COUNTRY

criteria: country code

Hashing required.

Use 2-letter country codes (lowercase) in ISO 3166-1 alpha-2.

MADID

criteria: mobile advertiser ID

Hashing NOT required.

Use all lowercase, keep hyphens.

Hashing

Provide SHA256 values for normalized keys and HEX representations of this value, using lowercase for A through F. The hash function in PHP converts normalized email and phone number:

example result

hash("sha256", "mary@example.com")

f1904cf1a9d73a55fa5de0ac823c4403ded71afd4c3248d00bdcd0866552bb79

hash("sha256", "15559876543")

1ef970831d7963307784fa8688e8fce101a15685d62aa765fed23f3a2c576a4e

External Identifiers

You can match people for an audience with your own identifiers, known as External Identifiers or EXTERN_ID. While you do not need to hash this ID, you must hash all Personally Identifying Information (PII) that you send with the EXTERN_IDs.

For matching to work in future requests, you should also use the exact same format when you send the IDs. For example, if you choose to hash using SHA256, make sure to use the same hashed value.

You can use these IDs as individual keys to delete people from Custom Audiences or create new Custom Audiences. This way you don't need to re-upload any other matching keys. If you tag someone with hashed personal information and EXTERN_ID, we give EXTERN_ID lower precedence when we match them with people on Facebook.

The data retention period for EXTERN_ID is 90 days.

If you have an audience of EXTERN_ID fields in your ad account, create a new audience with just these identifiers:

curl \
  -F 'payload={"schema":"EXTERN_ID","data":["<ID>","<ID>"]}' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/<VERSION>/<CUSTOM_AUDIENCE_ID>/users

You can also add people tagged EXTERN_ID and with multi-key matching:

curl \
  -F 'payload={ 
    "schema": [ 
      "EXTERN_ID", 
      "FN", 
      "EMAIL", 
      "LN" 
    ], 
    "data": [ 
      [ 
        "<ID>", 
        "<HASH>", 
        "<HASH>", 
        "<HASH>" 
      ], 
      [ 
        "<ID>", 
        "<HASH>", 
        "<HASH>", 
        "<HASH>" 
      ], 
      [ 
        "<ID>", 
        "<HASH>", 
        "<HASH>", 
        "<HASH>" 
      ] 
    ] 
  }' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/<VERSION>/<CUSTOM_AUDIENCE_ID>/users

Facebook supports EXTERN_ID parameters for individual Ad Accounts. Facebook cannot use values from one Account for any other Ad Accounts, even if the accounts belong to the same entity.

Resources

There are other types of audiences you can build and target, or share: