Bid Multipliers

This API is available on a limited basis to partners and advertisers that are on the allow list. Contact your Meta representative to use it.

Bid multipliers enable advertisers to reduce the amount of audience segmentation required because it allows them to maintain a nuanced bidding strategy within a single ad set with one targeted audience. For example, an advertiser can create a single ad set, then use bid multipliers to bid differently for each of those recency buckets.

Advertisers typically create ad sets so that they can bid differently for various audience segments. For example, an advertiser can create 3 ad sets corresponding to 3 different age groups: 18–25, 26–35, 36–65.

Advertisers running housing, employment and credit ads, who are based in the United States or are running ads targeted to the United States have different sets of restrictions and a subset of audience categories are available for adjusting bids. Housing, employment, and credit campaigns are restricted from adjusting bids for audience categories of age, gender, locale, home_location, user_bucket, and lookalike custom_audience (a custom audience derived from a lookalike audience). See Special Ad Category.

Beginning January 30, 2023, ads that use a bid multiplier with third-party data categories (booking_window, custom_audience (including lookalike custom audiences), lengthofstay, travelstartdate, travelstartdayofweek, user_recency, user_bucket) will no longer be delivered to users who have opted out.

Bid Multiplier Best Practices

  • Use complex, customized bidding strategies without having to create too many audience segments or ad sets. This helps you achieve better ads delivery while you avoid over-segmenting campaigns into a larger number of ad sets with relatively small audiences.
  • Bid multipliers are not specific to an objective. They are compatible with the following optimizations: APP_INSTALLS, CLICKS, LANDING_PAGE_VIEWS, LEAD_GENERATION, OFFSITE_CLICKS, and OFFSITE_CONVERSIONS.
  • In the past, you could create 3 ad sets corresponding to 3 different age groups. You could then separately bid for each one of these ad sets. You can now create a single ad set and use bid multipliers to bid differently for each of those age groups; bid multipliers range from 0.09 to 1.0.
  • Bid multipliers need to be specified under a single user_groups key.

Note: All bid strategies are supported with bid multipliers, specifically: Bid Cap, Cost Cap and Lowest Cost.

Set Up Audience Categories

With bid multiplier, you can define audience categories and assign a bid multiplier for each audience category. Audience categories are defined with user demographic information, user device, and advertiser custom data. Housing, employment, or credit campaigns are restricted from assigning bids for audience categories of age, gender, locale, home_location, user_bucket, and lookalike custom_audience (a custom audience derived from a lookalike audience).

PriorityDescription

age

Bid differently based on age or age range. (Not available for housing, employment, and credit campaigns.)

booking_window

Bid differently based on number of days until the start of travel.

custom_audience

Bid based on custom_audience the user is a part of. Lookalike audiences are supported for this option, except for housing, employment, and credit campaigns.

device_platform

Bid differently based on the user's device platform, such as mobile or desktop.

gender

Bid differently based on gender. (Not available for housing, employment, and credit campaigns.)

home_location

Bid based on the user's home_location. This represents their current home location. The home_location multiplier can be broken down into cities, regions, and countries. (Not available for housing, employment, and credit campaigns.)

lengthofstay

Bid based on number of days between start and end of travel.

locale

Bid differently based on locale such as English or Spanish. (Not available for housing, employment, and credit campaigns.)

position_type

Bid based on which position an ad is shown; for example, facebook_feed, facebook_marketplace, or instagram_story.

publisher_platform

Bid based on publisher_platform such as facebook, instagram, audience_network, messenger.

travelstartdate

Bid differently based on date that travel starts; for example, 20181231 is 31 December 2018.

travelstartdayofweek

Bid based on day of week that travel starts. 0 is Monday; 6 is Sunday.

user_bucket

Bid based on the user_bucket value defined in the advertiser's pixel fire or app event. The user_bucket field is an optional parameter expressed in an integer ranging from 0 to 100. (Not available for housing, employment, and credit campaigns.)

user_device

Bid based on user_device, such as iPhone. See user_device

user_os

Bid based on user_os such as iOS or Android.

user_recency

Bid based on when the user last visited the site or app.

age

