Ads Buying and Optimization

Learn how your bids and budget work with Facebook's ad auction and delivery. This covers bidding options, placing bids for desired action, setting budget limits and tracking ads delivery. Facebook's auction functions the same way for API-created ads as they do for ads from Facebook tools. See Ads Help Center, Auction.

Budgets

Set daily budget or lifetime budget at the ad set level. The amount you set for bid and budget are at ad account currencies minimum denomination level, such as cents for USD. All ads delivered in that set will not exceed a spend limit:

  • To run your ads continuously, choose a per day budget.
  • For a fixed duration, choose a lifetime budget.

To set a daily budget of 20 dollars:

curl -X POST \ -F 'name="My First Adset"' \ -F 'daily_budget=2000' \ -F 'start_time="2019-11-17T15:17:32-0800"' \ -F 'end_time="2019-11-24T15:17:32-0800"' \ -F 'campaign_id="<AD_CAMPAIGN_ID>"' \ -F 'bid_amount=100' \ -F 'billing_event="LINK_CLICKS"' \ -F 'optimization_goal="LINK_CLICKS"' \ -F 'targeting={ "geo_locations": { "countries": [ "US" ] } }' \ -F 'status="PAUSED"' \ -F 'access_token=<ACCESS_TOKEN>' \ https://graph.facebook.com/v5.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 First Adset', 'daily_budget' : '2000', 'start_time' : '2019-08-07T02:19:13-0700', 'end_time' : '2019-08-14T02:19:13-0700', 'campaign_id' : '<adCampaignLinkClicksID>', 'bid_amount' : '100', 'billing_event' : 'LINK_CLICKS', 'optimization_goal' : 'LINK_CLICKS', 'targeting' : {'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 First Adset', 'daily_budget' => '2000', 'start_time' => '2019-08-07T02:19:13-0700', 'end_time' => '2019-08-14T02:19:13-0700', 'campaign_id' => '<adCampaignLinkClicksID>', 'bid_amount' => '100', 'billing_event' => 'LINK_CLICKS', 'optimization_goal' => 'LINK_CLICKS', 'targeting' => array('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 First Adset', 'daily_budget': '2000', 'start_time': '2019-08-07T02:19:13-0700', 'end_time': '2019-08-14T02:19:13-0700', 'campaign_id': '<adCampaignLinkClicksID>', 'bid_amount': '100', 'billing_event': 'LINK_CLICKS', 'optimization_goal': 'LINK_CLICKS', 'targeting': {'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 First Adset\") .setDailyBudget(2000L) .setStartTime(\"2019-08-07T02:19:13-0700\") .setEndTime(\"2019-08-14T02:19:13-0700\") .setCampaignId(\"<adCampaignLinkClicksID>\") .setBidAmount(100L) .setBillingEvent(AdSet.EnumBillingEvent.VALUE_LINK_CLICKS) .setOptimizationGoal(AdSet.EnumOptimizationGoal.VALUE_LINK_CLICKS) .setTargeting( new Targeting() .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 First Adset', daily_budget: '2000', start_time: '2019-08-07T02:19:13-0700', end_time: '2019-08-14T02:19:13-0700', campaign_id: '<adCampaignLinkClicksID>', bid_amount: '100', billing_event: 'LINK_CLICKS', optimization_goal: 'LINK_CLICKS', targeting: {'geo_locations':{'countries':['US']}}, status: 'PAUSED', })

To set a lifetime budget of 200 dollars for a campaign setup to run for 10 days:

