Get Started

Create your first ad with the Marketing API by following these steps.

Before You Start

You should get familiar with the Graph API and Facebook's Ad Campaign Structure. Once you are ready to start making calls, you need:

After that, you can get started. Don't forget to check general best practices for using the Marketing API.

Step 1: Create a Campaign

Start the process creating a new campaign object from the class Campaign. At this stage, you need to set an objective for your ads, which is the overall goal of your campaign. We recommend that you create a PAUSED campaign initially, so you do not get billed while testing.

curl -X POST \ -F 'name="My campaign"' \ -F 'objective="LINK_CLICKS"' \ -F 'status="PAUSED"' \ -F 'special_ad_categories=[]' \ -F 'access_token=<ACCESS_TOKEN>' \ https://graph.facebook.com/v8.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' : 'My campaign', 'objective' : 'LINK_CLICKS', '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' => 'My campaign', 'objective' => 'LINK_CLICKS', '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': 'My campaign', 'objective': 'LINK_CLICKS', '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(\"My campaign\") .setObjective(Campaign.EnumObjective.VALUE_LINK_CLICKS) .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: 'My campaign', objective: 'LINK_CLICKS', status: 'PAUSED', special_ad_categories: [], })

To verify your campaign has been created, you can check it in the ads manager.

Resources:

Step 2: Define Targeting

Before moving to create your ad sets, you need to define your target audience. In the next step, you create an ad set and specify your audience's attributes.

First, use our targeting search to look for predefined values used to set up your audience. In the following example, we are looking for interests:

use FacebookAds\Object\TargetingSearch;
use FacebookAds\Object\Search\TargetingSearchTypes;

$result = TargetingSearch::search(
  TargetingSearchTypes::INTEREST,
  null,
  'baseball');
from facebookads.adobjects.targetingsearch import TargetingSearch
params = {
    'q': 'baseball',
    'type': 'adinterest',
}

resp = TargetingSearch.search(params=params)
print(resp)
curl -G \
  -d 'type=adinterest' \
  -d 'q=baseball' \
  -d 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/search

Based on the interests received above, we create a sample targeting spec:

use FacebookAds\Object\Targeting;
use FacebookAds\Object\Fields\TargetingFields;

$targeting = new Targeting();
$targeting->{TargetingFields::GEO_LOCATIONS} =
  array(
    'countries' => array('US')
  );
$targeting->{TargetingFields::INTERESTS} = <INTERESTS>;
from facebookads.adobjects.targeting import Targeting

targeting = {
    Targeting.Field.geo_locations: {
        Targeting.Field.countries: ['US'],
    },
    Targeting.Field.interests: <INTERESTS>,
}

Step 3: Create Ad Set and Define Budget, Billing, Optimization, and Duration

An ad set is a group of ads that share the same daily or lifetime budget, schedule, billing, optimization, and targeting data.

At this stage, you need to create a new object from the class AdSet and specify:

  • Duration: How long your ads will run. Set it using start_time and end_time.
  • Budget: How much money you want to spend. Use daily_budget or lifetime_budget.
  • Optimization: What result you want to achieve with your ad. Set up using optimization_goal.
  • Billing: How you want to pay. Use billing_event.
  • Bid: What value you place on the occurrence of your optimization event. Use the bid_amount field.

We recommend the creation of an ad set with the PAUSED status to avoid charges during your test.

use DateTime;
use FacebookAds\Object\AdSet;
use FacebookAds\Object\Fields\AdSetFields;
use FacebookAds\Object\Values\AdSetBillingEventValues;
use FacebookAds\Object\Values\AdSetOptimizationGoalValues;

$start_time = (new \DateTime("+1 week"))->format(DateTime::ISO8601);
$end_time = (new \DateTime("+2 week"))->format(DateTime::ISO8601);

$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 => <TARGETING>,
  AdSetFields::START_TIME => $start_time,
  AdSetFields::END_TIME => $end_time,
));
$adset->create(array(
  AdSet::STATUS_PARAM_NAME => AdSet::STATUS_PAUSED,
));
import datetime
from facebookads.adobjects.adset import AdSet

today = datetime.date.today()
start_time = str(today + datetime.timedelta(weeks=1))
end_time = str(today + datetime.timedelta(weeks=2))

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>,
    AdSet.Field.start_time: start_time,
    AdSet.Field.end_time: end_time,
})

adset.remote_create(params={
    'status': AdSet.Status.paused,
})
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"))
      )
  )
  .setStartTime(start_time)
  .setEndTime(end_time)
  .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 'start_time=2018-02-06T04:45:17+0000' \
  -F 'end_time=2018-02-13T04:45:17+0000' \
  -F 'status=PAUSED' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/adsets

Step 4: Provide Ad Creative

Reference Docs

Use AdCreative to provide the visual elements of your ad. The information you need to provide in AdCreative depends on the objective. Common attributes are:

  • One or more uploaded images or videos
  • Set title, description, and so on
  • Link your ad to a Facebook Page
  • Add a "Call to Action" button

Depending on your objective you may have to provide advanced fields. For example, ads for an iOS app require an app store URL. With the objective "website clicks", you need to provide a link to your website.