Group users by age ranges; for example, 18-25, 26-35. As an example, for an ad set with USD 5 max bid, bid USD 2.5 for users aged between 18 to 25, bid USD 3.5 for users aged between 26 and 40, bid USD 5 for all other users. Note: The default is optional. You can apply 1.0 as the multiplier.

Example

{
    "user_groups": {
      "age": {
        "18-25": 0.5,
        "26-40": 0.7,
        "default": 1.0
      }
    }
}

booking_window

Possible breakdown values include any integer range greater than or equal to 1. For example, 1-3, 4-9, and so on.

Example

curl -X POST \ 
  -F 'bid_adjustments=
     {"user_groups":{"booking_window":{"event_sources":["123456789"],"1-2":0.1,"3-5":0.2,"default":0.5}}}' \ 
  -F 'access_token='$access_token \ 
  https://graph.facebook.com/<API_VERSION>/<ad_set_id>

See also Travel Multipler Example.

custom_audience

Beginning January 30, 2023, ads that use a bid multiplier with third-party data categories (booking_window, custom_audience (including lookalike custom audiences), lengthofstay, travelstartdate, travelstartdayofweek, user_recency, user_bucket) will no longer be delivered to users who have opted out.

You can adjust bids based on your custom audiences.

Example

curl -X POST \ 
  -F 'bid_adjustments=
     {"user_groups":{"custom_audience":{"<CUSTOM_AUDIENCE_ID>":0.8, "<CUSTOM_AUDIENCE_ID>":1.0, "default":0.5}}}' \ 
  -F 'access_token='$access_token \ 
  https://graph.facebook.com/<API_VERSION>/<ad_set_id>

device_platform

Possible breakdown values:

  • mobile
  • desktop

Example

{
  "user_groups": {
    "device_platform": {
      "mobile": 0.7,
      "desktop": 0.9
    }
  }
}

gender

Group users by gender.

Example

{
  "user_groups": {
    "gender": {
      "male": 0.5,
      "female": 0.7,
      "default": 1.0
    }
  }
}

home_location

Possible breakdown values:

  • city id
  • region id
  • 2-digit country code

You can find city id and region id in the Search API. You can query from the Graph API Explorer or from your terminal.

Note: The default can only be set under home_location not cities, regions, or countries.

Example

{
  "user_groups": {
    "home_location": {
      "cities": {
         "2420605": 0.2
      },
      "regions": {
         "3847": 0.5
      },
      "countries": {
         "US": 0.2
      },
      "default": 0.8
     }
  }
}

length_of_stay

Possible breakdown values include any integer range greater than or equal to 1. For example, “1-3”, “4-9”, and so on.

Example

curl -X POST \ 
  -F 'bid_adjustments=
  {"user_groups":{"length_of_stay":{"event_sources":["123456789"],"1-2":0.1,"3-     5":0.2,"default":0.5}}}' \ 
  -F 'access_token='$access_token \ 
  https://graph.facebook.com/<API_VERSION>/<ad_set_id>

See also Travel Multipler Example.

locale

You can use locale or locale group IDs, such as 6 for US English or 5 for German.

You can find locale IDs with Targeting Search, Locale with type=adlocale. For example:

{
  "user_groups": {
    "locale": {
      6: 0.8,
      5: 0.3
    }
  }
}

position_type

This category is similar to the position options in the Targeting API. Possible breakdown values:

PlacementValue

Facebook feed

facebook_feed

Facebook Marketplace

facebook_marketplace

Facebook video feeds

facebook_suggested_video

Facebook right column

facebook_right_hand_column

Facebook Business Explore

facebook_biz_disco_feed

Instagram feed

instagram_stream

Instagram profile feed

instagram_profile_feed

Instagram Explore

instagram_explore

Instagram Explore home

instagram_explore_home

Messenger inbox

messenger_messenger_home

Instagram Stories

instagram_story

Facebook Stories

facebook_story

Messenger Stories

messenger_story

Instagram Reels

instagram_reels

Facebook Reels

facebook_facebook_reels

Facebook in-stream videos

facebook_instream_video

Ads on Facebook Reels

facebook_facebook_reels_overlay

Facebook search results

facebook_search

Instagram search results

instagram_ig_search

Messenger sponsored messages

Not supported

Audience Network native, banner and interstitial

audience_network_classic

Audience Network rewarded videos

audience_network_rewarded_video