curl -X POST \ -F 'name="My First Adset"' \ -F 'lifetime_budget=20000' \ -F 'start_time="2019-11-17T15:17:32-0800"' \ -F 'end_time="2019-11-27T15:17:32-0800"' \ -F 'campaign_id="<AD_CAMPAIGN_ID>"' \ -F 'bid_amount=100' \ -F 'billing_event="LINK_CLICKS"' \ -F 'optimization_goal="LINK_CLICKS"' \ -F 'targeting={ "facebook_positions": [ "feed" ], "geo_locations": { "countries": [ "US" ] }, "publisher_platforms": [ "facebook", "audience_network" ] }' \ -F 'status="PAUSED"' \ -F 'access_token=<ACCESS_TOKEN>' \ https://graph.facebook.com/v5.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 First Adset', 'lifetime_budget' : '20000', 'start_time' : '2019-08-07T02:19:25-0700', 'end_time' : '2019-08-17T02:19:25-0700', 'campaign_id' : '<adCampaignLinkClicksID>', 'bid_amount' : '100', 'billing_event' : 'LINK_CLICKS', 'optimization_goal' : 'LINK_CLICKS', 'targeting' : {'facebook_positions':['feed'],'geo_locations':{'countries':['US']},'publisher_platforms':['facebook','audience_network']}, '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 First Adset', 'lifetime_budget' => '20000', 'start_time' => '2019-08-07T02:19:25-0700', 'end_time' => '2019-08-17T02:19:25-0700', 'campaign_id' => '<adCampaignLinkClicksID>', 'bid_amount' => '100', 'billing_event' => 'LINK_CLICKS', 'optimization_goal' => 'LINK_CLICKS', 'targeting' => array('facebook_positions' => array('feed'),'geo_locations' => array('countries' => array('US')),'publisher_platforms' => array('facebook','audience_network')), '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 First Adset', 'lifetime_budget': '20000', 'start_time': '2019-08-07T02:19:25-0700', 'end_time': '2019-08-17T02:19:25-0700', 'campaign_id': '<adCampaignLinkClicksID>', 'bid_amount': '100', 'billing_event': 'LINK_CLICKS', 'optimization_goal': 'LINK_CLICKS', 'targeting': {'facebook_positions':['feed'],'geo_locations':{'countries':['US']},'publisher_platforms':['facebook','audience_network']}, '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 First Adset\") .setLifetimeBudget(20000L) .setStartTime(\"2019-08-07T02:19:25-0700\") .setEndTime(\"2019-08-17T02:19:25-0700\") .setCampaignId(\"<adCampaignLinkClicksID>\") .setBidAmount(100L) .setBillingEvent(AdSet.EnumBillingEvent.VALUE_LINK_CLICKS) .setOptimizationGoal(AdSet.EnumOptimizationGoal.VALUE_LINK_CLICKS) .setTargeting( new Targeting() .setFieldFacebookPositions(Arrays.asList(\"feed\")) .setFieldGeoLocations( new TargetingGeoLocation() .setFieldCountries(Arrays.asList(\"US\")) ) .setFieldPublisherPlatforms(Arrays.asList(\"facebook\", \"audience_network\")) ) .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 First Adset', lifetime_budget: '20000', start_time: '2019-08-07T02:19:25-0700', end_time: '2019-08-17T02:19:25-0700', campaign_id: '<adCampaignLinkClicksID>', bid_amount: '100', billing_event: 'LINK_CLICKS', optimization_goal: 'LINK_CLICKS', targeting: {'facebook_positions':['feed'],'geo_locations':{'countries':['US']},'publisher_platforms':['facebook','audience_network']}, status: 'PAUSED', })

If you choose daily budget, we pace your daily spending while a lifetime budget paces spending over an ad set's lifetime.

Ad Sets Budget Rebalancing

Ad Set Budget Balancing lets Facebook automatically move budget between Ad Sets in a Campaign once a day around midnight in your time zone. Move budgets from Ad Sets experiencing under-delivery to budget-constrained Ad Sets that can deliver more impressions. Facebook determines delivery rate based on target spend and actual spend at different times.

To use this feature, you need Ad Sets:

  • Under the same Campaign.
  • That run at least 10 hours per day.
  • With the same budget type: daily or lifetime budget.
  • That are active at the time of rebalancing.

Budgets are rebalanced between Ad Set, but you enable it with budget_rebalance_flag on a Campaign object. All Ad Sets in the campaign are affected. Set this field using the API call below.

curl -i -X POST \
-d "budget_rebalance_flag=true" \
-d "access_token=<ACCESS_TOKEN>" \
https://graph.facebook.com/AD_VERSION/<CAMPAIGN_ID>

You can also set budget_rebalance_flag on Campaign creation. See Ads Management Quickstart.

Optimization Goals

Define advertising goals you want to achieve when Facebook delivers your ads. We use your ad set's optimization_goal to decide which people get your ad. For example with APP_INSTALLS, Facebook delivers your ad to people who are more likely to install your app.

