On Oct 7th , we released the new version (v2.5) of our Marketing API. With the release of this API, we also released an updated version of our PHP and Python SDKs. Here are some of the salient features of this version, which we want to highlight for all the developers using our SDKs.
Other important feature changes to the SDK include:
status
is available only as a parameter while ad object creation and update. There are two additional fields called configured_status
and effective_status
which can be used while reading./stats
endpoint has been deprecated and the v2.5 SDK versions do not support these any more.All the breaking changes introduced by v2.5 are detailed in v2.5 changelog. The requisite updates per these breaking changes have been made in the latest version of our PHP and Python SDKs.
From the Marketing API stand point the following changes are in effect:
In the Python SDK, the following changes are important to note:
These changes also propagate in the fields and the methods:
Old Naming | New Naming |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
In the PHP SDK, these changes are reflected a bit differently:
Old Naming | New Naming |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Since these changes affect all the core ad objects in the API, they also transiently affect all the CRUD operations performed on these objects. Here is a code snippet which goes through each step involved in creating a new ad using v2.5.
Please note that 'none' is not a valid objective type starting v2.5.
use FacebookAds\Object\Campaign;
use FacebookAds\Object\Fields\CampaignFields;
use FacebookAds\Object\Values\CampaignObjectiveValues;
$campaign = new Campaign(null, 'act_<AD_ACCOUNT_ID>');
$campaign->setData(array(
CampaignFields::NAME => 'My campaign',
CampaignFields::OBJECTIVE => CampaignObjectiveValues::LINK_CLICKS,
));
$campaign->create(array(
Campaign::STATUS_PARAM_NAME => Campaign::STATUS_PAUSED,
));
from facebookads.adobjects.campaign import Campaign
campaign = Campaign(parent_id='act_<AD_ACCOUNT_ID>')
campaign.update({
Campaign.Field.name: 'My Campaign',
Campaign.Field.objective: Campaign.Objective.link_clicks,
})
campaign.remote_create(params={
'status': Campaign.Status.paused,
})
Campaign campaign = new AdAccount(act_<AD_ACCOUNT_ID>, context).createCampaign()
.setName("My campaign")
.setObjective(Campaign.EnumObjective.VALUE_LINK_CLICKS)
.setStatus(Campaign.EnumStatus.VALUE_PAUSED)
.execute();
String campaign_id = campaign.getId();
curl \
-F 'name=My campaign' \
-F 'objective=LINK_CLICKS' \
-F 'status=PAUSED' \
-F 'access_token=<ACCESS_TOKEN>' \
https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/campaigns
Once, the campaogn creation is complete, use the campaign_id
generated to create an adset.
use FacebookAds\Object\AdSet;
use FacebookAds\Object\Fields\AdSetFields;
use FacebookAds\Object\Fields\TargetingFields;
use FacebookAds\Object\Values\AdSetBillingEventValues;
use FacebookAds\Object\Targeting;
use FacebookAds\Object\Values\AdSetOptimizationGoalValues;
$adset = new AdSet(null, 'act_<AD_ACCOUNT_ID>');
$adset->setData(array(
AdSetFields::NAME => 'My Ad Set',
AdSetFields::OPTIMIZATION_GOAL => AdSetOptimizationGoalValues::REACH,
AdSetFields::BILLING_EVENT => AdSetBillingEventValues::IMPRESSIONS,
AdSetFields::BID_AMOUNT => 2,
AdSetFields::DAILY_BUDGET => 1000,
AdSetFields::CAMPAIGN_ID => <CAMPAIGN_ID>,
AdSetFields::TARGETING => (new Targeting())->setData(array(
TargetingFields::GEO_LOCATIONS => array(
'countries' => array('US'),
),
)),
));
$adset->create(array(
AdSet::STATUS_PARAM_NAME => AdSet::STATUS_PAUSED,
));
from facebookads.adobjects.adset import AdSet
from facebookads.adobjects.targeting import Targeting
adset = AdSet(parent_id='act_<AD_ACCOUNT_ID>')
adset.update({
AdSet.Field.name: 'My Ad Set',
AdSet.Field.campaign_id: <CAMPAIGN_ID>,
AdSet.Field.daily_budget: 1000,
AdSet.Field.billing_event: AdSet.BillingEvent.impressions,
AdSet.Field.optimization_goal: AdSet.OptimizationGoal.reach,
AdSet.Field.bid_amount: 2,
AdSet.Field.targeting: {
Targeting.Field.geo_locations: {
'countries': ['US'],
},
},
})
adset.remote_create(params={
'status': AdSet.Status.paused,
})
print(adset)
AdSet adSet = new AdAccount(act_<AD_ACCOUNT_ID>, context).createAdSet()
.setName("My Ad Set")
.setOptimizationGoal(AdSet.EnumOptimizationGoal.VALUE_REACH)
.setBillingEvent(AdSet.EnumBillingEvent.VALUE_IMPRESSIONS)
.setBidAmount(2L)
.setDailyBudget(1000L)
.setCampaignId(<CAMPAIGN_ID>)
.setTargeting(
new Targeting()
.setFieldGeoLocations(
new TargetingGeoLocation()
.setFieldCountries(Arrays.asList("US"))
)
)
.setStatus(AdSet.EnumStatus.VALUE_PAUSED)
.execute();
String ad_set_id = adSet.getId();
curl \
-F 'name=My Ad Set' \
-F 'optimization_goal=REACH' \
-F 'billing_event=IMPRESSIONS' \
-F 'bid_amount=2' \
-F 'daily_budget=1000' \
-F 'campaign_id=<CAMPAIGN_ID>' \
-F 'targeting={"geo_locations":{"countries":["US"]}}' \
-F 'status=PAUSED' \
-F 'access_token=<ACCESS_TOKEN>' \
https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/adsets
The ad creative object is not affected by the change to the naming structure and therefore this step remains same as before. Here is how you can create a simple creative using the SDKs.
from facebookads.objects import AdCreative, Adimage
from facebookads.specs import ObjectStorySpec, LinkData
# After ad set creation
image = AdImage(parent_id='act_<AD_ACCOUNT_ID>')
image[AdImage.Field.filename] = './my-image.jpg'
image.remote_create()
image_hash = image[AdImage.Field.hash]
# Add Link to your creative
link_data = LinkData()
link_data[LinkData.Field.message] = 'try it out'
link_data[LinkData.Field.link] = '<URL>'
link_data[LinkData.Field.caption] = 'My caption'
link_data[LinkData.Field.image_hash] = image_hash
object_story_spec = ObjectStorySpec()
object_story_spec[ObjectStorySpec.Field.page_id] = <PAGE_ID>
object_story_spec[ObjectStorySpec.Field.link_data] = link_data
creative = AdCreative(parent_id=my_account.get_id_assured())
creative[AdCreative.Field.name] = 'Sample Creative'
creative[AdCreative.Field.object_story_spec] = object_story_spec
creative.remote_create()
This final step of the ad creation flow is to create the ad using the adset_id
and the creative_id
that were generated in step 2 and step 3.
use FacebookAds\Object\Ad;
use FacebookAds\Object\Fields\AdFields;
$data = array(
AdFields::NAME => 'My Ad',
AdFields::ADSET_ID => <AD_SET_ID>,
AdFields::CREATIVE => array(
'creative_id' => <CREATIVE_ID>,
),
);
$ad = new Ad(null, 'act_<AD_ACCOUNT_ID>');
$ad->setData($data);
$ad->create(array(
Ad::STATUS_PARAM_NAME => Ad::STATUS_PAUSED,
));
from facebookads.adobjects.ad import Ad
ad = Ad(parent_id='act_<AD_ACCOUNT_ID>')
ad[Ad.Field.name] = 'My Ad'
ad[Ad.Field.adset_id] = <AD_SET_ID>
ad[Ad.Field.creative] = {
'creative_id': <CREATIVE_ID>,
}
ad.remote_create(params={
'status': Ad.Status.paused,
})
Ad ad = new AdAccount(act_<AD_ACCOUNT_ID>, context).createAd()
.setName("My Ad")
.setAdsetId(<AD_SET_ID>)
.setCreative(
new AdCreative()
.setFieldId(<CREATIVE_ID>)
)
.setStatus(Ad.EnumStatus.VALUE_PAUSED)
.execute();
ad_account = FacebookAds::AdAccount.get('act_<AD_ACCOUNT_ID>')
ad = ad_account.ads.create({
name: 'My Ad',
adset_id: <ADSET_ID>,
creative: {
creative_id: <CREATIVE_ID>,
},
status: 'PAUSED',
})
curl \
-F 'name=My Ad' \
-F 'adset_id=<AD_SET_ID>' \
-F 'creative={"creative_id":"<CREATIVE_ID>"}' \
-F 'status=PAUSED' \
-F 'access_token=<ACCESS_TOKEN>' \
https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/ads
This step completes the basic ad creation flow. For more SDK examples, visit our Marketing API docs.