Audience Network in-stream videos

Not supported

Example

{
  "user_groups": {
    "position_type":{
        "facebook_feed":0.9,
        "messenger_messenger_home":0.7,
        "instagram_stream":0.8,
        "audience_network_classic":0.5,
        "default":0.4
    }
  }
}

publisher_platform

Possible breakdown values are:

  • facebook
  • instagram
  • audience_network
  • messenger

Example

{
  "user_groups": {
    "publisher_platform": {
      "facebook": 0.7,
      "instagram": 0.9,
      "default": 1.0 // We'll apply bid multiplier 1.0 if no default is specified anyway
    }
  }
}

travel_start_date

Possible breakdown values include any date range in format _yyyymmdd_-_yyyymmdd_.

Example

curl -X POST \ 
  -F 'bid_adjustments=
     {"user_groups":{"travel_start_date":{"event_sources":["123456789"],"20180901-20181001":0.2,"default":0.9}}}' \ 
  -F 'access_token='$access_token \ 
  https://graph.facebook.com/<API_VERSION>/<ad_set_id>

See also Travel Multipler Example.

travel_start_day_of_week

Possible breakdown values include any integer between 0 and 6, inclusive. 0 is Monday; 6 is Sunday.

Example

curl -X POST \ 
  -F 'bid_adjustments=
  {"user_groups":{"travel_start_day_of_week":{"event_sources":        ["123456789"],"0":0.1,"2":0.2,"6":0.3,"default":0.9}}}' \ 
  -F 'access_token='$access_token \ 
  https://graph.facebook.com/<API_VERSION>/<ad_set_id>

See also Travel Multipler Example.

user_bucket

You can send us results of your own user classifier. Then send us an extra user_bucket parameter in pixel fires or app events. User buckets are integers ranging from 0 to 100.

Specify the user bucket group definition with the following format:

  • event_sources - Pixel fire or app event source to track.
  • event_retention - Optional. Time, in seconds, to ignore old user_bucket values.
  • events_dedup_mode - Optional. Flag to indicate which user_bucket value to use when a single event source sends different user_bucket values for the same user. The default value is latest.
  • event_source_preference - Optional. Flag to indicate which user_bucket to use when multiple event sources send different user_bucket values for the same user. The default value is latest.

Example

{
  "user_groups": {
   "user_bucket": {
      "event_sources": [<pixel_id>,<app_id>,...],
      "event_retention": 604800, // optional, exclude old events
      
      //optional, useful when multiple event sources have user_bucket
      "events_dedup_mode": "max"|"min"|"latest",
      
      //optional, dedup user_bucket values sent from one single event source
      "event_source_preference": "max"|"min"|"latest",
      
      "1":0.7, // these are the bid multipliers
      "2":1.0,
     }
  }
}

user_device

Possible breakdown values:

  • iPad
  • iPhone

See other possible values at Targeting Search API with type=adTargetingCategory and class=user_device.

Example

{
  "user_groups": {
    "user_device": {
      "iPad": 0.7,
      "iPhone": 0.9,
      "default": 1.0
    }
  }
}

Example

curl
  -F 'name=Test BM Adset '$(date +%s) \
  -F 'bid_amount=3000' \
  -F 'billing_event=IMPRESSIONS' \
  -F 'optimization_goal=OFFSITE_CONVERSIONS' \
  -F 'daily_budget=15000' \
  -F 'campaign_id=23843038336220329' \
  -F 'promoted_object={"product_set_id":"267888283975766"}' \
  -F 'targeting={
     "geo_locations": {"countries":["AQ"]},
     "dynamic_audience_ids": ["23842885952670329"],
     "publisher_platforms": ["facebook"]
    }' \
  -F 'bid_adjustments={"user_groups":{"user_device": {"iPad": 0.7, "iPhone": 0.9, "default": 1.0}}}' \
  -F 'status=PAUSED' \
  -F 'access_token='$access_token \
  https://graph.facebook.com/<API_VERSION>/act_1653439931385336/adsets

Example