optimization_goal defaults to a goal associated with your objective. For example, if objective is APP_INSTALLS, optimization_goal defaults to APP_INSTALLS.

If you specify another optimization_goal, Facebook delivers your ad to as many daily unique people as possible, regardlesss of the probability anyone takes action towards your objective. See Validation Best Practices.

In Marketing API v2.4, we replaced forms of bidding such as bid_type, bid_info, and conversion_specs, with new fields: optimization_goal, bid_amount, and billing_event. This decoupled campaign optimization such APP_INSTALLS or LINK_CLICKS from billing, such as charges per IMPRESSIONS, APP_INSTALLS, or LINK_CLICKS.

See Resources for more information.

Bidding

A bid expresses how much you value your ad reaching a target audience and delivering results on your optimization_goal. bid_amount is the amount you want to spend to reach a given optimization_goal. At Facebook's ad auction, Facebook evaluates your bid_amount and the probability of reaching your optimization_goal. We apply an effective bid so you only win auctions and have your ads delivered when you are likely to reach your optimization_goal.

When you choose your bid:

  • Bid your true value: Think about your advertising objective and bid the maximum amount you're willing to pay for that objective.
  • Decide whether you want to maximize for profit or for growth

You can also set objective and billing_event but neither directly impact bid_amount or your effective bid. Your actual cost is usually equal or less than bid_amount; occasionally it may be a little higher, see Billing Event.

For example, use these settings to spend about $10.00 for 1,000 daily unique views:

  • Campaign objective: APP_INSTALLS
  • Ad set optimization_goal: REACH
  • Ad set billing_event: IMPRESSIONS

However, to spend $10.00 for each app install, use these settings:

  • Campaign objective: APP_INSTALLS
  • Ad set optimization_goal: APP_INSTALLS
  • Ad set billing_event: any valid option

billing_event does not affect auction prices directly. It indirectly affects your actual spending due to Ads Delivery Pacing.

Bid Strategy

As of 3.0 you can use the bid_strategy field to provide your bid preferences. This makes it easier for you to choose a bid strategy with Marketing API. With this field you can select:

  • LOWEST_COST_WITHOUT_CAP: Facebook automatically bids on your behalf and gets you the lowest cost results. Automatically increase your effective bid as needed to get the results you want based on your given optimization_goal. If you choose Value as an optimization_goal, in Ads Manager, we display Highest Value as your bid strategy.
  • LOWEST_COST_WITH_BID_CAP: We automatically bid for you and get the lowest costs. We automatically increase your bid as needed to get the results you want, however do not surpass your specified limit.
  • TARGET_COST: We try to maintain a stable, average cost given your budget. You'll also need to provide a target cost with bid_amount field for us to maintain the same average cost as you increase your budget.
  • COST_CAP: Get the most results possible while staying within the cost per action you set. You must provide a cap number in the bid_amount field. See Cost Cap.
  • LOWEST_COST_WITH_MIN_ROAS: Specific bidding option for value optimization. You must specify a roas_average_floor, which is the minimum return wanted from ads spend. See Minimum Return on Advertiser Spend Bidding.

See the table below for more details on each strategy:

Bid StrategyCompatible ObjectivesWhen To UseConsiderations

LOWEST_COST_WITHOUT_CAP

APP_INSTALLS

CONVERSIONS

EVENT_RESPONSES

LEAD_GENERATION

LINK_CLICKS

MESSAGES

PAGE_LIKES

POST_ENGAGEMENT

PRODUCT_CATALOG_SALES

REACH

STORE_VISITS

VIDEO_VIEWS

You want to spend your full budget.


You need to understand what bid and cost to use for other bid options.


You need to spend your given budget as efficiently as possible.

No control over your cost.


Costs can rise as you exhaust least expensive opportunities or as you increase budget.

LOWEST_COST_WITH_BID_CAP

APP_INSTALLS CONVERSIONS EVENT_RESPONSES LEAD_GENERATION LINK_CLICKS MESSAGES PAGE_LIKES POST_ENGAGEMENT PRODUCT_CATALOG_SALES REACH STORE_VISITS VIDEO_VIEWS

You want to set a max bid across auctions to control cost and reach as many users as possible at that bid.

Need to spend more time managing bids to control cost.


Costs can rise as you exhaust cheaper opportunities or increase your budget.


May not spend full budget.