Example

This example shows how to provide an image and create the AdCreative object.

First, create an AdImage from an image file:

use FacebookAds\Object\AdImage;
use FacebookAds\Object\Fields\AdImageFields;

$image = new AdImage(null, 'act_<AD_ACCOUNT_ID>');
$image->{AdImageFields::FILENAME} = '<IMAGE_PATH>';

$image->create();
echo 'Image Hash: '.$image->{AdImageFields::HASH}.PHP_EOL;
from facebookads.adobjects.adimage import AdImage

image = AdImage(parent_id='act_<AD_ACCOUNT_ID>')
image[AdImage.Field.filename] = '<IMAGE_PATH>'
image.remote_create()

# Output image Hash
print(image[AdImage.Field.hash])
AdImage adImage = new AdAccount(act_<AD_ACCOUNT_ID>, context).createAdImage()
  .addUploadFile("filename", new File(<IMAGE_PATH>))
  .execute();
curl \
  -F 'filename=@<IMAGE_PATH>' \
  -F 'access_token=<ACCESS_TOKEN>' \
  https://graph.facebook.com/v2.11/act_<AD_ACCOUNT_ID>/adimages

Then, use the image hash to create the AdCreative:

curl -X POST \ -F 'name="Sample Creative"' \ -F 'object_story_spec={ "page_id": "<PAGE_ID>", "link_data": { "image_hash": "<IMAGE_HASH>", "link": "https://facebook.com/<PAGE_ID>", "message": "try it out" } }' \ -F 'access_token=<ACCESS_TOKEN>' \ https://graph.facebook.com/v8.0/act_<AD_ACCOUNT_ID>/adcreatives
'use strict'; const bizSdk = require('facebook-nodejs-business-sdk'); const AdAccount = bizSdk.AdAccount; const AdCreative = bizSdk.AdCreative; 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' : 'Sample Creative', 'object_story_spec' : {'page_id':'<pageID>','link_data':{'image_hash':'<imageHash>','link':'https:\/\/facebook.com\/<pageID>','message':'try it out'}}, }; const adcreatives = (new AdAccount(id)).createAdCreative( fields, params ); logApiCallResult('adcreatives api call complete.', adcreatives);
require __DIR__ . '/vendor/autoload.php'; use FacebookAds\Object\AdAccount; use FacebookAds\Object\AdCreative; 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' => 'Sample Creative', 'object_story_spec' => array('page_id' => '<pageID>','link_data' => array('image_hash' => '<imageHash>','link' => 'https:\/\/facebook.com\/<pageID>','message' => 'try it out')), ); echo json_encode((new AdAccount($id))->createAdCreative( $fields, $params )->exportAllData(), JSON_PRETTY_PRINT);
from facebook_business.adobjects.adaccount import AdAccount from facebook_business.adobjects.adcreative import AdCreative 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': 'Sample Creative', 'object_story_spec': {'page_id':'<pageID>','link_data':{'image_hash':'<imageHash>','link':'https:\/\/facebook.com\/<pageID>','message':'try it out'}}, } print AdAccount(id).create_ad_creative( 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).createAdCreative() .setName(\"Sample Creative\") .setObjectStorySpec( new AdCreativeObjectStorySpec() .setFieldLinkData( new AdCreativeLinkData() .setFieldImageHash(\"<imageHash>\") .setFieldLink(\"https://facebook.com/<pageID>\") .setFieldMessage(\"try it out\") ) .setFieldPageId(\"<pageID>\") ) .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) adcreatives = ad_account.adcreatives.create({ name: 'Sample Creative', object_story_spec: {'page_id':'<pageID>','link_data':{'image_hash':'<imageHash>','link':'https:\/\/facebook.com\/<pageID>','message':'try it out'}}, })

Verify your image upload by going to your Image Library inside ads manager.

At this point, the AdCreative with your link is not yet visible in Ads Manager. You see this data once you book your ad. You can debug your ad creative with Graph API Explorer:

GET /{my-creative-id} HTTP/1.1
Host: graph.facebook.com

Step 5: Schedule Delivery

Finally, create your Ad object to link your AdCreative and AdSet. Set the status of your Ad to paused to avoid placing an order instantly.

curl -X POST \ -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/v8.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 Ad', 'adset_id' : '<adSetID>', 'creative' : {'creative_id':'<adCreativeID>'}, '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 Ad', 'adset_id' => '<adSetID>', 'creative' => array('creative_id' => '<adCreativeID>'), '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 Ad', 'adset_id': '<adSetID>', 'creative': {'creative_id':'<adCreativeID>'}, '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 Ad\") .setAdsetId(<adSetID>L) .setCreative( new AdCreative() .setFieldId(\"<adCreativeID>\") ) .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 Ad', adset_id: '<adSetID>', creative: {'creative_id':'<adCreativeID>'}, status: 'PAUSED', })

Verify that your ad exists in the ads manager. Click on the campaign you just created, then on the ad set, and on the ad.

Once you're comfortable booking ads with the API, set the status to active. First, the ad goes through ad review, and has the status PENDING_REVIEW. Once the review is done, it goes back to the status of ACTIVE.