curl
  -F 'name=Test BM Adset '$(date +%s) \
  -F 'bid_amount=3000' \
  -F 'billing_event=IMPRESSIONS' \
  -F 'optimization_goal=OFFSITE_CONVERSIONS' \
  -F 'daily_budget=15000' \
  -F 'campaign_id=23843038336220329' \
  -F 'promoted_object={"product_set_id":"267888283975766"}' \
  -F 'targeting={
     "geo_locations": {"countries":["AQ"]},
     "dynamic_audience_ids": ["23842885952670329"],
     "publisher_platforms": ["facebook"]
     }' \
  -F 'bid_adjustments={"user_groups":{"user_device": {"iPad": 0.7, "iPhone": 0.9, "default": 1.0}}}' \
  -F 'status=PAUSED' \
  -F 'access_token='$access_token \
   https://graph.facebook.com/<API_VERSION>/act_1653439931385336/adsets
   {"id":"23843038339320329"}

Example

curl
  -F 'access_token='$access_token \
  https://graph.facebook.com/VERSION/ID?fields=bid_adjustments
  {"bid_adjustments":{"user_groups":"{\"user_device\":    {\"default\":1,\"iPad\":0.7,\"iPhone\":0.9}}"},"id":"ID"}

See also Advanced Example.

user_group_weight_spec

Possible breakdown values:

  • age
  • gender
  • device_platform
  • publisher_platform
  • user_device
  • user_os

See also Advanced Example.

Example - The user_group_weight_spec is a JSON structure and looks like this:

{
  <BREAKDOWN_NAME>: {
    <BREAKDOWN_VALUE_1>: <WEIGHT_VALUE> OR <NESTED_USER_GROUP_WEIGHT_SPEC>,
    <BREAKDOWN_VALUE_2>: <WEIGHT_VALUE> OR <NESTED_USER_GROUP_WEIGHT_SPEC>,
    <BREAKDOWN_VALUE_3>: <WEIGHT_VALUE> OR <NESTED_USER_GROUP_WEIGHT_SPEC>,
    ...
    "default": <WEIGHT_VALUE> OR <NESTED_USER_GROUP_WEIGHT_SPEC>, // optional, if not specified, we'll use 1.0
  }
}
{
  "age": {
    "18-25": 0.7,
    "26-35": {
      "gender": {
        "male": 0.9,
        "female": 1.0
      }
    },
    "default": 0.85
  }
}

* For users between the ages of 18 and 25, we apply bid multiplier 0.7.
* For male users between the ages of 26 and 35, we apply bid multiplier 0.9.
* For female users between the ages of 26 and 35, we apply bid multiplier 1.0.
* For all other users, we apply bid multiplier 0.85.

Breakdown values are integer age ranges. For example, 18-25, where the minimum age is 18 and ranges should not overlap.

Example

{
  "user_groups": {
    "age": {
      "18-25": 0.7,
      "30-40": 1.0,
      "default": 0.3
    }
  }
}

Advanced Example

> curl 
    -F 'bid_adjustments={"user_groups":{"user_device":{"iPad":0.3,"iPhone":{"user_os":{"Android":0.3,"iOS":{"age":{"18-35":0.3,"35-45":0.4}}}}}}}' -F access_token=$token https://graph.intern.facebook.com/v2.12/6089875504114
{"success":true}%
> curl -G 
   -d access_token=$token https://graph.intern.facebook.com/v2.12/6089875504114\?  fields\=bid_adjustments
{"bid_adjustments":{"user_groups":"{\"user_device\":{\"iPad\":0.3,\"iPhone\":{\"user_os\":{\"Android\":0.3,\"iOS\":{\"age\":{\"18-35\":0.3,\"35-45\":0.4}}}}}}"},"id":"6089875504114"}%

Travel Multiplier Examples

curl -X POST \
  -F 'bid_adjustments={"user_groups":{"travel_start_day_of_week":{"event_sources":["1862565504034757"],"1":0.1,"3":0.1,"default":0.9}}}' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/<API_VERSION>/<ADSET_ID>

  Length of Stay 'bid_adjustments={"user_groups":{"length_of_stay":{"event_sources":["1862565504034757"],"1-2":0.1,"3-7":0.2,"default":0.5}}}'
  Booking window 'bid_adjustments={"user_groups":{"booking_window":{"event_sources":["1862565504034757"],"1-2":0.1,"3-7":0.2,"default":0.5}}}'
  Travel start date: 'bid_adjustments={"user_groups":{"travel_start_date":{"event_sources":["1862565504034757"],"20180918-20190101":0.1,"default":0.5}}}'
  Day of week: 'bid_adjustments={"user_groups":{"travel_start_day_of_week":{"event_sources":["1862565504034757"],"1":0.1,"2":0.1,"0":0.2,"default":0.5}}}'