Bid is not the cost you’ll see in reporting.

TARGET_COST

APP_INSTALLS CONVERSIONS LEAD_GENERATION PRODUCT_CATALOG_SALES STORE_VISITS

You want to try to maintain a consistent cost.

Lose out on all cheaper results.


May not spend your entire budget.

COST_CAP

APP_INSTALLS CONVERSIONS EVENT_RESPONSES LEAD_GENERATION LINK_CLICKS MESSAGES

PAGE_LIKES POST_ENGAGEMENT PRODUCT_CATALOG_SALES VIDEO_VIEWS

You want to maximize cost-efficiency.


You need to keep cost within a specific threshold.

Cost may rise as you run out of cheapest opportunities.


Learning phase requires more aggressive exploration.


May not spend full budget once you hit the cap.

LOWEST_COST_WITH_MIN_ROAS

APP_INSTALLS

CONVERSIONS PRODUCT_CATALOG_SALES

If Return On Ad Spend is the primary measure of success, and you are able to pass back transaction values to our platform.

Specific to value optimization.


Setting the benchmark too high may lead to under-delivery.

LOWEST_COST_WITH_BID_CAP and TARGET_COST are also called manual bidding and enables you to add additional cost controls in the bid_amount field. For background, see Ads Help Center, About bid strategies: Lowest cost and Ads Help Center, About bid strategies: Target cost.

For example, create an ad set with TARGET_COST bid strategy with a target cost of $2 USD:

curl \
  -F 'name=My Ad Set' \
  -F 'optimization_goal=REACH' \
  -F 'billing_event=IMPRESSIONS' 
  -F 'bid_strategy=TARGET_COST'
  -F 'bid_amount=200' \
  -F 'daily_budget=1000' \
  -F 'campaign_id=<CAMPAIGN_ID>' \
  -F 'targeting={"geo_locations":{"countries":["US"]}}' \
  -F 'status=PAUSED' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/<VERSION>/act_<AD_ACCOUNT_ID>/adsets

To read bid_strategy from an ad set:

curl -G \
  -d 'fields=bid_strategy' \
  -d 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/<VERSION>/<AD_SET_ID>

To update an ad set's bid strategy from TARGET_COST to LOWEST_COST_WITH_BID_CAP with a bid cap of $3 USD:

curl
  -F 'bid_strategy=LOWEST_COST_WITH_BID_CAP' \
  -F 'bid_amount=300' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/<VERSION>/<AD_SET_ID>

In earlier versions of the API, you choose bidding strategy by setting is_autobid, is_average_price_pacing and bid_amount. is_autobid and is_average_price_pacing were boolean flags which indicated if you choose automatic bidding or average price bids. bid_amount set a bid cap in the case of a maximum bid or set the target average price in the case of average price bid. If you are using an earlier version of the API:

  • Auto bid - Set is_autobid to true. Do not set is_average_price_pacing to true or bid_amount.
  • Maximum bid - You must set bid_amount to a specific maximum. Do not set is_average_price_pacing and is_autobid to true.
  • Average price bid - Set is_average_price_pacing to true. You must set bid_amount to a specific target average price. Do not set is_auto_bid set to true.

This is a mapping between bid_strategy field and is_autobid and is_average_price_pacing boolean flags:

bid_strategyis_autobidis_average_price_pacing

LOWEST_COST_WITHOUT_CAP

true

false

LOWEST_COST_WITH_BID_CAP

false

false

TARGET_COST

false

true

Cost Cap

Cost cap is a cost-based bid feature that enables advertisers to express and optimize against the actual cost (CPA/CPI) of conversions. This feature allows advertisers to get the most results possible without exceeding their desired cost, allowing them to maximize cost efficiency, reducing complexities of managing bids, and helping advertisers scale more profitably and confidently.

To use cost cap:

  • billing_event must be IMPRESSIONS
  • pacing_type must be standard
  • optimization_goal must be compatible with cost cap

To use a cost cap bid strategy in campaign budget optimization, in addition to the requirements listed above, your objective should also work with cost cap. For more information about compatible objectives, see Your Guide to Facebook Bid Stategies, Cost Cap.

For example, to use a cost cap at the ad campaign level:

