This guide assumes you have an app that has been whitelisted for the Facebook Ads API, that you have a fully working development environment with all required dependencies and that are ready to start coding. If you haven't done this, please see the README file.
We also assume you are somewhat familiar with namespaces in PHP. If not, we recommend you take some time to read the namespace basics in the PHP Manual.
You should also have the documentation for the Facebook Marketing APIs available as you will need to refer to this to understand which combination of parameters are required for the different object types.
The classes within the Facebook Ads SDK are designed to be included using an autoloader compliant with the PSR-4. If you are using Composer to include dependencies, you will find an implementation available within the vendor folder. This guide assumes you are using this autoloader.
<?php
define('VENDOR_DIR', '/path/to/sdk/'); // Path to the Vendor directory
$loader = include VENDOR_DIR.'/vendor/autoload.php';
To make any request to the Ads API, you will need to have a valid access token and the user has accepted the ads_management
permission.
The FacebookAds\Api
object is the basis of the Ads SDK which encapsulates a FacebookAds\Session
and is used to execute requests against the Graph API.
An easy to use init method is provided:
use FacebookAds\Api;
// Set the default application to be used with this session and register an instance of the Api object
Api::init('<APP_ID>', '<APP_SECRET>', '<ACCESS_TOKEN>');
// The instace is now retrivable
$api = Api::instance();
Generally you should not need to make requests to the Graph API directly as these calls are handled by the implementation of objects within the SDK. However, there may be some case where you do want to query the Graph directly. In this case, you can use the call
method of the Api
class which returns a FacebookAds\Http\RequestInterface
, by default the registered class is FacebookAds\Http\Request
:
$response = $api->call(
'/61405622',
Api::HTTP_METHOD_GET,
array('fields'=>'name',)
);
var_dump($response->getContent());
The first time an Api
object is instantiated, we store a static reference to that object within the Api
class and this is used as the default instance within the SDK. This saves you from having to pass around a reference to an Api
instance within your application.
A common requirement amongst Facebook Ads API developers however is to be able to handle multiple sessions within a single script execution. For example, you may have a process which syncs updated objects for multiple app users into some local datastore.
To enable this, we provide two ways to manage sessions.
The first is by mutating the default instance used by the application. The default instance can be accessed using the method Api::instance()
. You can also change the default instance using the static method Api::setInstance($api)
.
The second is to explicitly define the Api
instance you want to use when querying the Graph. This is achieved by passing an instance to the constructor of any class that extends from Object\AbstractCrudObject
.
use FacebookAds\Object\AdGroup;
$my_adgroup = new AdGroup($id, $parent_id=null, $api);
For any entity that can be directly queried from the Graph API we have provided classes which extend Object\AbstractCrudObject
. This provides create
, read
, update
and delete
methods for the majority of these entities. However, in some cases the Graph API does not support all of these operations and you will receive an \Exception
if you attempt to call an unsupported method.
When setting class variables on an object of this type we perform some basic validation to ensure the field is a valid field and an \Exception
will be thrown if a field name is not found within the field definition for that class.
There is another set of entities which cannot be directly queried from the Graph such as an AdPreview
. This type of object extends Object\AbstractObject
which provides methods to access the response data.
For each object type, we provide a class enumerating the available fields of that object. These can be found within the FacebookAds\Object\Fields
namespace and provide a way to reference fields without using strings. You can alternatively use strings if you find this easier.
For example, you can set the data of an object using the field definitions in the following way:
$someObject->setData(array(
MyObjectFields::ID => 1234,
MyObjectFields::NAME => 'My Name',
));
Alternatively, you can use the string equivalent:
$someObject->setData(array(
'id'=>1234,
'name'=>'My Name',
));
Similarly the same applies for direct assignation:
//Using field definitions:
$someObject->{SomeObjectFields::ID} = 123;
//Equivalent to using the variable name directly:
$someObject->id = 123;
###The Cursor Class
When requesting multiple objects from the Graph, responses may be returned in pages of data which can be traversed using cursors. We encapsulate this information into a Cursor
class which represents the set of objects in the current page along with information about how to access subsequent pages of objects. This class implements the \Iterable
and \Countable
interfaces.
##Reading Objects
###Reading a single object
To read an object from the Graph you will need its id
. By default, only the id
field of an object is queried and you should specify when reading an object the fields you need. It is not recommended that you request all fields unless you require them all.
use FacebookAds\Object\AdAccount;
use FacebookAds\Object\Fields\AdAccountFields;
$required_fields = array(
AdAccountFields::ID,
AdAccountFields::NAME,
AdAccountFields::DAILY_SPEND_LIMIT,
);
$adaccount = (new AdAccount($id))->read($required_fields);
See Defining Default Fields within the section about Extending the SDK for an example of how to avoid defining the fields you require every request.
###Reading multiple objects
We provide the static method readIds($ids = array(...), $fields = array(...))
to enable you to request many objects of a single type and will return a Cursor
:
use FacebookAds\Object\AdAccount;
use FacebookAds\Object\Fields\AdAccountFields;
$required_fields = array(
AdAccountFields::ID,
AdAccountFields::NAME,
AdAccountFields::DAILY_SPEND_LIMIT,
);
$account_ids = array('act_x', 'act_y'...)
$adaccounts = AdAccount::readIds($account_ids, $required_fields);
foreach($adaccounts as $account) {
echo $account->id."\n";
}
##Creating Objects
When creating objects on the Graph, they are generally created by making a POST request to an edge of a parent object. For example, AdGroups are created using the endpoint https://graph.facebook.com/act_123123/adgroups
. Therefore when creating an object, you must know the id
of the parent object which is generally the id of an AdAccount. You should consult the Facebook Developer Documentation to see which parent object to use.
use FacebookAds\Object\AdGroup;
use FacebookAds\Object\Fields\AdGroupFields;
$account_id = 'act_123123';
$adgroup = new AdGroup($id=null, $account_id);
$adgroup->setData(array(
AdGroupFields::NAME => 'My Test AdGroup',
AdSetFields::CAMPAIGN_GROUP_ID => $campaign_group_id,
AdSetFields::CAMPAIGN_STATUS => AdSet::STATUS_PAUSED,
AdSetFields::DAILY_BUDGET => '150',
AdSetFields::START_TIME => (new \DateTime("+1 week"))->format(\DateTime::ISO8601),
AdSetFields::END_TIME => (new \DateTime("+2 week"))->format(\DateTime::ISO8601),
));
$adgroup->create();
echo $adgroup->id;
##Updating Objects
When you mutate an AdObject, we record which variables have changed and make it easy for you to write these change to the Graph API by calling the update
method.
Please note that in some cases the variable name used to update an attribute of an entity differs from the one read from Graph API. Any variable you change will be included in the request to update an object an you will likely receive an \Exception
if the field name is incorrect. Please consult the Facebook Developer Documentation to see which fields are required.
use FacebookAds\Object\AdGroup;
use FacebookAds\Object\Fields\AdGroupFields;
$adgroup = new AdGroup($id);
$adgroup->name = 'Updated Name';
$adgroup->update();
To delete an object, you only need call the delete
method on an instance of that object. Note, you do not have had to have read the object from the Graph API, all you need is the id
of the object.
use FacebookAds\Object\AdGroup;
use FacebookAds\Object\Fields\AdGroupFields;
$adgroup = new AdGroup($id);
$adgroup->delete();
###Deleting multiple objects
We provide the static method deleteIds($ids = array(...))
to enable you to delete many objects at the same time. This method returns a boolean value and will only return true
if all objects were successfully deleted. A return value of false
means one or more failed to be deleted. Please also note that we do not verify the type of the id
you have passed into this function.
use FacebookAds\Object\AdGroup;
$status = AdGroup::deleteIds($ids = array(...));
On object that extends AbstractCrudObject
you can call the save
method which will call create
if they object does not have a value for id
set, or will call update
a value is present.
Objects on the Graph API may also have connections. A connection provides a way to retrieve objects which relate to the current object, for example, you can retrieve all of the AdGroups relative to an AdAccount using the URL https://graph.facebook.com/act_123123/adgroups
.
For each connection an object has, we provide a helper method to retrieve its related objects. In the case of ObjectObject\AdAccount
we provide several of these methods including getAdgroups($required_fields)
which will return a Cursor
containing a page of Object\AdGroup
objects.
use FacebookAds\Object\AdAccount;
$account = new AdAccount($id);
$adgroups = $account->getAdgroups($fields = array('name')));
foreach($adgroups as $adgroup) {
echo $adgroup->name."\n";
}
You only need the id
of the object on which you want to call a connection method, therefore you do not need to have read the object from the Graph API first.
For cases where these helper methods are not available, see Requesting Connections Without Helper Methods.
Facebook's targeting can generally be broken down into interests, demographics, behaviors and geo targeting. Many of these need to be queried from the Graph API search endpoint.
To query targeting using the Ads SDK, you can use the Object\TargetingSearch
class.
This set of examples will walk you through:
- Reading AdAccounts for a user
- Creating an AdCampaign
- Searching targeting criteria
- Creating an AdSet
- Creating an AdImage
- Creating an AdCreative
- Creating an AdGroup
Examples can be found within the examples/
folder of the SDK. This assumes you have bootstrap code with an access token:
<?php
define('SDK_DIR', '/path/to/sdk/'); // Path to the SDK directory
$loader = include SDK_DIR.'/vendor/autoload.php';
use FacebookAds\Api;
Api::init($app_id, $app_secret, $access_token);
The FacebookSession
contains the id
of the user who has the active session and this can be used to read their AdAccount
connections.
use FacebookAds\Object\AdUser;
use FacebookAds\Object\Fields\AdUserFields;
use FacebookAds\Object\AdAccount;
use FacebookAds\Object\Fields\AdAccountFields;
$user = new AdUser('me');
$user->read(array(AdUserFields::ID));
$accounts = $user->getAdAccounts(array(
AdAccountFields::ID,
AdAccountFields::NAME,
));
// Print out the accounts
echo "Accounts:\n";
foreach($accounts as $account) {
echo $account->id . ' - ' .$account->name."\n";
}
// Grab the first account for next steps (you should probably choose one)
$account = (count($accounts)) ? $accounts->getObjects()[0] : null;
echo "\nUsing this account: ";
echo $account->id."\n";
Now we have an AdAccount
for the current user we can go ahead an create our AdCampaign. All AdGroups
within your AdCampaign
should have the same objective. You can find the available objectives within the AdObjectives
class.
In the following example we create a paused campaign so your ads do not go live, however you can omit the status field if you want your ad to run.
use FacebookAds\Object\AdCampaign;
use FacebookAds\Object\Fields\AdCampaignFields;
use FacebookAds\Object\Values\AdObjectives;
use FacebookAds\Object\Values\AdBuyingTypes;
$campaign = new AdCampaign(null, $account->id);
$campaign->setData(array(
AdCampaignFields::NAME => 'My First Campaign',
AdCampaignFields::OBJECTIVE => AdObjectives::WEBSITE_CLICKS,
AdCampaignFields::STATUS => AdCampaign::STATUS_PAUSED,
));
$campaign->create();
echo "Campaign ID:" . $campaign->id . "\n";
The final thing we need before creating an AdGroup
is some targeting. Many attributes of targeting can be found defined in the developer documentation, however some categories need you to search, such as interests. For this, we provide the TargetingSearch
class.
use FacebookAds\Object\TargetingSearch;
use FacebookAds\Object\Search\TargetingSearchTypes;
$results = TargetingSearch::search(
$type = TargetingSearchTypes::INTEREST,
$class = null,
$query = 'facebook london'
);
// we'll take the top result for now
$target = (count($results)) ? $results->getObjects()[0] : null;
echo "Using target: ".$target->name."\n";
Targeting for the moment is expressed in the form of a multidimensional array:
$targeting = array(
'geo_locations' => array(
'countries' => array('GB'),
),
'interests' => array(
array(
'id' => $target->id,
'name'=>$target->name
)
)
);
An AdSet
is a set of AdGroup
objects and it is best practice to ensure all AdGroup
objects within an AdSet
have the same targeting.
The AdSet
holds the attributes about the duration of a campaign and the budget. When deciding a budget, you should also choose between lifetime_budget
and daily_budget
.
use FacebookAds\Object\AdSet;
use FacebookAds\Object\Fields\AdSetFields;
use FacebookAds\Object\Values\BidTypes;
$adset = new AdSet(null, $account->id);
$adset->setData(array(
AdSetFields::NAME => 'My First AdSet',
AdSetFields::CAMPAIGN_GROUP_ID => $campaign->id,
AdSetFields::CAMPAIGN_STATUS => AdSet::STATUS_ACTIVE,
AdSetFields::DAILY_BUDGET => '150',
AdSetFields::BID_TYPE => BidTypes::BID_TYPE_CPM;
AdSetFields::TARGETING => $targeting,
AdSetFields::START_TIME =>
(new \DateTime("+1 week"))->format(\DateTime::ISO8601),
AdSetFields::END_TIME =>
(new \DateTime("+2 week"))->format(\DateTime::ISO8601),
));
$adset->create();
echo 'AdSet ID: '. $adset->id . "\n";
Now you have a AdSet
, you will be able to create an AdGroup
, however, first you will need to upload the image you want to use as part of the AdCreative
.
use FacebookAds\Object\AdImage;
use FacebookAds\Object\Fields\AdImageFields;
$image = new AdImage(null, $account->id);
$image->filename = SDK_DIR.'/test/misc/FB-f-Logo__blue_512.png';
$image->create();
echo 'Image Hash: '.$image->hash . "\n";
You can create an AdCreative
in two ways. The first is by including a JSON object when creating an AdGroup
and the second, which we will demonstrate here, is by explicitly creation an AdCreative
and using its id
when creating an AdGroup
.
use FacebookAds\Object\AdCreative;
use FacebookAds\Object\Fields\AdCreativeFields;
$creative = new AdCreative(null, $account->id);
$creative->setData(array(
AdCreativeFields::NAME => 'Sample Creative',
AdCreativeFields::TITLE => 'Welcome to the Jungle',
AdCreativeFields::BODY => 'We\'ve got fun \'n\' games',
AdCreativeFields::IMAGE_HASH => $image->hash,
AdCreativeFields::OBJECT_URL => 'http://www.example.com/',
));
$creative->create();
echo 'Creative ID: '.$creative->id . "\n";
The final step is to create the AdGroup
. The AdGroup
contains all of the information about bid, creative and targeting. It should also have the asme objective as the AdCampaign
we created.
use FacebookAds\Object\AdGroup;
use FacebookAds\Object\Fields\AdGroupFields;
use FacebookAds\Object\Fields\AdGroupBidInfoFields;
$adgroup = new AdGroup(null, $account->id);
$adgroup->setData(array(
AdGroupFields::CREATIVE =>
array('creative_id' => $creative->id),
AdGroupFields::NAME => 'My First AdGroup',
AdGroupFields::BID_INFO =>
array(AdGroupBidInfoFields::IMPRESSIONS => '2'),
AdGroupFields::CAMPAIGN_ID => $adset->id,
));
$adgroup->create();
echo 'AdGroup ID:' . $adgroup->id . "\n";
There are many scenarios in which you may want to extend the SDK, and when developing this SDK we attempted to balance extensibility with ease of use for new developers.
We noted earlier that by default no fields are requested when calling the read
method of a class implementing AbstractCrudObject
, however if you always require the same set of fields throughout your application we have provided a simple way to do this.
Within your own namespace, you can extend the any class implementing AbstractCrudObject
and override the static variable $defaultReadFields
to be an array of fields you want to be read by default. You should try to not change the classes in the SDK directly as this may break forward compatibly.
namespace MyNamespace\Object;
use FacebookAds\Object\Fields\AdAccountFields;
class AdAccount extends FacebookAds\Object\AdAccount {
protected static $defaultReadFields = array(
AdAccountFields::ID,
AdAccountFields::NAME,
AdAccountFields::DAILY_SPEND_LIMIT,
AdAccountFields::CURRENCY,
);
}
Within your application, whenever you use an AdAccount
, you should use the one within your namespace instead of the FacebookAds
one.
use MyNamespace\Object\AdAccount;
$adaccount = (new AdAccount($id))->read();
echo $adaccount->name;
As detailed in the Connections section, we provide helper methods to request objects relative to an object. However, in some cases these methods may not have been implemented, or if you have extended our based objects as in the example of defining default fields to read, calling a connection helper method on a base object will return objects of the \FacebookAds namespace type.
In this case, you can use our generic connection methods to retrieve the correct type of object for any class extending AbstractCrudObject
. To enable this, we provide two methods, getOneByConnection
and getManyByConnection
or which the latter is the most commonly used.
use FacebookAds\Object\AdAccount;
// AdGroup in your namespace which you have used to extend the
// FacebookAds\Object\AdGroup class
use MyNamespace\Object\AdGroup;
$account = new AdAccount($id);
$my_adaccount_objects = $account->getManyByConnection(
AdGroup::className(), $fields = array(...), $params = array(...));