user_os

Possible breakdown values:

  • iOS
  • Windows

See other possible values at Targeting Search API with type=adTargetingCategory and class=user_os.

Current supported values:

  • Android
  • Windows
  • Windows Phone
  • iOS

Example

{
  "user_groups": {
    "user_os": {
      "Android": 0.7,
      "iOS": 0.9,
      "default": 1.0
    }
  }
}

iOS14 Impact

Will bid multiplier for website conversion campaigns be affected by iOS 14 policy changes?

Yes, we anticipate signal loss and less identifiable attribution from iOS 14 changes, resulting in fewer signals per ad set. Although the majority of categories you can bid on should continue to function as usual, multipliers for recency, custom audience and user_bucket, will be impacted if targeting iOS 14.5 users, as those multipliers depend on events measured by the FB pixel or the Conversions API. All other multipliers are coming from onsite data and don't rely on the FB pixel or the Conversions API.

user_recency

Group users by time because they have any pixel fire or app events. You must specify which event sources to track and time windows.

Example

This example shows how to apply bid multiplier 1.0 for users who have pixel fire or app events within 86400 seconds, and so on.

{
  "user_groups": {
    "user_recency": {
      "event_sources": [<pixel_id>,<app_id>,...],
      "0-86400": 1.0,
      "86401-172800": 0.7,
      "default": 0.5
    }
  }
}

Cascade Multiple Breakdowns

You can also define user groups with multiple breakdowns by replacing a floating bid multiplier number with a further breakdown specification. For example, an adset with USD 5 max bid and below config would look like this:

  • bid USD 4.5 for male users
  • bid USD 3.5 for female users aged between 18 and 25
  • bid USD 4.0 for female users aged between 26 and 35
  • bid USD 5.0 for all other users
{
  "user_groups": {
    "gender": {
      "male": 0.9,
      "female": {
        "age": {
          "18-25": 0.7,
          "26-35": 0.8
        }
      }
    }
  }
}

Usage Requirements

  • The value of the bid multiplier can range from 0.09 to 1.0.

API Calls

Get

curl -G \
  -d 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/<API_VERSION>/<ADSET_ID>?fields=bid_adjustments

Update

curl \
  -F 'bid_adjustments={"user_groups":<USER_GROUP_WEIGHT_SPEC>}' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/<API_VERSION>/<PRODUCT_CATALOG_ID>/<ADSET_ID>

Create or Update Bid Multiplier for an Ad Set

Below is a sample API call to update an existing ad set. (You need to substitute an ad set ID, access token, event sources, and your desired bid multipliers.)

