8

I've read a lot about facebook ads and stuff, using GUI it allow to do what I'm doing and for some reason on sdk it doesn't.

I get this suberror code on Facebook ads sdk subcode 1487930.

The message says:

You Must Select an Object to Promote, the user message says: Your campaign must > include an ad set with a selected object to promote related to your objective > > (ex: Page, URL, event). Please update your ad set to continue.

Response returns no fields to blame and error happens when creative is being created: $creative->create();

I setup my adset like this:

    use Facebook;
    use FacebookAds\Api;
    use FacebookAds\Object;
    use Facebook\Exceptions;

        $inventory = new Models\AdvertisingInventory();
        $item = $inventory->getListing($id)->getAttributes();
        $item['properties'] = json_decode($item['properties'], true);

        /**
         * Step 1 Instantiate an API
         *
         * @link https://developers.facebook.com/docs/marketing-api/sdks#init-sdk
         */

        try {
            Api::init($this->app_id, $this->app_secret, $this->access_token);
        } catch (\Exception $e) {
            return $this->AdvertisingRenderErrorMessage($e);
        }

        /**
         * Step 2 Query to create campaign
         * @var $campaign
         * @link https://developers.facebook.com/docs/marketing-api/reference/ad-campaign-group
         *
         * TODO: Implement ad image widget sizing: https://www.facebook.com/business/help/103816146375741
         */
        try {

            $account = new Object\AdAccount($this->current_facebook_ads_account);

            $campaign = new Object\Campaign(null, $this->current_facebook_ads_account); // Getting AdAccount instance

            $ad_campaigns = $account->getCampaigns($campaign::getFields())->getArrayCopy(); // Checks of there are any campaigns already created

            $current_campaign = null;

            if (!empty($ad_campaigns)) {
                foreach ($ad_campaigns as $ad_campaign) { // loops through campaigns
                    $campaign_data = $ad_campaign->exportAllData();
                    if ($campaign_data['name'] == 'Sell old inventory') { // If campaign name matches the name given to new campaign, created campaign is then used
                        $current_campaign = $ad_campaign;
                    }
                }
            }

            if (!is_null($current_campaign)) { // Checks if campaign is already assigned if yes, then its used.
                $campaign = $current_campaign;
            } else { // else new one is created
                $campaign->setData(array(
                    Object\Fields\CampaignFields::NAME => 'Sell old inventory',
                    Object\Fields\CampaignFields::OBJECTIVE => Object\Values\CampaignObjectiveValues::LINK_CLICKS,
                ));

                $campaign->validate()->create(array(
                    Object\Campaign::STATUS_PARAM_NAME => Object\Campaign::STATUS_PAUSED
                ));
            }

            //$campaignData = $campaign->getData();

            echo 'Campaign ID: ' . $campaign->id . " <br>\n";

        } catch (\Exception $e) {
            return $this->AdvertisingRenderErrorMessage($e);
        }

        /**
         * Step 3 Search for targeting topic
         * @var $targeting
         * @link https://developers.facebook.com/docs/marketing-api/targeting-specs/v2.7
         */
        try {
            $results = Object\TargetingSearch::search(
                Object\Search\TargetingSearchTypes::INTEREST,
                null,
                'Automobiles');

            $target = (count($results)) ? $results->current() : null;

            //if (!is_null($target)) {

            echo "Using target: " . $target->name . "<br/>";

            $targeting = new Object\Targeting();
            $targeting->{Object\Fields\TargetingFields::GEO_LOCATIONS} = array(
                'countries' => array('NZ')
            );
            $targeting->{Object\Fields\TargetingFields::INTERESTS} = array(
                array(
                    'id' => $target->id,
                    'name' => $target->name,
                ),
            );
            //}
        } catch (\Exception $e) {
            return $this->AdvertisingRenderErrorMessage($e);
        }

        /**
         * Step 4 Create an AdSet
         * @var $adset
         * @link https://developers.facebook.com/docs/marketing-api/reference/ad-campaign
         */
        try {

            $adset = new Object\AdSet(null, $this->current_facebook_ads_account);
            //$fields = $adset::getFields();

            $available_adsets = $campaign->getAdSets(array(Object\Fields\AdSetFields::NAME,Object\Fields\AdSetFields::ID));

            $current_adset = null;

            if (!empty($available_adsets)) {
                foreach ($available_adsets as $ad_set) { // loops through adsets
                    if ($adset->name == $item['title']) { // If adset name matches the name given to new campaign, created campaign is then used
                        $current_adset = $ad_set;
                    }
                }
            }

            if (!is_null($current_adset)) {
                $adset = $current_adset;
                /*$adset->read(array(
                    Object\Fields\AdSetFields::PROMOTED_OBJECT,
                    Object\Fields\AdSetFields::NAME
                ));
                echo $adset->name."<br>";
                echo $adset->promoted_object."<br>";*/
            } else {

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


                $adset->setData(array(
                    Object\Fields\AdSetFields::NAME => $item['title'],
                    Object\Fields\AdSetFields::OPTIMIZATION_GOAL => Object\Values\AdSetOptimizationGoalValues::LINK_CLICKS,
                    Object\Fields\AdSetFields::BILLING_EVENT => Object\Values\AdSetBillingEventValues::LINK_CLICKS,
                    Object\Fields\AdSetFields::BID_AMOUNT => 100,
                    Object\Fields\AdSetFields::DAILY_BUDGET => 500,
                    Object\Fields\AdSetFields::CAMPAIGN_ID => $campaign->id,
                    Object\Fields\AdSetFields::TARGETING => $targeting,
                    Object\Fields\AdSetFields::START_TIME => $start_time,
                    Object\Fields\AdSetFields::END_TIME => $end_time,
                    Object\Fields\AdSetFields::PROMOTED_OBJECT => (object) array(
                        Object\Fields\AdPromotedObjectFields::PAGE_ID => '178698438995498',
                    )
                ));
                $adset->create(array(
                    Object\AdSet::STATUS_PARAM_NAME => Object\AdSet::STATUS_PAUSED,
                ));
            }
            echo 'Adset ID: ' . $adset->id . " <br>\n";
        } catch (\Exception $e) {
            return $this->AdvertisingRenderErrorMessage($e);
        }


        //New method
        /**
         * Step 5 Create an AdImage
         * @var $image
         * @link https://developers.facebook.com/docs/marketing-api/reference/ad-image
         */
        try {
            $image = new Object\AdImage(null, $this->current_facebook_ads_account); // Invokes images preparation for Facebook ad instance
            $target_path = __DIR__ . '/assets/temp/'; // path where images will be streamed to

            if (!file_exists($target_path)) {
                mkdir($target_path, 0755); // creating path if one doesn't exist
            }

            $files_in_dir = array_diff(scandir($target_path), array('..', '.')); // checking for existing files in target directory
            $size = getimagesize($item['properties']['images_large'][0]); // getting image details
            $extension = image_type_to_extension($size[2]); // getting image extension from type
            $target_file_name = preg_replace(['/\./', '/\\s/', '/\\t/'], "_", strtolower($item['title'])) . $extension; // creating proper file name
            $target_file = $target_path . $target_file_name; // setting full target directory

            if (array_search($target_file_name, $files_in_dir) === false) { // checking if target file already exists

                $image_file = file_get_contents($item['properties']['images_large'][0]);

                file_put_contents($target_file, $image_file);
            }

            $image->{Object\Fields\AdImageFields::FILENAME} = $target_file; // Using target file as ad image

            $image->create();

            echo 'Image Hash: ' . $image->hash . " <br>\n";
        } catch (\Exception $e) {
            return $this->AdvertisingRenderErrorMessage($e);
        }

        /**
         * Step 6 Create an AdCreative
         */
        try {

            $creative = new Object\AdCreative(null, $this->current_facebook_ads_account);

            $available_creatives = $adset->getAdCreatives($creative::getFields());

            $current_creative = null;

            if (!empty($available_creatives)) {
                foreach ($available_creatives as $creative) { // loops through adsets
                    if ($creative->name == 'Creative of '.$item['title']) { // If adset name matches the name given to new campaign, created campaign is then used
                        $current_creative = $creative;
                    }
                }
            }

            if (!is_null($current_creative)) {
                $creative = $current_creative;
            } else {

                $creative = new Object\AdCreative(null, $this->current_facebook_ads_account);
                $creative->setData(array(
                    Object\Fields\AdCreativeFields::NAME => 'Creative of '.$item['title'],
                    Object\Fields\AdCreativeFields::TITLE => $item['title'],
                    Object\Fields\AdCreativeFields::BODY => $item['properties']['description'],
                    Object\Fields\AdCreativeFields::IMAGE_HASH => $image->hash,
                    Object\Fields\AdCreativeFields::LINK_URL => ipConfig()->get('globalPortalUrl'),
                    Object\Fields\AdCreativeFields::OBJECT_URL => ipConfig()->get('globalPortalUrl'),
                ));
                **$creative->create();**
            }
            echo 'Creative ID: ' . $creative->id . " <br>\n";
        } catch (\Exception $e) {
            return $this->AdvertisingRenderErrorMessage($e);
        }


        /**
         * Step 7 Create an Ad
         *
         * Then, use the image hash returned from above. Finally, create your ad along with ad creative.
         * Please note that the ad creative is not created independently, rather its data structure
         * is appended to the ad group
         *
         * @link https://developers.facebook.com/docs/marketing-api/reference/adgroup
         */
        try {

            $ad = new Object\Ad(null, $this->current_facebook_ads_account);

            $last_ad = $adset->getAds($ad::getFields())->end()->exportData();

            //var_dump($last_ad); exit();

            $ad->setData(array(
                Object\Fields\AdFields::NAME => $item['title'].' #1',
                Object\Fields\AdFields::ADSET_ID => $adset->id,
                Object\Fields\AdFields::CREATIVE => array('creative_id' => $creative->id),
            ));
            $ad->create(array(
                Object\Ad::STATUS_PARAM_NAME => Object\Ad::STATUS_PAUSED,
            ));
            echo 'Ad ID:' . $ad->id . " <br>\n";

        } catch (\Exception $e) {
            return $this->AdvertisingRenderErrorMessage($e);

        }