curl 
 -F "name"="L3 With Lifetime Budget" \
 -F "objective"="LINK_CLICKS" \
 -F "lifetime_budget=100000" \
 -F "bid_strategy"="COST_CAP" \
 -F "access_token"="ACCESS_TOKEN" \
https://graph.facebook.com/VERSION/AD_ACCOUNT_ID/campaigns

To set a cost cap at the ad set level:

curl \
  -F 'name=My Ad Set' \
  -F 'optimization_goal=CONVERSIONS' \
  -F 'billing_event=IMPRESSIONS'-F 'bid_strategy=COST_CAP'-F 'bid_amount=200' \
  -F 'daily_budget=1000' \
  -F 'campaign_id=<CAMPAIGN_ID>' \
  -F 'targeting={"geo_locations":{"countries":["US"]}}' \
  -F 'status=PAUSED' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/<VERSION>/act_<AD_ACCOUNT_ID>/adsets

Minimum Return on Advertiser Spend (Min ROAS) Bidding

This is a specific bidding option for value optimization. As such, you must already be eligible for value optimization, which has several prerequisites:

  • optimization_goal must be VALUE.
  • The account should have access to value optimization, which you can query from your ad account:

    • CAN_USE_ROAS_VALUE_OPTIMIZATION - Account is eligible to value optimization when campaign objective = “Website Conversion”
    • ADS_NEKO_MAI_ROAS - Account is eligible to value optimization when campaign objective = “App Install”
    • CAN_USE_DYNAMIC_ADS_VALUE_OPTIMIZATION - Account is eligible to value optimization when campaign objective = “Catalog Sales”
  • Min ROAS bidding uses bid_constraints to pass the “ROAS floor”, but you cannot use with bid_constraints. Instead use roas_average_floor.

API Specification on Ad Set

Notes about roas_average_floor:

  • roas_average_floor represents “the mininum roas” = “total conversion purchase value” / “total spend”; for example, “return on ads spend”
  • IMPORTANT: In the API, roas_average_floor is an integer and scaled up 10000x. So roas_average_floor = 100 means “the minimum roas” = 0.01 (or 1%), and roas_average_floor = 23300 means “the mininum roas” = 2.33 (or 233%). For example, to set minimum ROAS to be 1.5, the corresponding API spec should be bid_constraints = {"roas_average_floor": 15000}.
  • The valid range of roas_average_floor is [100, 10000000], inclusive. This means that the valid range of “minimum ROAS” is [0.01, 1000.0] or [1%, 100000.0%], inclusive.
  • Do not set bid_info or bid_amount with the minimun ROAS bidding ad set. You can only set the 'bid' of minimum ROAS through roas_average_floor in bid_constraints.
{
  "bid_strategy": "LOWEST_COST_WITH_MIN_ROAS",
  "bid_constraints": {
    "roas_average_floor": <roas_average_floor number>
  },
}

Examples

Create new minimum bidding ad set

The API call below creates a min ROAS bidding ad set, with campaign objective = “website conversion” and ROAS floor = 1.0 (or 100%).

curl \
  -F 'name=minRoasBiddingDemo' \
  -F 'daily_budget=2000' \
  -F 'optimization_goal=VALUE' \
  -F 'promoted_object={"pixel_id": "<PIXEL_ID>", "custom_event_type": "PURCHASE"}' \
  -F 'targeting={"geo_locations":{"countries":["US"]}}' \
  -F 'campaign_id=<CAMPAIGN_ID>' \
  -F 'status=PAUSED' \
  -F 'start_time=2018-12-10T12:45:26-0700' \
  *-F 'bid_strategy=LOWEST_COST_WITH_MIN_ROAS' \
  -F 'bid_constraints={"roas_average_floor": 10000}' \*
  -F 'billing_event=IMPRESSIONS' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/<VERSION>/act_<AD_ACCOUNT_ID>/adsets
Remove roas_average_floor from minimum ROAS bidding ad set
curl \
  -F bid_strategy=LOWEST_COST_WITHOUT_CAP \
  -F 'bid_constraints={}' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/<VERSION>/act_<AD_ACCOUNT_ID>/<ad set ID>
Add roas_average_floor to value optimization ad set

This example sets the minimum ROAS to 1.23 (123%):