curl -X POST \ -F 'bid_adjustments={ "user_groups": { "user_bucket": { "event_sources": [ "<PIXEL_ID>", "<APP_ID>" ], "1": 0.1, "2": 0.2, "3": 0.3, "default": { "gender": { "male": 0.99, "female": 0.12 } } } } }' \ -F 'access_token=<ACCESS_TOKEN>' \ https://graph.facebook.com/v19.0/<AD_SET_ID>/
'use strict'; const bizSdk = require('facebook-nodejs-business-sdk'); const AdSet = bizSdk.AdSet; const access_token = '<ACCESS_TOKEN>'; const app_secret = '<APP_SECRET>'; const app_id = '<APP_ID>'; const id = '<AD_SET_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 = { 'bid_adjustments' : {'user_groups':{'user_bucket':{'event_sources':['<pixelID>','<appID>'],'1':0.1,'2':0.2,'3':0.3,'default':{'gender':{'male':0.99,'female':0.12}}}}}, }; const sample_code = (new AdSet(id)).update( fields, params ); logApiCallResult('sample_code api call complete.', sample_code);
require __DIR__ . '/vendor/autoload.php'; use FacebookAds\Object\AdSet; use FacebookAds\Api; use FacebookAds\Logger\CurlLogger; $access_token = '<ACCESS_TOKEN>'; $app_secret = '<APP_SECRET>'; $app_id = '<APP_ID>'; $id = '<AD_SET_ID>'; $api = Api::init($app_id, $app_secret, $access_token); $api->setLogger(new CurlLogger()); $fields = array( ); $params = array( 'bid_adjustments' => array('user_groups' => array('user_bucket' => array('event_sources' => array('<pixelID>','<appID>'),'1' => 0.1,'2' => 0.2,'3' => 0.3,'default' => array('gender' => array('male' => 0.99,'female' => 0.12))))), ); echo json_encode((new AdSet($id))->updateSelf( $fields, $params )->exportAllData(), JSON_PRETTY_PRINT);
from facebook_business.adobjects.adset import AdSet from facebook_business.api import FacebookAdsApi access_token = '<ACCESS_TOKEN>' app_secret = '<APP_SECRET>' app_id = '<APP_ID>' id = '<AD_SET_ID>' FacebookAdsApi.init(access_token=access_token) fields = [ ] params = { 'bid_adjustments': {'user_groups':{'user_bucket':{'event_sources':['<pixelID>','<appID>'],'1':0.1,'2':0.2,'3':0.3,'default':{'gender':{'male':0.99,'female':0.12}}}}}, } print AdSet(id).update( 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 = \"<AD_SET_ID>\"; APIContext context = new APIContext(access_token).enableDebug(true); new AdSet(id, context).update() .setBidAdjustments(\"{\\"user_groups\\":{\\"user_bucket\\":{\\"event_sources\\":[\\"<pixelID>\\",\\"<appID>\\"],\\"1\\":0.1,\\"2\\":0.2,\\"3\\":0.3,\\"default\\":{\\"gender\\":{\\"male\\":0.99,\\"female\\":0.12}}}}}\") .execute(); } }
require 'facebook_ads' access_token = '<ACCESS_TOKEN>' app_secret = '<APP_SECRET>' app_id = '<APP_ID>' id = '<AD_SET_ID>' FacebookAds.configure do |config| config.access_token = access_token config.app_secret = app_secret end ad_set = FacebookAds::AdSet.get(id) ad_set.bid_adjustments = {'user_groups':{'user_bucket':{'event_sources':['<pixelID>','<appID>'],'1':0.1,'2':0.2,'3':0.3,'default':{'gender':{'male':0.99,'female':0.12}}}}} ad_set.save

Set Up Test Campaign

Create your test campaigns using a conversion lift or split test, working with your Meta account team and measurement lead. To assess performance, we suggest the following cells in a 3-way split test:

  • Cell 1 (Control A), Campaign 1 - 1 ad set with 1 bid for all targeted users
  • Cell 2 (Control B), Campaign 2 - Multiple ad sets where we create one ad set for each user group. (you can use Website/Mobile Custom Audiences rules to segment based on pixel/app parameters).
  • Cell 3 (Test), Campaign 3 - 1 ad set, with different bid multipliers for different user groups. Make sure the adjusted bid for each user group here is the same as the ad set level bid for the corresponding ad set in Cell 2.

Set Up Split Tests

At this point, you should set up split testing and control groups to verify performance using bid multiplier. We run the tests for 1–2 weeks, and don't require a minimum budget. Set up split testing as follows:

  • Cell 1, Control A Should contain one ad set with one bid amount and targeting should be based on all user_buckets.
  • Cell 2, Control B Should contain multiple ad sets, with one ad set per user_bucket. Each ad set should target a separate user_bucket and corresponding bid. You can use website or mobile custom Audiences rules to further segment your audience based on other Meta Pixel or App Events parameters. See Website Custom Audiences and Mobile App Custom Audiences.
  • Cell 3, Test Contains one ad set with your bid_adjustment property to determine different bids for each user_bucket. Your multipliers should correspond to individual ad set bids for Cell 2, Control B.

For more information, see Split Testing.

Set Up Test Campaign

Set up an ad campaign as you do normal campaigns. Contact your Meta representative for help setting up your bid adjustment.

Set up user_groups and different bid multipliers for each group. Your groups are based on demographic properties, such as age, gender, and specific properties, such as user score or loyalty program. For example:

{
   "user_bucket":{
      "business_id":253286871795863,
      "1":0.7,
      "2":1.0,
      "3":{
         "gender":{
            "male":1.0,
            "female":0.8
         }
      },
      "default": 0.9
   }
}

In this example:

  • For people with loyalty_program value 1, apply bid multiplier 0.7
  • For people with loyalty_program value 2, apply bid multiplier 1.0
  • For males with loyalty_program value 3, apply bid multiplier 1.0
  • For females with loyalty_program value 3, apply bid multiplier 0.8
  • For people with loyalty_program other than 1, 2 or 3, apply bid multiplier 0.9
  • For all others, apply bid multiplier 1.0

Now, you can create the ad campaign:

curl -X POST \ -F 'name="My Adset with bid multiplier"' \ -F 'campaign_id="<AD_CAMPAIGN_ID>"' \ -F 'daily_budget=3000' \ -F 'billing_event="IMPRESSIONS"' \ -F 'optimization_goal="OFFSITE_CONVERSIONS"' \ -F 'bid_amount=500' \ -F 'bid_adjustments={ "user_groups": { "gender": { "male": 0.8, "female": 1 } } }' \ -F 'promoted_object={ "product_set_id": "<PRODUCT_SET_ID>", "custom_event_type": "ADD_TO_CART" }' \ -F 'targeting={ "facebook_positions": [ "feed" ], "geo_locations": { "countries": [ "US" ] } }' \ -F 'status="PAUSED"' \ -F 'access_token=<ACCESS_TOKEN>' \ https://graph.facebook.com/v19.0/act_<AD_ACCOUNT_ID>/adsets
'use strict'; const bizSdk = require('facebook-nodejs-business-sdk'); const AdAccount = bizSdk.AdAccount; const AdSet = bizSdk.AdSet; const access_token = '<ACCESS_TOKEN>'; const app_secret = '<APP_SECRET>'; const app_id = '<APP_ID>'; const id = '<AD_ACCOUNT_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 Adset with bid multiplier', 'campaign_id' : '<adCampaignLinkClicksID>', 'daily_budget' : '3000', 'billing_event' : 'IMPRESSIONS', 'optimization_goal' : 'OFFSITE_CONVERSIONS', 'bid_amount' : '500', 'bid_adjustments' : {'user_groups':{'gender':{'male':0.8,'female':1}}}, 'promoted_object' : {'product_set_id':'<productSetID>','custom_event_type':'ADD_TO_CART'}, 'targeting' : {'facebook_positions':['feed'],'geo_locations':{'countries':['US']}}, 'status' : 'PAUSED', }; const 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 = '<AD_ACCOUNT_ID>'; $api = Api::init($app_id, $app_secret, $access_token); $api->setLogger(new CurlLogger()); $fields = array( ); $params = array( 'name' => 'My Adset with bid multiplier', 'campaign_id' => '<adCampaignLinkClicksID>', 'daily_budget' => '3000', 'billing_event' => 'IMPRESSIONS', 'optimization_goal' => 'OFFSITE_CONVERSIONS', 'bid_amount' => '500', 'bid_adjustments' => array('user_groups' => array('gender' => array('male' => 0.8,'female' => 1))), 'promoted_object' => array('product_set_id' => '<productSetID>','custom_event_type' => 'ADD_TO_CART'), 'targeting' => array('facebook_positions' => array('feed'),'geo_locations' => array('countries' => array('US'))), 'status' => 'PAUSED', ); echo json_encode((new AdAccount($id))->createAdSet( $fields, $params )->exportAllData(), JSON_PRETTY_PRINT);
from facebook_business.adobjects.adaccount import AdAccount from facebook_business.adobjects.adset import AdSet from facebook_business.api import FacebookAdsApi access_token = '<ACCESS_TOKEN>' app_secret = '<APP_SECRET>' app_id = '<APP_ID>' id = '<AD_ACCOUNT_ID>' FacebookAdsApi.init(access_token=access_token) fields = [ ] params = { 'name': 'My Adset with bid multiplier', 'campaign_id': '<adCampaignLinkClicksID>', 'daily_budget': '3000', 'billing_event': 'IMPRESSIONS', 'optimization_goal': 'OFFSITE_CONVERSIONS', 'bid_amount': '500', 'bid_adjustments': {'user_groups':{'gender':{'male':0.8,'female':1}}}, 'promoted_object': {'product_set_id':'<productSetID>','custom_event_type':'ADD_TO_CART'}, 'targeting': {'facebook_positions':['feed'],'geo_locations':{'countries':['US']}}, 'status': 'PAUSED', } 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 = \"<AD_ACCOUNT_ID>\"; APIContext context = new APIContext(access_token).enableDebug(true); new AdAccount(id, context).createAdSet() .setName(\"My Adset with bid multiplier\") .setCampaignId(\"<adCampaignLinkClicksID>\") .setDailyBudget(3000L) .setBillingEvent(AdSet.EnumBillingEvent.VALUE_IMPRESSIONS) .setOptimizationGoal(AdSet.EnumOptimizationGoal.VALUE_OFFSITE_CONVERSIONS) .setBidAmount(500L) .setBidAdjustments(\"{\\"user_groups\\":{\\"gender\\":{\\"male\\":0.8,\\"female\\":1}}}\") .setPromotedObject(\"{\\"product_set_id\\":\\"<productSetID>\\",\\"custom_event_type\\":\\"ADD_TO_CART\\"}\") .setTargeting( new Targeting() .setFieldFacebookPositions(Arrays.asList(\"feed\")) .setFieldGeoLocations( new TargetingGeoLocation() .setFieldCountries(Arrays.asList(\"US\")) ) ) .setStatus(AdSet.EnumStatus.VALUE_PAUSED) .execute(); } }
require 'facebook_ads' access_token = '<ACCESS_TOKEN>' app_secret = '<APP_SECRET>' app_id = '<APP_ID>' id = '<AD_ACCOUNT_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 with bid multiplier', campaign_id: '<adCampaignLinkClicksID>', daily_budget: '3000', billing_event: 'IMPRESSIONS', optimization_goal: 'OFFSITE_CONVERSIONS', bid_amount: '500', bid_adjustments: {'user_groups':{'gender':{'male':0.8,'female':1}}}, promoted_object: {'product_set_id':'<productSetID>','custom_event_type':'ADD_TO_CART'}, targeting: {'facebook_positions':['feed'],'geo_locations':{'countries':['US']}}, status: 'PAUSED', })