I assigned that page to my business account and that app which the query goes through as well the user is the owner of business account, the app and the page.

What else does it need if the the page id is provided? The Campaign objective is:

Object\Fields\CampaignFields::OBJECTIVE => Object\Values\CampaignObjectiveValues::LINK_CLICKS

I use valid page_id. I'm I missing some extra data for the (FYI tried this without (object) typehint):

Object\Fields\AdSetFields::PROMOTED_OBJECT => (object) array(
    Object\Fields\AdPromotedObjectFields::PAGE_ID => '178698438995498',
)

Or there are problems with app, page and business account settings?

Please someone answer my calls. Tried almost everything can't pass this point. Any other promoted objects do not work with the campaign objective.

P.S. Someone with reputation more then 1500 please create ne facebook-php-ads-sdk tag.

Alex M
  • 2,756
  • 7
  • 29
  • 35
juslintek
  • 441
  • 3
  • 12
  • 1
    did you find a solution to this? – aks Sep 14 '16 at 10:34
  • Yeah, but I don't remember it, I think it was because of invalid constant set as param on image, I have a working code. If you need pm me. :-) P.S. If you're planning to do constant automated advertising then talk to google for business account or something, they will raise limitations to the account. But I will try to see whats different now then it was before tomorrow, because I'm really busy now. – juslintek Dec 02 '16 at 20:11

