Cost Per Actions (CPA) allows you to specify conversion events and get charged by the amount of conversions. CPA for video views is also called CPV.
An alternative to CPA is oCPM , which charges per impressions served.
Your bid is defined for an ad set . These fields must follow the restrictions below:
Name | Description |
---|---|
|
Defines the action you pay on. Set to |
|
Defines the action you optimize for. Set to same value as your |
|
Value you place on the objective, specified in cents, minimum 1 cent. For example, |
|
For those ads which optimize for connections including |
Starting on v9
, CPA billing for app ads is deprecated, you cannot set both billing event and optimization goal to APP_INSTALLS
. Instead, we recommend using the impression
billing events. You can still specify APP_INSTALLS
under billing_event
or optimization_goal
, but not both at the same time.
See ad set document on allowed updates to ad sets.
The example below creates a CPA bidded ad set. Note that for CPA ad sets, you must set a promoted_object
.
curl -X POST \
-F 'name="A CPA Ad Set"' \
-F 'campaign_id="<AD_CAMPAIGN_ID>"' \
-F 'daily_budget=5000' \
-F 'start_time="2024-06-09T21:13:43-0700"' \
-F 'end_time="2024-06-16T21:13:43-0700"' \
-F 'billing_event="IMPRESSIONS"' \
-F 'optimization_goal="REACH"' \
-F 'bid_amount=1000' \
-F 'promoted_object={
"page_id": "<PAGE_ID>"
}' \
-F 'targeting={
"facebook_positions": [
"feed"
],
"geo_locations": {
"countries": [
"US"
]
}
}' \
-F 'user_os="iOS"' \
-F 'publisher_platforms="facebook"' \
-F 'device_platforms="mobile"' \
-F 'access_token=<ACCESS_TOKEN>' \
https://graph.facebook.com/v20.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' : 'A CPA Ad Set',
'campaign_id' : '<adCampaignLinkClicksID>',
'daily_budget' : '5000',
'start_time' : '2024-05-20T15:32:55-0700',
'end_time' : '2024-05-27T15:32:55-0700',
'billing_event' : 'IMPRESSIONS',
'optimization_goal' : 'REACH',
'bid_amount' : '1000',
'promoted_object' : {'page_id':'<pageID>'},
'targeting' : {'facebook_positions':['feed'],'geo_locations':{'countries':['US']}},
'user_os' : 'iOS',
'publisher_platforms' : 'facebook',
'device_platforms' : 'mobile',
};
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' => 'A CPA Ad Set',
'campaign_id' => '<adCampaignLinkClicksID>',
'daily_budget' => '5000',
'start_time' => '2024-05-20T15:32:55-0700',
'end_time' => '2024-05-27T15:32:55-0700',
'billing_event' => 'IMPRESSIONS',
'optimization_goal' => 'REACH',
'bid_amount' => '1000',
'promoted_object' => array('page_id' => '<pageID>'),
'targeting' => array('facebook_positions' => array('feed'),'geo_locations' => array('countries' => array('US'))),
'user_os' => 'iOS',
'publisher_platforms' => 'facebook',
'device_platforms' => 'mobile',
);
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': 'A CPA Ad Set',
'campaign_id': '<adCampaignLinkClicksID>',
'daily_budget': '5000',
'start_time': '2024-05-20T15:32:55-0700',
'end_time': '2024-05-27T15:32:55-0700',
'billing_event': 'IMPRESSIONS',
'optimization_goal': 'REACH',
'bid_amount': '1000',
'promoted_object': {'page_id':'<pageID>'},
'targeting': {'facebook_positions':['feed'],'geo_locations':{'countries':['US']}},
'user_os': 'iOS',
'publisher_platforms': 'facebook',
'device_platforms': 'mobile',
}
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(\"A CPA Ad Set\")
.setCampaignId(\"<adCampaignLinkClicksID>\")
.setDailyBudget(5000L)
.setStartTime(\"2024-05-20T15:32:55-0700\")
.setEndTime(\"2024-05-27T15:32:55-0700\")
.setBillingEvent(AdSet.EnumBillingEvent.VALUE_IMPRESSIONS)
.setOptimizationGoal(AdSet.EnumOptimizationGoal.VALUE_REACH)
.setBidAmount(1000L)
.setPromotedObject(\"{\\"page_id\\":\\"<pageID>\\"}\")
.setTargeting(
new Targeting()
.setFieldFacebookPositions(Arrays.asList(\"feed\"))
.setFieldGeoLocations(
new TargetingGeoLocation()
.setFieldCountries(Arrays.asList(\"US\"))
)
)
.setParam(\"user_os\", \"iOS\")
.setParam(\"publisher_platforms\", \"facebook\")
.setParam(\"device_platforms\", \"mobile\")
.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: 'A CPA Ad Set',
campaign_id: '<adCampaignLinkClicksID>',
daily_budget: '5000',
start_time: '2024-05-20T15:32:55-0700',
end_time: '2024-05-27T15:32:55-0700',
billing_event: 'IMPRESSIONS',
optimization_goal: 'REACH',
bid_amount: '1000',
promoted_object: {'page_id':'<pageID>'},
targeting: {'facebook_positions':['feed'],'geo_locations':{'countries':['US']}},
user_os: 'iOS',
publisher_platforms: 'facebook',
device_platforms: 'mobile',
})
After that, you can create ads and put them into this ad set following the creation flow here .
Change the bid to a CPA ad set:
curl -X POST \
-F 'billing_event="IMPRESSIONS"' \
-F 'optimization_goal="LINK_CLICKS"' \
-F 'bid_amount=200' \
-F 'targeting={
"geo_locations": {
"countries": [
"US"
]
},
"facebook_positions": [
"feed"
]
}' \
-F 'access_token=<ACCESS_TOKEN>' \
https://graph.facebook.com/v20.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 = {
'billing_event' : 'IMPRESSIONS',
'optimization_goal' : 'LINK_CLICKS',
'bid_amount' : '200',
'targeting' : {'geo_locations':{'countries':['US']},'facebook_positions':['feed']},
};
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(
'billing_event' => 'IMPRESSIONS',
'optimization_goal' => 'LINK_CLICKS',
'bid_amount' => '200',
'targeting' => array('geo_locations' => array('countries' => array('US')),'facebook_positions' => array('feed')),
);
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 = {
'billing_event': 'IMPRESSIONS',
'optimization_goal': 'LINK_CLICKS',
'bid_amount': '200',
'targeting': {'geo_locations':{'countries':['US']},'facebook_positions':['feed']},
}
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()
.setBillingEvent(AdSet.EnumBillingEvent.VALUE_IMPRESSIONS)
.setOptimizationGoal(AdSet.EnumOptimizationGoal.VALUE_LINK_CLICKS)
.setBidAmount(200L)
.setTargeting(
new Targeting()
.setFieldFacebookPositions(Arrays.asList(\"feed\"))
.setFieldGeoLocations(
new TargetingGeoLocation()
.setFieldCountries(Arrays.asList(\"US\"))
)
)
.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.billing_event = 'IMPRESSIONS'ad_set.optimization_goal = 'LINK_CLICKS'ad_set.bid_amount = '200'ad_set.targeting = {'geo_locations':{'countries':['US']},'facebook_positions':['feed']}
ad_set.save
To create an ad bidding CPV, or CPA for video views, first create an ad campaign with objective=VIDEO_VIEWS
.
curl -X POST \
-F 'name="Video Views campaign"' \
-F 'objective="OUTCOME_ENGAGEMENT"' \
-F 'status="PAUSED"' \
-F 'special_ad_categories=[]' \
-F 'access_token=<ACCESS_TOKEN>' \
https://graph.facebook.com/v19.0/act_<AD_ACCOUNT_ID>/campaigns
'use strict';
const bizSdk = require('facebook-nodejs-business-sdk');
const AdAccount = bizSdk.AdAccount;
const Campaign = bizSdk.Campaign;
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' : 'Video Views campaign',
'objective' : 'OUTCOME_ENGAGEMENT',
'status' : 'PAUSED',
'special_ad_categories' : [],
};
const campaigns = (new AdAccount(id)).createCampaign(
fields,
params
);
logApiCallResult('campaigns api call complete.', campaigns);
require __DIR__ . '/vendor/autoload.php';
use FacebookAds\Object\AdAccount;
use FacebookAds\Object\Campaign;
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' => 'Video Views campaign',
'objective' => 'OUTCOME_ENGAGEMENT',
'status' => 'PAUSED',
'special_ad_categories' => array(),
);
echo json_encode((new AdAccount($id))->createCampaign(
$fields,
$params
)->exportAllData(), JSON_PRETTY_PRINT);
from facebook_business.adobjects.adaccount import AdAccount
from facebook_business.adobjects.campaign import Campaign
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': 'Video Views campaign',
'objective': 'OUTCOME_ENGAGEMENT',
'status': 'PAUSED',
'special_ad_categories': [],
}
print AdAccount(id).create_campaign(
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).createCampaign()
.setName(\"Video Views campaign\")
.setObjective(Campaign.EnumObjective.VALUE_OUTCOME_ENGAGEMENT)
.setStatus(Campaign.EnumStatus.VALUE_PAUSED)
.setParam(\"special_ad_categories\", \"[]\")
.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)
campaigns = ad_account.campaigns.create({
name: 'Video Views campaign',
objective: 'OUTCOME_ENGAGEMENT',
status: 'PAUSED',
special_ad_categories: [],
})
Then, set the CPA for video views bid_info
at the ad set:
use FacebookAds\Object\AdSet;
use FacebookAds\Object\Fields\AdSetFields;
use FacebookAds\Object\Fields\TargetingFields;
use FacebookAds\Object\Targeting;
use FacebookAds\Object\Values\AdSetBillingEventValues;
use FacebookAds\Object\Values\AdSetOptimizationGoalValues;
$adset = new AdSet(null, 'act_<AD_ACCOUNT_ID>');
$adset->setData(array(
AdSetFields::NAME => 'A CPV Ad Set',
AdSetFields::CAMPAIGN_ID => <CAMPAIGN_ID>,
AdSetFields::DAILY_BUDGET => 500,
AdSetFields::START_TIME =>
(new \DateTime("+1 week"))->format(\DateTime::ISO8601),
AdSetFields::END_TIME =>
(new \DateTime("+2 week"))->format(\DateTime::ISO8601),
AdSetFields::BILLING_EVENT => AdSetBillingEventValues::VIDEO_VIEWS,
AdSetFields::OPTIMIZATION_GOAL => AdSetOptimizationGoalValues::VIDEO_VIEWS,
AdSetFields::BID_AMOUNT => 100,
AdSetFields::TARGETING => (new Targeting())->setData(array(
TargetingFields::GEO_LOCATIONS => array(
'countries' => array(
'US',
),
),
TargetingFields::PUBLISHER_PLATFORMS => array('facebook'),
TargetingFields::DEVICE_PLATFORMS => array('mobile'),
)),
));
$adset->create(array(
AdSet::STATUS_PARAM_NAME => AdSet::STATUS_PAUSED,
));
import time
from facebookads.adobjects.adset import AdSet
adset = AdSet(parent_id='act_<AD_ACCOUNT_ID>')
adset.update({
AdSet.Field.name: 'A CPV Ad Set',
AdSet.Field.campaign_id: <CAMPAIGN_ID>,
AdSet.Field.daily_budget: 500,
AdSet.Field.start_time: int(time.time()),
AdSet.Field.end_time: int(time.time() + 100000),
AdSet.Field.optimization_goal: AdSet.OptimizationGoal.video_views,
AdSet.Field.billing_event: AdSet.BillingEvent.video_views,
AdSet.Field.bid_amount: 100,
AdSet.Field.targeting: {
'geo_locations': {
'countries': ['US'],
},
Targeting.Field.publisher_platforms: ['facebook'],
Targeting.Field.device_platforms: ['mobile'],
},
})
adset.remote_create(params={
'status': AdSet.Status.paused,
})
AdSet adSet = new AdAccount(act_<AD_ACCOUNT_ID>, context).createAdSet()
.setName("A CPV Ad Set")
.setCampaignId(<CAMPAIGN_ID>)
.setDailyBudget(500L)
.setStartTime(start_time)
.setEndTime(end_time)
.setBillingEvent(AdSet.EnumBillingEvent.VALUE_VIDEO_VIEWS)
.setOptimizationGoal(AdSet.EnumOptimizationGoal.VALUE_VIDEO_VIEWS)
.setBidAmount(100L)
.setTargeting(
new Targeting()
.setFieldDevicePlatforms(Arrays.asList(Targeting.EnumDevicePlatforms.VALUE_MOBILE))
.setFieldGeoLocations(
new TargetingGeoLocation()
.setFieldCountries(Arrays.asList("US"))
)
.setFieldPublisherPlatforms(Arrays.asList("facebook"))
)
.setStatus(AdSet.EnumStatus.VALUE_PAUSED)
.execute();
String ad_set_id = adSet.getId();
curl \
-F 'name=A CPV Ad Set' \
-F 'campaign_id=<CAMPAIGN_ID>' \
-F 'daily_budget=500' \
-F 'start_time=2018-02-06T04:45:29+0000' \
-F 'end_time=2018-02-13T04:45:29+0000' \
-F 'billing_event=VIDEO_VIEWS' \
-F 'optimization_goal=VIDEO_VIEWS' \
-F 'bid_amount=100' \
-F 'targeting={
"device_platforms": ["mobile"],
"geo_locations": {"countries":["US"]},
"publisher_platforms": ["facebook"]
}' \
-F 'status=PAUSED' \
-F 'access_token=<ACCESS_TOKEN>' \
https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/adsets