curl \
  -F 'bid_strategy=LOWEST_COST_WITH_MIN_ROAS' \
  -F 'bid_constraints={"roas_average_floor": 12300}' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/<VERSION>/act_<AD_ACCOUNT_ID>/<ad set ID>
Change roas_average_floor for existing minimum ROAS bidding ad set

This API call changes the ad set's roas_average_floor to 2.23 (223%).

curl \
  -F 'bid_constraints={"roas_average_floor": 22300}' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/<VERSION>/act_<AD_ACCOUNT_ID>/<ad set ID>

Tracking Specs

Tracking specs help you track actions taken by users interacting with your ad. Tracking specs only track; they do not optimize ads delivery for an action or charge you based on that action.

You can use tracking specs with any bid type and creative. To specify tracking specs use the ad field, tracking_specs.

We automatically select a default tracking spec set based on your objective, but you can track additional actions. For example, a link page post ad with POST_ENGAGEMENT objective defaults to post_engagement tracking, but you setup a Facebook pixel on the offsite page and track other actions.

The default tracking spec for the page post engagement objective is action.type = post_engagement with ids for the post and page:

curl -X POST \ -F 'name="My First Ad"' \ -F 'adset_id="<AD_SET_ID>"' \ -F 'creative={ "creative_id": "<CREATIVE_ID>" }' \ -F 'tracking_specs={ "action.type": "post_engagement", "post": "<POST_ID>", "page": "<PAGE_ID>" }' \ -F 'status="PAUSED"' \ -F 'access_token=<ACCESS_TOKEN>' \ https://graph.facebook.com/v5.0/act_<AD_ACCOUNT_ID>/ads
'use strict'; const bizSdk = require('facebook-nodejs-business-sdk'); const AdAccount = bizSdk.AdAccount; const Ad = bizSdk.Ad; 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 First Ad', 'adset_id' : '<adSetID>', 'creative' : {'creative_id':'<adCreativeID>'}, 'tracking_specs' : {'action.type':'post_engagement','post':'<postID>','page':'<pageID>'}, 'status' : 'PAUSED', }; const ads = (new AdAccount(id)).createAd( fields, params ); logApiCallResult('ads api call complete.', ads);
require __DIR__ . '/vendor/autoload.php'; use FacebookAds\Object\AdAccount; use FacebookAds\Object\Ad; use FacebookAds\Api; use FacebookAds\Logger\CurlLogger; $access_token = '<ACCESS_TOKEN>'; $app_secret = '<APP_SECRET>'; $app_id = '<APP_ID>'; $id = '<AD_ACCOUNT_ID>'; $api = Api::init($app_id, $app_secret, $access_token); $api->setLogger(new CurlLogger()); $fields = array( ); $params = array( 'name' => 'My First Ad', 'adset_id' => '<adSetID>', 'creative' => array('creative_id' => '<adCreativeID>'), 'tracking_specs' => array('action.type' => 'post_engagement','post' => '<postID>','page' => '<pageID>'), 'status' => 'PAUSED', ); echo json_encode((new AdAccount($id))->createAd( $fields, $params )->exportAllData(), JSON_PRETTY_PRINT);
from facebook_business.adobjects.adaccount import AdAccount from facebook_business.adobjects.ad import Ad 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 First Ad', 'adset_id': '<adSetID>', 'creative': {'creative_id':'<adCreativeID>'}, 'tracking_specs': {'action.type':'post_engagement','post':'<postID>','page':'<pageID>'}, 'status': 'PAUSED', } print AdAccount(id).create_ad( 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).createAd() .setName(\"My First Ad\") .setAdsetId(<adSetID>L) .setCreative( new AdCreative() .setFieldId(\"<adCreativeID>\") ) .setTrackingSpecs(\"{\\"action.type\\":\\"post_engagement\\",\\"post\\":\\"<postID>\\",\\"page\\":\\"<pageID>\\"}\") .setStatus(Ad.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) ads = ad_account.ads.create({ name: 'My First Ad', adset_id: '<adSetID>', creative: {'creative_id':'<adCreativeID>'}, tracking_specs: {'action.type':'post_engagement','post':'<postID>','page':'<pageID>'}, status: 'PAUSED', })

For custom tracking specs, see Tracking Specs, Custom.

FAQ

Most actions in an ad, including link clicks, app installs, video viewing over a certain period, tag photo, like, comment, share, and so on.