3 Answers3

2

I was having this error because I was using the wrong parameter name when creating an Adcreative. I was using page_id instead of object_id.

Hope it can help someone.

Alex M
  • 2,756
  • 7
  • 29
  • 35
Éric Bergeron
  • 620
  • 6
  • 7
1

I don't think promoted object is required for LINK_CLICKS objective. Have you tried not setting it at all?

Facebook docs for ad set, section Creating, field promoted_object says

Required with certain campaign objectives

and the LINK_CLICKS objective is not listed there.


Alternatively you can create an ad with desired parameters through FB interface (ads manager or power editor) and then read back its values through API to see what fields are filled and what values were used.

David
  • 1,426
  • 17
  • 25
  • I'm using LINK_CLICKS objective and i'm seeing the same "Your campaign must include an ad set with a selected object to promote related to your objective (ex: Page, URL, event). Please update your ad set to continue.." when POSTing my new ad to /ads. – Kirby Jun 17 '17 at 21:06
0

You need to make sure that your campaign objective is in line with your adsetoptimization goal. I had the same problem when I tried Campaign objective: LINK_CLICKS and AdsetOptimizationGoal: REACH. Makes sense that this wouldn't work.

Here is the code I got working:

Campaign create:

$fields = [];
$params = [
        'name' => 'My campaign_3',
        'objective' => 'LINK_CLICKS',
        'status' => 'PAUSED',
    ];

    $cmpId = null;
    try {
        $cmpId = $campaign = (new AdAccount('act_' . $this->adAccountId))->createCampaign(
            $fields,
            $params
        );
    } catch (Exception $e) {
        dump('Exception with message: ' . $e->getMessage());
        dump($e->getResponse());
    }

Adset create:

$adset = new AdSet(null, 'act_301136867381876');
$adset->setData(array(
        AdSetFields::NAME => 'My Ad Set',
        AdSetFields::OPTIMIZATION_GOAL => AdSetOptimizationGoalValues::LINK_CLICKS,
        AdSetFields::BILLING_EVENT => AdSetBillingEventValues::IMPRESSIONS,
        AdSetFields::BID_AMOUNT => 10,
        AdSetFields::DAILY_BUDGET => 100,
        AdSetFields::CAMPAIGN_ID => $cmpId,
        AdSetFields::TARGETING => $targeting,
        AdSetFields::START_TIME => $start_time->format(DateTime::ISO8601),
        AdSetFields::END_TIME => $end_time->format(DateTime::ISO8601),
        AdSetFields::DESTINATION_TYPE => 'WEBSITE'
    ));
Stormnorm
  • 171
  • 4
  • 11