Once you create your ad sets, set bid_adjustments on the ad set via the API. The parameter should look something like this:

{
  "user_groups": {
    "user_bucket": {
      "event_sources": [<pixel_id>,<app_id>,...],
      "event_source_preference": "max"|"min"|"latest", //optional, useful when multiple event sources have user_bucket
      "events_dedup_mode": "max"|"min"|"latest", //optional, dedup user_bucket values sent from one single event source
      "event_retention": 604800, // optional, exclude old events
      "1":0.7, // these are the bid multipliers
      "2":1.0,
      "default": { // used in the case that we don't have user_bucket for that user
         gender:{ // this is a nested example, but you could just do "default": 1.0,
            "male": {
              home_location: {
                  cities: { // city id, can be found in search API, eg: search?type=adgeolocation&q=Menlo Park&limit=10
                    "2420605": 0.2,
                  },
                  regions: {
                    "3847": 0.5
                  },
                  countries: {
                    "US": 0.2
                  }
                }
              }
            },
            "female": {
              "user_recency": {
                "event_sources": [<pixel_id>,<app_id>,...],
                "0-86400": 0.5,
                "86400-172800": 0.7,
                "default": 0.2
              }
            }
         },
      },
   },
}

We don't currently validate this parameter. Send your ad set ID to your Meta representative and we can manually check it.

For each event source, the most recently received user_bucket for that user is used. But, if multiple event sources are specified (ex: pixel and app), and 2 or more of them have their own user_bucket recorded, then we take the max of them all.

The following is an example call to update an existing ad set. You should provide your own ad set ID, access token, event sources, and bid multipliers:

curl -X POST 
  -F access_token=<access_token> \
  -F 'bid_adjustments={"user_groups": {"user_bucket": {"event_sources": [<pixel_id>,  <app_id>,...], "1": 0.1, "2": 0.2, "3": 0.3, "default": {"gender": {"male": 0.99, "female": 0.1}} }} }' \ 
  https://graph.facebook.com/<VERSION>/<ad-set-id>