The AdWords API will sunset on April 27, 2022. Migrate to the Google Ads API to take advantage of the latest Google Ads features.

Campaign Management Samples

The code samples below provide examples for managing campaigns using the AdWords API. Client Library.

Add a campaign group and set its performance target

<?php
/**
 * Copyright 2017 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace Google\AdsApi\Examples\AdWords\v201809\CampaignManagement;

require __DIR__ . '/../../../../vendor/autoload.php';

use Google\AdsApi\AdWords\AdWordsServices;
use Google\AdsApi\AdWords\AdWordsSession;
use Google\AdsApi\AdWords\AdWordsSessionBuilder;
use Google\AdsApi\AdWords\v201809\cm\Campaign;
use Google\AdsApi\AdWords\v201809\cm\CampaignGroup;
use Google\AdsApi\AdWords\v201809\cm\CampaignGroupOperation;
use Google\AdsApi\AdWords\v201809\cm\CampaignGroupPerformanceTarget;
use Google\AdsApi\AdWords\v201809\cm\CampaignGroupPerformanceTargetOperation;
use Google\AdsApi\AdWords\v201809\cm\CampaignGroupPerformanceTargetService;
use Google\AdsApi\AdWords\v201809\cm\CampaignGroupService;
use Google\AdsApi\AdWords\v201809\cm\CampaignOperation;
use Google\AdsApi\AdWords\v201809\cm\CampaignService;
use Google\AdsApi\AdWords\v201809\cm\EfficiencyTargetType;
use Google\AdsApi\AdWords\v201809\cm\Money;
use Google\AdsApi\AdWords\v201809\cm\Operator;
use Google\AdsApi\AdWords\v201809\cm\PerformanceTarget;
use Google\AdsApi\AdWords\v201809\cm\SpendTargetType;
use Google\AdsApi\AdWords\v201809\cm\VolumeGoalType;
use Google\AdsApi\Common\OAuth2TokenBuilder;

/**
 * This code example adds a campaign group and sets a performance target for
 * that group. To get campaigns, run GetCampaigns.php. To download reports, run
 * DownloadCriteriaReportWithAwql.php.
 */
class AddCampaignGroupsAndPerformanceTargets
{

    const CAMPAIGN_ID_1 = 'INSERT_CAMPAIGN_ID_1_HERE';
    const CAMPAIGN_ID_2 = 'INSERT_CAMPAIGN_ID_2_HERE';

    public static function runExample(
        AdWordsServices $adWordsServices,
        AdWordsSession $session,
        $campaignIds
    ) {
        $campaignGroup = self::createCampaignGroup($adWordsServices, $session);
        self::addCampaignsToGroup(
            $adWordsServices,
            $session,
            $campaignGroup,
            $campaignIds
        );
        self::createPerformanceTarget($adWordsServices, $session, $campaignGroup);
    }

    private static function createCampaignGroup(
        AdWordsServices $adWordsServices,
        AdWordsSession $session
    ) {
        $campaignGroupService = $adWordsServices->get($session, CampaignGroupService::class);

        // Create the campaign group.
        $campaignGroup = new CampaignGroup();
        $campaignGroup->setName('Mars campaign group #' . uniqid());

        // Create the operation.
        $operation = new CampaignGroupOperation();
        $operation->setOperand($campaignGroup);
        $operation->setOperator(Operator::ADD);

        $campaignGroup = $campaignGroupService->mutate([$operation])->getValue()[0];
        printf(
            "Campaign group with ID %d and name '%s' was created.\n",
            $campaignGroup->getId(),
            $campaignGroup->getName()
        );

        return $campaignGroup;
    }

    private static function addCampaignsToGroup(
        AdWordsServices $adWordsServices,
        AdWordsSession $session,
        $campaignGroup,
        $campaignIds
    ) {
        $campaignService = $adWordsServices->get($session, CampaignService::class);

        $operations = [];
        foreach ($campaignIds as $campaignId) {
            $campaign = new Campaign();
            $campaign->setId($campaignId);
            $campaign->setCampaignGroupId($campaignGroup->getId());

            $operation = new CampaignOperation();
            $operation->setOperand($campaign);
            $operation->setOperator(Operator::SET);
            $operations[] = $operation;
        }

        $campaigns = $campaignService->mutate($operations)->getValue();
        printf(
            "The following campaign IDs were added to the campaign group with ID %d:\n",
            $campaignGroup->getId()
        );
        foreach ($campaigns as $campaign) {
            printf("\t%d\n", $campaign->getId());
        }
    }

    private static function createPerformanceTarget(
        AdWordsServices $adWordsServices,
        AdWordsSession $session,
        CampaignGroup $campaignGroup
    ) {
        $campaignGroupPerformanceTargetService = $adWordsServices->get(
            $session,
            CampaignGroupPerformanceTargetService::class
        );

        // Create the performance target.
        $performanceTarget = new PerformanceTarget();
        // Keep the CPC for the campaigns < $3.
        $performanceTarget->setEfficiencyTargetType(
            EfficiencyTargetType::CPC_LESS_THAN_OR_EQUAL_TO
        );
        $performanceTarget->setEfficiencyTargetValue(3000000);

        // Keep the maximum spend under $50.
        $performanceTarget->setSpendTargetType(SpendTargetType::MAXIMUM);
        $maxSpend = new Money();
        $maxSpend->setMicroAmount(500000000);
        $performanceTarget->setSpendTarget($maxSpend);

        // Aim for at least 3000 clicks.
        $performanceTarget->setVolumeTargetValue(3000);
        $performanceTarget->setVolumeGoalType(VolumeGoalType::MAXIMIZE_CLICKS);

        // Start the performance target today, and run it for the next 90 days.
        $startDate = date('Ymd', strtotime('now'));
        $endDate = date('Ymd', strtotime('+90 day'));

        $performanceTarget->setStartDate($startDate);
        $performanceTarget->setEndDate($endDate);

        // Create the campaign group performance target.
        $campaignGroupPerformanceTarget = new CampaignGroupPerformanceTarget();
        $campaignGroupPerformanceTarget->setCampaignGroupId(
            $campaignGroup->getId()
        );
        $campaignGroupPerformanceTarget->setPerformanceTarget($performanceTarget);

        // Create the operation.
        $operation = new CampaignGroupPerformanceTargetOperation();
        $operation->setOperand($campaignGroupPerformanceTarget);
        $operation->setOperator(Operator::ADD);

        $campaignGroupPerformanceTarget = $campaignGroupPerformanceTargetService->mutate([$operation])->getValue()[0];

        // Display the results.
        printf(
            "Campaign group performance target with ID %d was added for campaign group ID %d.\n",
            $campaignGroupPerformanceTarget->getId(),
            $campaignGroupPerformanceTarget->getCampaignGroupId()
        );
    }


    public static function main()
    {
        // Generate a refreshable OAuth2 credential for authentication.
        $oAuth2Credential = (new OAuth2TokenBuilder())->fromFile()->build();

        // Construct an API session configured from a properties file and the
        // OAuth2 credentials above.
        $session = (new AdWordsSessionBuilder())->fromFile()->withOAuth2Credential($oAuth2Credential)->build();
        self::runExample(
            new AdWordsServices(),
            $session,
            [intval(self::CAMPAIGN_ID_1), intval(self::CAMPAIGN_ID_2)]
        );
    }
}

AddCampaignGroupsAndPerformanceTargets::main();

Add a label to multiple campaigns

<?php
/**
 * Copyright 2017 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace Google\AdsApi\Examples\AdWords\v201809\CampaignManagement;

require __DIR__ . '/../../../../vendor/autoload.php';

use Google\AdsApi\AdWords\AdWordsServices;
use Google\AdsApi\AdWords\AdWordsSession;
use Google\AdsApi\AdWords\AdWordsSessionBuilder;
use Google\AdsApi\AdWords\v201809\cm\CampaignLabel;
use Google\AdsApi\AdWords\v201809\cm\CampaignLabelOperation;
use Google\AdsApi\AdWords\v201809\cm\CampaignService;
use Google\AdsApi\AdWords\v201809\cm\Operator;
use Google\AdsApi\Common\OAuth2TokenBuilder;

/**
 * This example adds a label to multiple campaigns.
 */
class AddCampaignLabels
{

    const CAMPAIGN_ID_1 = 'INSERT_CAMPAIGN_ID_1_HERE';
    const CAMPAIGN_ID_2 = 'INSERT_CAMPAIGN_ID_2_HERE';
    const LABEL_ID = 'INSERT_LABEL_ID_HERE';

    public static function runExample(
        AdWordsServices $adWordsServices,
        AdWordsSession $session,
        array $campaignIds,
        $labelId
    ) {
        $campaignService = $adWordsServices->get($session, CampaignService::class);

        // Create campaign labels and campaign label operations, and add the
        // operations to the list.
        $operations = [];
        foreach ($campaignIds as $campaignId) {
            $campaignLabel = new CampaignLabel();
            $campaignLabel->setCampaignId($campaignId);
            $campaignLabel->setLabelId($labelId);

            $operation = new CampaignLabelOperation();
            $operation->setOperand($campaignLabel);
            $operation->setOperator(Operator::ADD);

            $operations[] = $operation;
        }

        // Add campaign labels on the server and print out some information for
        // each created campaign label.
        $result = $campaignService->mutateLabel($operations);
        foreach ($result->getValue() as $campaignLabel) {
            printf(
                "Campaign label for campaign ID %d and label ID %d was added.\n",
                $campaignLabel->getCampaignId(),
                $campaignLabel->getLabelId()
            );
        }
    }

    public static function main()
    {
        // Generate a refreshable OAuth2 credential for authentication.
        $oAuth2Credential = (new OAuth2TokenBuilder())->fromFile()->build();

        // Construct an API session configured from a properties file and the
        // OAuth2 credentials above.
        $session = (new AdWordsSessionBuilder())->fromFile()->withOAuth2Credential($oAuth2Credential)->build();
        self::runExample(
            new AdWordsServices(),
            $session,
            [intval(self::CAMPAIGN_ID_1), intval(self::CAMPAIGN_ID_2)],
            intval(self::LABEL_ID)
        );
    }
}

AddCampaignLabels::main();

Add a campaign using BatchJobService

<?php
/**
 * Copyright 2017 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace Google\AdsApi\Examples\AdWords\v201809\CampaignManagement;

require __DIR__ . '/../../../../vendor/autoload.php';

use Google\AdsApi\AdWords\AdWordsServices;
use Google\AdsApi\AdWords\AdWordsSession;
use Google\AdsApi\AdWords\AdWordsSessionBuilder;
use Google\AdsApi\AdWords\BatchJobs\v201809\BatchJobs;
use Google\AdsApi\AdWords\v201809\cm\AdGroup;
use Google\AdsApi\AdWords\v201809\cm\AdGroupAd;
use Google\AdsApi\AdWords\v201809\cm\AdGroupAdOperation;
use Google\AdsApi\AdWords\v201809\cm\AdGroupCriterionOperation;
use Google\AdsApi\AdWords\v201809\cm\AdGroupOperation;
use Google\AdsApi\AdWords\v201809\cm\AdvertisingChannelType;
use Google\AdsApi\AdWords\v201809\cm\BatchJob;
use Google\AdsApi\AdWords\v201809\cm\BatchJobOperation;
use Google\AdsApi\AdWords\v201809\cm\BatchJobService;
use Google\AdsApi\AdWords\v201809\cm\BatchJobStatus;
use Google\AdsApi\AdWords\v201809\cm\BiddableAdGroupCriterion;
use Google\AdsApi\AdWords\v201809\cm\BiddingStrategyConfiguration;
use Google\AdsApi\AdWords\v201809\cm\BiddingStrategyType;
use Google\AdsApi\AdWords\v201809\cm\Budget;
use Google\AdsApi\AdWords\v201809\cm\BudgetBudgetDeliveryMethod;
use Google\AdsApi\AdWords\v201809\cm\BudgetOperation;
use Google\AdsApi\AdWords\v201809\cm\Campaign;
use Google\AdsApi\AdWords\v201809\cm\CampaignCriterionOperation;
use Google\AdsApi\AdWords\v201809\cm\CampaignOperation;
use Google\AdsApi\AdWords\v201809\cm\CampaignStatus;
use Google\AdsApi\AdWords\v201809\cm\CpcBid;
use Google\AdsApi\AdWords\v201809\cm\ExpandedTextAd;
use Google\AdsApi\AdWords\v201809\cm\Keyword;
use Google\AdsApi\AdWords\v201809\cm\KeywordMatchType;
use Google\AdsApi\AdWords\v201809\cm\ManualCpcBiddingScheme;
use Google\AdsApi\AdWords\v201809\cm\Money;
use Google\AdsApi\AdWords\v201809\cm\NegativeCampaignCriterion;
use Google\AdsApi\AdWords\v201809\cm\Operator;
use Google\AdsApi\AdWords\v201809\cm\Predicate;
use Google\AdsApi\AdWords\v201809\cm\PredicateOperator;
use Google\AdsApi\AdWords\v201809\cm\Selector;
use Google\AdsApi\Common\OAuth2TokenBuilder;
use UnexpectedValueException;

/**
 * This example adds complete campaigns using BatchJobService.
 */
class AddCompleteCampaignsUsingBatchJob
{

    const NUMBER_OF_CAMPAIGNS_TO_ADD = 2;
    const NUMBER_OF_ADGROUPS_TO_ADD = 2;
    const NUMBER_OF_KEYWORDS_TO_ADD = 5;
    const POLL_FREQUENCY_SECONDS = 30;
    const MAX_POLL_ATTEMPTS = 60;

    private static $temporaryId = 0;

    public static function runExample(
        AdWordsServices $adWordsServices,
        AdWordsSession $session
    ) {
        $batchJobService = $adWordsServices->get($session, BatchJobService::class);

        // Create a BatchJob.
        $addOp = new BatchJobOperation();
        $addOp->setOperator(Operator::ADD);
        $addOp->setOperand(new BatchJob());

        $result = $batchJobService->mutate([$addOp]);
        $batchJob = $result->getValue()[0];

        // Get the upload URL from the new job.
        $uploadUrl = $batchJob->getUploadUrl()->getUrl();
        printf(
            "Created BatchJob with ID %d, status '%s' and upload URL '%s'.\n",
            $batchJob->getId(),
            $batchJob->getStatus(),
            $uploadUrl
        );

        $namePrefix = uniqid();
        // Create and add an operation to create a new budget.
        $budgetOperation = self::buildBudgetOperation($namePrefix);
        $operations = [$budgetOperation];

        // Create and add an operation to create new campaigns.
        $campaignOperations = self::buildCampaignOperations($namePrefix, $budgetOperation);
        $operations = array_merge($operations, $campaignOperations);

        // Create and add operations to create new negative keyword criteria for
        // each campaign.
        $campaignCriterionOperations = self::buildCampaignCriterionOperations($campaignOperations);
        $operations = array_merge($operations, $campaignCriterionOperations);

        // Create and add operations to create new ad groups.
        $adGroupOperations = self::buildAdGroupOperations($namePrefix, $campaignOperations);
        $operations = array_merge($operations, $adGroupOperations);

        // Create and add operations to create new ad group criteria (keywords).
        $adGroupCriterionOperations = self::buildAdGroupCriterionOperations($adGroupOperations);
        $operations = array_merge($operations, $adGroupCriterionOperations);

        // Create and add operations to create new ad group ads (text ads).
        $adGroupAdOperations = self::buildAdGroupAdOperations($adGroupOperations);
        $operations = array_merge($operations, $adGroupAdOperations);

        // Use BatchJobs to upload all operations.
        $batchJobs = new BatchJobs($session);
        $batchJobs->uploadBatchJobOperations($operations, $uploadUrl);

        printf(
            "Uploaded %d operations for batch job with ID %d.\n",
            count($operations),
            $batchJob->getId()
        );

        // Poll for completion of the batch job using an exponential back off.
        $pollAttempts = 0;
        $isPending = true;
        do {
            $sleepSeconds = self::POLL_FREQUENCY_SECONDS * pow(2, $pollAttempts);
            printf("Sleeping %d seconds...\n", $sleepSeconds);
            sleep($sleepSeconds);

            $selector = new Selector();
            $selector->setFields(
                ['Id', 'Status', 'DownloadUrl', 'ProcessingErrors', 'ProgressStats']
            );
            $selector->setPredicates(
                [
                    new Predicate('Id', PredicateOperator::EQUALS, [$batchJob->getId()])
                ]
            );
            $batchJob = $batchJobService->get($selector)->getEntries()[0];
            printf(
                "Batch job ID %d has status '%s'.\n",
                $batchJob->getId(),
                $batchJob->getStatus()
            );

            $pollAttempts++;
            if ($batchJob->getStatus() !== BatchJobStatus::ACTIVE
                && $batchJob->getStatus() !== BatchJobStatus::AWAITING_FILE
                && $batchJob->getStatus() !== BatchJobStatus::CANCELING) {
                $isPending = false;
            }
        } while ($isPending && $pollAttempts <= self::MAX_POLL_ATTEMPTS);

        if ($isPending) {
            throw new UnexpectedValueException(
                sprintf(
                    'Job is still pending state after polling %d times.',
                    self::MAX_POLL_ATTEMPTS
                )
            );
        }

        if ($batchJob->getProcessingErrors() !== null) {
            $i = 0;
            foreach ($batchJob->getProcessingErrors() as $processingError) {
                printf(
                    " Processing error [%d]: errorType=%s, trigger=%s, errorString=%s, fieldPath=%s, reason=%s\n",
                    $i++,
                    $processingError->getApiErrorType(),
                    $processingError->getTrigger(),
                    $processingError->getErrorString(),
                    $processingError->getFieldPath(),
                    $processingError->getReason()
                );
            }
        } else {
            printf("No processing errors found.\n");
        }

        if ($batchJob->getDownloadUrl() !== null
            && $batchJob->getDownloadUrl()->getUrl() !== null) {
            $mutateResults = $batchJobs->downloadBatchJobResults(
                $batchJob->getDownloadUrl()->getUrl()
            );
            printf(
                "Downloaded results from %s:\n",
                $batchJob->getDownloadUrl()->getUrl()
            );

            if (count($mutateResults) === 0) {
                printf("  No results available.\n");
            } else {
                foreach ($mutateResults as $mutateResult) {
                    $outcome = $mutateResult->getErrorList() === null ? 'SUCCESS' : 'FAILURE';
                    printf(
                        "  Operation [%d] - %s\n",
                        $mutateResult->getIndex(),
                        $outcome
                    );
                }
            }
        } else {
            printf("No results available for download.\n");
        }
    }

    /**
     * Builds objects of AdGroupAdOperation for creating an ad group ad for
     * ad groups in the specified ad group operations.
     *
     * @param AdGroupOperation[] $adGroupOperations an array of AdGroupOperation
     * @return array an array of AdGroupAdOperation
     */
    private static function buildAdGroupAdOperations(array $adGroupOperations)
    {
        $operations = [];
        foreach ($adGroupOperations as $adGroupOperation) {
            $adGroupId = $adGroupOperation->getOperand()->getId();
            $adGroupAd = new AdGroupAd();
            $adGroupAd->setAdGroupId($adGroupId);

            $expandedTextAd = new ExpandedTextAd();
            $expandedTextAd->setHeadlinePart1('Luxury Cruise to Mars');
            $expandedTextAd->setHeadlinePart2('Visit the Red Planet in style.');
            $expandedTextAd->setDescription('Low-gravity fun for everyone!');
            $expandedTextAd->setFinalUrls(['http://www.example.com/1']);

            $adGroupAd->setAd($expandedTextAd);

            $operation = new AdGroupAdOperation();
            $operation->setOperator(Operator::ADD);
            $operation->setOperand($adGroupAd);

            $operations[] = $operation;
        }

        return $operations;
    }

    /**
     * Builds objects of AdGroupCriterionOperation for creating biddable criteria
     * (as keywords) for ad groups in the specified ad group operations. 50% of
     * keywords are created with some invalid characters to demonstrate how
     * BatchJobService returns information about such errors.
     *
     * @param AdGroupOperation[] $adGroupOperations an array of AdGroupOperation
     * @return array an array of AdGroupCriterionOperation
     */
    private static function buildAdGroupCriterionOperations(array $adGroupOperations)
    {
        $adGroupCriteriaOperations = [];

        // Create AdGroupCriterionOperations to add keywords.
        foreach ($adGroupOperations as $adGroupOperation) {
            $newAdGroupId = $adGroupOperation->getOperand()->getId();
            for ($i = 0; $i < self::NUMBER_OF_KEYWORDS_TO_ADD; $i++) {
                // Create Keyword.
                $text = sprintf('mars%d', $i);

                // Make 50% of keywords invalid to demonstrate error handling.
                if ($i % 2 == 0) {
                    $text = $text . '!!!';
                }
                $keyword = new Keyword();
                $keyword->setText($text);
                $keyword->setMatchType(KeywordMatchType::BROAD);

                // Create BiddableAdGroupCriterion.
                $biddableAdGroupCriterion = new BiddableAdGroupCriterion();
                $biddableAdGroupCriterion->setAdGroupId($newAdGroupId);
                $biddableAdGroupCriterion->setCriterion($keyword);

                // Create AdGroupCriterionOperation.
                $operation = new AdGroupCriterionOperation();
                $operation->setOperand($biddableAdGroupCriterion);
                $operation->setOperator(Operator::ADD);

                // Add to list.
                $adGroupCriteriaOperations[] = $operation;
            }
        }

        return $adGroupCriteriaOperations;
    }

    /**
     * Builds objects of AdGroupOperation for creating ad groups for campaigns in
     * the specified campaign operations.
     *
     * @param string $namePrefix a prefix string used to name ad groups
     * @param CampaignOperation[] $campaignOperations an array of
     *     CampaignOperation
     * @return array an array of AdGroupOperation
     */
    private static function buildAdGroupOperations(
        $namePrefix,
        array $campaignOperations
    ) {
        $operations = [];
        foreach ($campaignOperations as $campaignOperation) {
            for ($i = 0; $i < self::NUMBER_OF_ADGROUPS_TO_ADD; $i++) {
                $adGroup = new AdGroup();
                $adGroup->setCampaignId($campaignOperation->getOperand()->getId());
                $adGroup->setId(--self::$temporaryId);
                $adGroup->setName(
                    sprintf(
                        'Batch Ad Group %s.%s',
                        $namePrefix,
                        strval($adGroup->getId())
                    )
                );

                $biddingStrategyConfiguration = new BiddingStrategyConfiguration();
                $money = new Money();
                $money->setMicroAmount(10000000);
                $bid = new CpcBid();
                $bid->setBid($money);
                $biddingStrategyConfiguration->setBids([$bid]);

                $adGroup->setBiddingStrategyConfiguration(
                    $biddingStrategyConfiguration
                );

                $operation = new AdGroupOperation();
                $operation->setOperand($adGroup);
                $operation->setOperator(Operator::ADD);

                $operations[] = $operation;
            }
        }

        return $operations;
    }

    /**
     * Builds objects of CampaignCriterionOperation for creating a negative
     * campaign criterion (as keyword) for campaigns in the specified campaign
     * operations.
     *
     * @param CampaignOperation[] $campaignOperations an array of
     *     CampaignOperation
     * @return array an array of CampaignCriterionOperation
     */
    private static function buildCampaignCriterionOperations(
        array $campaignOperations
    ) {
        $operations = [];
        foreach ($campaignOperations as $campaignOperation) {
            $keyword = new Keyword();
            $keyword->setMatchType(KeywordMatchType::BROAD);
            $keyword->setText('venus');

            $negativeCriterion = new NegativeCampaignCriterion();
            $negativeCriterion->setCampaignId(
                $campaignOperation->getOperand()->getId()
            );
            $negativeCriterion->setCriterion($keyword);

            $operation = new CampaignCriterionOperation();
            $operation->setOperand($negativeCriterion);
            $operation->setOperator(Operator::ADD);

            $operations[] = $operation;
        }

        return $operations;
    }

    /**
     * Builds objects of CampaignOperation for creating a campaign using the ID of
     * budget in the specified budget operation.
     *
     * @param string $namePrefix a prefix string used to name campaigns
     * @param BudgetOperation $budgetOperation an object of BudgetOperation
     * @return array an array of CampaignOperation
     */
    private static function buildCampaignOperations(
        $namePrefix,
        BudgetOperation $budgetOperation
    ) {
        $budgetId = $budgetOperation->getOperand()->getBudgetId();

        $operations = [];
        for ($i = 0; $i < self::NUMBER_OF_CAMPAIGNS_TO_ADD; $i++) {
            $campaign = new Campaign();
            $campaign->setId(--self::$temporaryId);
            $campaign->setName(
                sprintf(
                    'Batch Campaign %s.%s',
                    $namePrefix,
                    strval($campaign->getId())
                )
            );

            // Recommendation: Set the campaign to PAUSED when creating it to stop
            // the ads from immediately serving. Set to ENABLED once you've added
            // targeting and the ads are ready to serve.
            $campaign->setStatus(CampaignStatus::PAUSED);
            $campaign->setAdvertisingChannelType(AdvertisingChannelType::SEARCH);

            $budget = new Budget();
            $budget->setBudgetId($budgetId);
            $campaign->setBudget($budget);
            $biddingStrategyConfiguration = new BiddingStrategyConfiguration();
            $biddingStrategyConfiguration->setBiddingStrategyType(
                BiddingStrategyType::MANUAL_CPC
            );

            // You can optionally provide a bidding scheme in place of the type.
            $cpcBiddingScheme = new ManualCpcBiddingScheme();
            $biddingStrategyConfiguration->setBiddingScheme($cpcBiddingScheme);

            $campaign->setBiddingStrategyConfiguration($biddingStrategyConfiguration);

            $operation = new CampaignOperation();
            $operation->setOperand($campaign);
            $operation->setOperator(Operator::ADD);
            $operations[] = $operation;
        }

        return $operations;
    }

    /**
     * Builds BudgetOperation for creating a budget.
     *
     * @param string $namePrefix a prefix string used to name a budget
     * @return BudgetOperation an object of BudgetOperation
     */
    private static function buildBudgetOperation($namePrefix)
    {
        $budget = new Budget();
        $budget->setBudgetId(--self::$temporaryId);
        $budget->setName('Interplanetary Cruise #' . $namePrefix);
        $budgetAmount = new Money();
        $budgetAmount->setMicroAmount(50000000);
        $budget->setAmount($budgetAmount);
        $budget->setDeliveryMethod(BudgetBudgetDeliveryMethod::STANDARD);

        $budgetOperation = new BudgetOperation();
        $budgetOperation->setOperand($budget);
        $budgetOperation->setOperator(Operator::ADD);

        return $budgetOperation;
    }

    public static function main()
    {
        // Generate a refreshable OAuth2 credential for authentication.
        $oAuth2Credential = (new OAuth2TokenBuilder())->fromFile()->build();

        // Construct an API session configured from a properties file and the
        // OAuth2 credentials above.
        $session = (new AdWordsSessionBuilder())->fromFile()->withOAuth2Credential($oAuth2Credential)->build();
        self::runExample(new AdWordsServices(), $session);
    }
}

AddCompleteCampaignsUsingBatchJob::main();

Create a draft and access its campaign

<?php
/**
 * Copyright 2017 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace Google\AdsApi\Examples\AdWords\v201809\CampaignManagement;

require __DIR__ . '/../../../../vendor/autoload.php';

use Google\AdsApi\AdWords\AdWordsServices;
use Google\AdsApi\AdWords\AdWordsSession;
use Google\AdsApi\AdWords\AdWordsSessionBuilder;
use Google\AdsApi\AdWords\v201809\cm\CampaignCriterion;
use Google\AdsApi\AdWords\v201809\cm\CampaignCriterionOperation;
use Google\AdsApi\AdWords\v201809\cm\CampaignCriterionService;
use Google\AdsApi\AdWords\v201809\cm\Draft;
use Google\AdsApi\AdWords\v201809\cm\DraftOperation;
use Google\AdsApi\AdWords\v201809\cm\DraftService;
use Google\AdsApi\AdWords\v201809\cm\Language;
use Google\AdsApi\AdWords\v201809\cm\Operator;
use Google\AdsApi\Common\OAuth2TokenBuilder;

/**
 * This example shows how to create a draft and access its associated
 * draft campaign.
 */
class AddDraft
{

    const BASE_CAMPAIGN_ID = 'INSERT_BASE_CAMPAIGN_ID_HERE';

    public static function runExample(
        AdWordsServices $adWordsServices,
        AdWordsSession $session,
        $baseCampaignId
    ) {
        $draftService = $adWordsServices->get($session, DraftService::class);

        $operations = [];
        // Create a draft.
        $draft = new Draft();
        $draft->setBaseCampaignId($baseCampaignId);
        $draft->setDraftname('Test Draft #' . uniqid());

        // Create a draft operation and add it to the operations list.
        $operation = new DraftOperation();
        $operation->setOperand($draft);
        $operation->setOperator(Operator::ADD);
        $operations[] = $operation;

        // Create the draft on the server and print out some information for
        // the created draft.
        $result = $draftService->mutate($operations);
        $draft = $result->getValue()[0];
        printf(
            "Draft with ID %d, base campaign ID %d, and draft campaign ID %d was added.\n",
            $draft->getDraftId(),
            $draft->getBaseCampaignId(),
            $draft->getDraftCampaignId()
        );

        // Once the draft is created, you can modify the draft campaign as if it
        // were a real campaign. For example, you may add criteria, adjust bids, or
        // even include additional ads. Adding a criterion is shown here.
        $campaignCriterionService = $adWordsServices->get($session, CampaignCriterionService::class);

        // Create a criterion.
        $language = new Language();
        $language->setId(1003); // Spanish
        $campaignCriterion = new CampaignCriterion();
        $campaignCriterion->setCampaignId($draft->getDraftCampaignId());
        $campaignCriterion->setCriterion($language);

        // Create a campaign criterion operation and add it to the operations list.
        $operations = [];
        $operation = new CampaignCriterionOperation();
        $operation->setOperand($campaignCriterion);
        $operation->setOperator(Operator::ADD);
        $operations[] = $operation;

        // Create a campaign criterion on the server.
        $campaignCriterionService->mutate($operations);

        printf(
            "Draft updated to include criteria in the campaign with ID %d.\n",
            $draft->getDraftCampaignId()
        );
    }

    public static function main()
    {
        // Generate a refreshable OAuth2 credential for authentication.
        $oAuth2Credential = (new OAuth2TokenBuilder())->fromFile()->build();

        // Construct an API session configured from a properties file and the
        // OAuth2 credentials above.
        $session = (new AdWordsSessionBuilder())->fromFile()->withOAuth2Credential($oAuth2Credential)->build();
        self::runExample(
            new AdWordsServices(),
            $session,
            intval(self::BASE_CAMPAIGN_ID)
        );
    }
}

AddDraft::main();

Upload keywords incrementally using BatchJobService

<?php
/**
 * Copyright 2017 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace Google\AdsApi\Examples\AdWords\v201809\CampaignManagement;

require __DIR__ . '/../../../../vendor/autoload.php';

use Google\AdsApi\AdWords\AdWordsServices;
use Google\AdsApi\AdWords\AdWordsSession;
use Google\AdsApi\AdWords\AdWordsSessionBuilder;
use Google\AdsApi\AdWords\BatchJobs\BatchJobUploadStatus;
use Google\AdsApi\AdWords\BatchJobs\v201809\BatchJobs;
use Google\AdsApi\AdWords\v201809\cm\AdGroupCriterionOperation;
use Google\AdsApi\AdWords\v201809\cm\ApiException;
use Google\AdsApi\AdWords\v201809\cm\BatchJob;
use Google\AdsApi\AdWords\v201809\cm\BatchJobError;
use Google\AdsApi\AdWords\v201809\cm\BatchJobErrorReason;
use Google\AdsApi\AdWords\v201809\cm\BatchJobOperation;
use Google\AdsApi\AdWords\v201809\cm\BatchJobService;
use Google\AdsApi\AdWords\v201809\cm\BatchJobStatus;
use Google\AdsApi\AdWords\v201809\cm\BiddableAdGroupCriterion;
use Google\AdsApi\AdWords\v201809\cm\Keyword;
use Google\AdsApi\AdWords\v201809\cm\KeywordMatchType;
use Google\AdsApi\AdWords\v201809\cm\Operator;
use Google\AdsApi\AdWords\v201809\cm\Predicate;
use Google\AdsApi\AdWords\v201809\cm\PredicateOperator;
use Google\AdsApi\AdWords\v201809\cm\Selector;
use Google\AdsApi\Common\OAuth2TokenBuilder;
use UnexpectedValueException;

/**
 * This code sample illustrates how to perform multiple requests using the
 * BatchJobService using incremental uploads.
 */
class AddKeywordsUsingIncrementalBatchJob
{

    const NUMBER_OF_KEYWORDS_TO_ADD = 100;
    const POLL_FREQUENCY_SECONDS = 30;
    const MAX_POLL_ATTEMPTS = 5;

    const AD_GROUP_ID = 'INSERT_AD_GROUP_ID_HERE';

    public static function runExample(
        AdWordsServices $adWordsServices,
        AdWordsSession $session,
        $adGroupId
    ) {
        $batchJobService = $adWordsServices->get($session, BatchJobService::class);

        // Create a BatchJob.
        $addOp = new BatchJobOperation();
        $addOp->setOperator(Operator::ADD);
        $addOp->setOperand(new BatchJob());

        $result = $batchJobService->mutate([$addOp]);
        $batchJob = $result->getValue()[0];

        // Get the upload URL from the new job.
        $uploadUrl = $batchJob->getUploadUrl()->getUrl();
        printf(
            "Created BatchJob with ID %d, status '%s' and upload URL '%s'.\n",
            $batchJob->getId(),
            $batchJob->getStatus(),
            $uploadUrl
        );

        // Use BatchJobs to upload all operations.
        $batchJobs = new BatchJobs($session);

        // Generate and upload the first set of operations.
        $adGroupCriterionOperations = self::buildAdGroupCriterionOperations($adGroupId);
        $batchJobUploadStatus = $batchJobs->uploadIncrementalBatchJobOperations(
            $adGroupCriterionOperations,
            new BatchJobUploadStatus($uploadUrl, $session)
        );
        printf(
            "Uploaded %d operations for batch job with ID %d.\n",
            count($adGroupCriterionOperations),
            $batchJob->getId()
        );

        // Generate and upload the second set of operations.
        $adGroupCriterionOperations = self::buildAdGroupCriterionOperations($adGroupId);
        $batchJobUploadStatus = $batchJobs->uploadIncrementalBatchJobOperations(
            $adGroupCriterionOperations,
            $batchJobUploadStatus
        );
        printf(
            "Uploaded %d operations for batch job with ID %d.\n",
            count($adGroupCriterionOperations),
            $batchJob->getId()
        );

        // Generate and upload the third and final set of operations.
        $adGroupCriterionOperations = self::buildAdGroupCriterionOperations($adGroupId);
        $batchJobUploadStatus = $batchJobs->uploadIncrementalBatchJobOperations(
            $adGroupCriterionOperations,
            $batchJobUploadStatus
        );
        printf(
            "Uploaded %d operations for batch job with ID %d.\n",
            count($adGroupCriterionOperations),
            $batchJob->getId()
        );
        $batchJobs->closeIncrementalUpload($batchJobUploadStatus);

        // Poll for completion of the batch job using an exponential back off.
        $pollAttempts = 0;
        $isPending = true;
        $wasCancelRequested = false;

        $selector = new Selector();
        $selector->setFields(
            ['Id', 'Status', 'DownloadUrl', 'ProcessingErrors', 'ProgressStats']
        );
        $selector->setPredicates(
            [
                new Predicate('Id', PredicateOperator::EQUALS, [$batchJob->getId()])
            ]
        );
        do {
            $sleepSeconds = self::POLL_FREQUENCY_SECONDS * pow(2, $pollAttempts);
            printf("Sleeping %d seconds...\n", $sleepSeconds);
            sleep($sleepSeconds);

            $batchJob = $batchJobService->get($selector)->getEntries()[0];
            printf(
                "Batch job ID %d has status '%s'.\n",
                $batchJob->getId(),
                $batchJob->getStatus()
            );

            $pollAttempts++;
            if ($batchJob->getStatus() !== BatchJobStatus::ACTIVE
                && $batchJob->getStatus() !== BatchJobStatus::AWAITING_FILE
                && $batchJob->getStatus() !== BatchJobStatus::CANCELING) {
                $isPending = false;
            }

            // Optional: Cancel the job if it has not completed after polling
            // MAX_POLL_ATTEMPTS times.
            if ($isPending && !$wasCancelRequested
                && $pollAttempts === self::MAX_POLL_ATTEMPTS) {
                $batchJob->setStatus(BatchJobStatus::CANCELING);
                $batchJobSetOperation = new BatchJobOperation();
                $batchJobSetOperation->setOperand($batchJob);
                $batchJobSetOperation->setOperator(Operator::SET);

                // Only request cancellation once per job.
                $wasCancelRequested = true;
                try {
                    $batchJob = $batchJobService->mutate([$batchJobSetOperation])->getValue()[0];
                    printf(
                        "Requested cancellation of batch job with ID %d.\n",
                        $batchJob->getId()
                    );
                    // Reset the poll attempt counter to wait for cancellation.
                    $pollAttempts = 0;
                } catch (ApiException $e) {
                    $errors = $e->getErrors();
                    if ($errors !== null
                        && count($errors) > 0
                        && $errors[0] instanceof BatchJobError) {
                        $batchJobError = $errors[0];
                        if ($batchJobError->getReason() === BatchJobErrorReason::INVALID_STATE_CHANGE) {
                            printf(
                                "Attempt to cancel batch job with ID %d was rejected because"
                                . " the job already completed or was canceled.\n",
                                $batchJob->getId()
                            );
                            continue;
                        }
                    }
                    throw $e;
                } finally {
                    // Reset the poll attempt counter to wait for cancellation.
                    $pollAttempts = 0;
                }
            }
        } while ($isPending && $pollAttempts <= self::MAX_POLL_ATTEMPTS);

        if ($isPending) {
            throw new UnexpectedValueException(
                sprintf(
                    'Job is still pending state after polling %d times.',
                    self::MAX_POLL_ATTEMPTS
                )
            );
        }

        if ($batchJob->getProcessingErrors() !== null) {
            $i = 0;
            foreach ($batchJob->getProcessingErrors() as $processingError) {
                printf(
                    " Processing error [%d]: errorType=%s, trigger=%s, errorString=%s, fieldPath=%s, reason=%s\n",
                    $i++,
                    $processingError->getApiErrorType(),
                    $processingError->getTrigger(),
                    $processingError->getErrorString(),
                    $processingError->getFieldPath(),
                    $processingError->getReason()
                );
            }
        } else {
            printf("No processing errors found.\n");
        }

        if ($batchJob->getDownloadUrl() !== null
            && $batchJob->getDownloadUrl()->getUrl() !== null) {
            $mutateResults = $batchJobs->downloadBatchJobResults(
                $batchJob->getDownloadUrl()->getUrl()
            );
            printf(
                "Downloaded results from %s:\n",
                $batchJob->getDownloadUrl()->getUrl()
            );

            if (count($mutateResults) === 0) {
                printf("  No results available.\n");
            } else {
                foreach ($mutateResults as $mutateResult) {
                    $outcome = $mutateResult->getErrorList() === null ? 'SUCCESS' : 'FAILURE';
                    printf(
                        "  Operation [%d] - %s\n",
                        $mutateResult->getIndex(),
                        $outcome
                    );
                }
            }
        } else {
            printf("No results available for download.\n");
        }
    }

    /**
     * Builds objects of AdGroupCriterionOperation for creating biddable criteria
     * (as keywords) for ad groups with the specified ID. 10% of keywords are
     * created with some invalid characters to demonstrate how `BatchJobService`
     * returns information about such errors.
     *
     * @param string $adGroupId the ID of the ad group to add the keywords to
     * @return array an array of AdGroupCriterionOperation
     */
    private static function buildAdGroupCriterionOperations($adGroupId)
    {
        $adGroupCriteriaOperations = [];

        $suffix = uniqid();
        // Create AdGroupCriterionOperations to add keywords.
        for ($i = 0; $i < self::NUMBER_OF_KEYWORDS_TO_ADD; $i++) {
            // Create Keyword.
            $text = sprintf("mars%s-%d", $suffix, $i);

            // Make 10% of keywords invalid to demonstrate error handling.
            if ($i % 10 === 0) {
                $text = $text . '!!!';
            }
            $keyword = new Keyword();
            $keyword->setText($text);
            $keyword->setMatchType(KeywordMatchType::BROAD);

            // Create BiddableAdGroupCriterion.
            $biddableAdGroupCriterion = new BiddableAdGroupCriterion();
            $biddableAdGroupCriterion->setAdGroupId($adGroupId);
            $biddableAdGroupCriterion->setCriterion($keyword);

            // Create AdGroupCriterionOperation.
            $operation = new AdGroupCriterionOperation();
            $operation->setOperand($biddableAdGroupCriterion);
            $operation->setOperator(Operator::ADD);

            // Add to list.
            $adGroupCriteriaOperations[] = $operation;
        }

        return $adGroupCriteriaOperations;
    }

    public static function main()
    {
        // Generate a refreshable OAuth2 credential for authentication.
        $oAuth2Credential = (new OAuth2TokenBuilder())->fromFile()->build();

        // Construct an API session configured from a properties file and the
        // OAuth2 credentials above.
        $session = (new AdWordsSessionBuilder())->fromFile()->withOAuth2Credential($oAuth2Credential)->build();
        self::runExample(
            new AdWordsServices(),
            $session,
            intval(self::AD_GROUP_ID)
        );
    }
}

AddKeywordsUsingIncrementalBatchJob::main();

Create a trial

<?php
/**
 * Copyright 2017 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace Google\AdsApi\Examples\AdWords\v201809\CampaignManagement;

require __DIR__ . '/../../../../vendor/autoload.php';

use Google\AdsApi\AdWords\AdWordsServices;
use Google\AdsApi\AdWords\AdWordsSession;
use Google\AdsApi\AdWords\AdWordsSessionBuilder;
use Google\AdsApi\AdWords\v201809\cm\CampaignTrialTrafficSplitType;
use Google\AdsApi\AdWords\v201809\cm\Operator;
use Google\AdsApi\AdWords\v201809\cm\Predicate;
use Google\AdsApi\AdWords\v201809\cm\PredicateOperator;
use Google\AdsApi\AdWords\v201809\cm\Selector;
use Google\AdsApi\AdWords\v201809\cm\Trial;
use Google\AdsApi\AdWords\v201809\cm\TrialAsyncErrorService;
use Google\AdsApi\AdWords\v201809\cm\TrialOperation;
use Google\AdsApi\AdWords\v201809\cm\TrialService;
use Google\AdsApi\AdWords\v201809\cm\TrialStatus;
use Google\AdsApi\Common\OAuth2TokenBuilder;

/**
 * This example shows how to create a trial and wait for it to complete.
 * See the Campaign Drafts and Experiments guide for more information:
 * https://developers.google.com/adwords/api/docs/guides/campaign-drafts-experiments
 */
class AddTrial
{

    const MAX_POLL_ATTEMPTS = 5;
    const POLL_FREQUENCY_SECONDS = 30;

    const DRAFT_ID = 'INSERT_DRAFT_ID_HERE';
    const BASE_CAMPAIGN_ID = 'INSERT_BASE_CAMPAIGN_ID_HERE';

    public static function runExample(
        AdWordsServices $adWordsServices,
        AdWordsSession $session,
        $draftId,
        $baseCampaignId
    ) {
        $trialService = $adWordsServices->get($session, TrialService::class);
        $trialAsynErrorService = $adWordsServices->get($session, TrialAsyncErrorService::class);

        // Create a trial.
        $trial = new Trial();
        $trial->setDraftId($draftId);
        $trial->setBaseCampaignId($baseCampaignId);
        $trial->setName('Test Trial #' . uniqid());
        $trial->setTrafficSplitPercent(50);
        $trial->setTrafficSplitType(
            CampaignTrialTrafficSplitType::RANDOM_QUERY
        );

        // Create a trial operation and add it to the operations list.
        $operations = [];
        $operation = new TrialOperation();
        $operation->setOperand($trial);
        $operation->setOperator(Operator::ADD);
        $operations[] = $operation;

        // Create the trial on the server.
        $trial = $trialService->mutate($operations)->getValue()[0];

        $selector = new Selector();
        $selector->setFields(
            ['Id', 'Status', 'BaseCampaignId', 'TrialCampaignId']
        );
        $selector->setPredicates(
            [new Predicate('Id', PredicateOperator::IN, [$trial->getId()])]
        );

        // Since creating a trial is asynchronous, we have to poll it to wait for it
        // to finish.
        $pollAttempts = 0;
        $isPending = true;
        $trial = null;
        do {
            $sleepSeconds = self::POLL_FREQUENCY_SECONDS * pow(2, $pollAttempts);
            printf("Sleeping %d seconds...\n", $sleepSeconds);
            sleep($sleepSeconds);

            $trial = $trialService->get($selector)->getEntries()[0];
            printf(
                "Trial ID %d has status '%s'.\n",
                $trial->getId(),
                $trial->getStatus()
            );

            $pollAttempts++;
            $isPending = ($trial->getStatus() === TrialStatus::CREATING) ? true : false;
        } while ($isPending && $pollAttempts <= self::MAX_POLL_ATTEMPTS);

        if ($trial->getStatus() === TrialStatus::ACTIVE) {
            // The trial creation was successful.
            printf(
                "Trial created with ID %d and trial campaign ID %d\n",
                $trial->getId(),
                $trial->getTrialCampaignId()
            );
        } elseif ($trial->getStatus() === TrialStatus::CREATION_FAILED) {
            // The trial creation failed, and errors can be fetched from the
            // TrialAsyncErrorService.
            $selector = new Selector();
            $selector->setFields(['TrialId', 'AsyncError']);
            $selector->setPredicates(
                [new Predicate('TrialId', PredicateOperator::IN, [$trial->getId()])]
            );

            $errors = $trialAsynErrorService->get($selector)->getEntries();

            if (count($errors) === 0) {
                printf(
                    "Could not retrieve errors for the trial with ID %d\n",
                    $trial->getId()
                );
            } else {
                printf("Could not create trial due to the following errors:\n");
                $i = 0;
                foreach ($errors as $error) {
                    printf("Error #%d: %s\n", $i++, $error->getAsyncError());
                }
            }
        } else {
            // Most likely, the trial is still being created. You can continue
            // polling, but we have limited the number of attempts in the example.
            printf(
                "Timed out waiting to create trial from draft with ID %d with base campaign with ID %d\n",
                $draftId,
                $baseCampaignId
            );
        }
    }

    public static function main()
    {
        // Generate a refreshable OAuth2 credential for authentication.
        $oAuth2Credential = (new OAuth2TokenBuilder())->fromFile()->build();

        // Construct an API session configured from a properties file and the
        // OAuth2 credentials above.
        $session = (new AdWordsSessionBuilder())->fromFile()->withOAuth2Credential($oAuth2Credential)->build();
        self::runExample(
            new AdWordsServices(),
            $session,
            intval(self::DRAFT_ID),
            intval(self::BASE_CAMPAIGN_ID)
        );
    }
}

AddTrial::main();

Get all disapproved ads in an ad group

<?php
/**
 * Copyright 2017 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace Google\AdsApi\Examples\AdWords\v201809\CampaignManagement;

require __DIR__ . '/../../../../vendor/autoload.php';

use Google\AdsApi\AdWords\AdWordsServices;
use Google\AdsApi\AdWords\AdWordsSession;
use Google\AdsApi\AdWords\AdWordsSessionBuilder;
use Google\AdsApi\AdWords\v201809\cm\AdGroupAdService;
use Google\AdsApi\AdWords\v201809\cm\OrderBy;
use Google\AdsApi\AdWords\v201809\cm\Paging;
use Google\AdsApi\AdWords\v201809\cm\PolicyApprovalStatus;
use Google\AdsApi\AdWords\v201809\cm\Predicate;
use Google\AdsApi\AdWords\v201809\cm\PredicateOperator;
use Google\AdsApi\AdWords\v201809\cm\Selector;
use Google\AdsApi\AdWords\v201809\cm\SortOrder;
use Google\AdsApi\Common\OAuth2TokenBuilder;

/**
 * This example gets all disapproved ads in an ad group. To get ad groups, run
 * BasicOperation/GetAdGroups.php.
 */
class GetAllDisapprovedAds
{

    const AD_GROUP_ID = 'INSERT_AD_GROUP_ID_HERE';
    const PAGE_LIMIT = 500;

    public static function runExample(
        AdWordsServices $adWordsServices,
        AdWordsSession $session,
        $adGroupId
    ) {
        $adGroupAdService = $adWordsServices->get($session, AdGroupAdService::class);

        // Create a selector to select all ads for the specified ad group.
        $selector = new Selector();
        $selector->setFields(['Id', 'PolicySummary']);
        $selector->setOrdering([new OrderBy('Id', SortOrder::ASCENDING)]);
        // Create the predicate to get only disapproved ads.
        $selector->setPredicates(
            [
                new Predicate('AdGroupId', PredicateOperator::IN, [$adGroupId]),
                new Predicate(
                    'CombinedApprovalStatus',
                    PredicateOperator::EQUALS,
                    [PolicyApprovalStatus::DISAPPROVED]
                )
            ]
        );
        $selector->setPaging(new Paging(0, self::PAGE_LIMIT));

        $totalNumEntries = 0;
        $disapprovedAdsCount = 0;
        do {
            // Retrieve ad group ads one page at a time, continuing to request pages
            // until all ad group ads have been retrieved.
            $page = $adGroupAdService->get($selector);

            // Print out some information for each ad group ad.
            if ($page->getEntries() !== null) {
                $totalNumEntries = $page->getTotalNumEntries();
                foreach ($page->getEntries() as $adGroupAd) {
                    $disapprovedAdsCount++;
                    $policySummary = $adGroupAd->getPolicySummary();
                    printf(
                        "Ad with ID %d and type '%s' was disapproved with the following policy topic entries:\n",
                        $adGroupAd->getAd()->getId(),
                        $adGroupAd->getAd()->getType()
                    );
                    // Display the policy topic entries related to the ad disapproval.
                    foreach ($policySummary->getPolicyTopicEntries() as $policyTopicEntry) {
                        printf(
                            "  topic id: %s, topic name: '%s', Help Center URL: %s\n",
                            $policyTopicEntry->getPolicyTopicId(),
                            $policyTopicEntry->getPolicyTopicName(),
                            $policyTopicEntry->getPolicyTopicHelpCenterUrl()
                        );
                        // Display the attributes and values that triggered the policy
                        // topic.
                        if ($policyTopicEntry->getPolicyTopicEvidences() === null) {
                            continue;
                        }
                        foreach ($policyTopicEntry->getPolicyTopicEvidences() as $evidence) {
                            printf(
                                "    evidence type: %s\n",
                                $evidence->getPolicyTopicEvidenceType()
                            );
                            $evidenceTextList = $evidence->getEvidenceTextList();
                            if ($evidenceTextList === null) {
                                continue;
                            }
                            for ($i = 0; $i < count($evidenceTextList); $i++) {
                                printf(
                                    "      evidence text[%d]: %s\n",
                                    $i,
                                    $evidenceTextList[$i]
                                );
                            }
                        }
                    }
                }
            }

            $selector->getPaging()->setStartIndex(
                $selector->getPaging()->getStartIndex() + self::PAGE_LIMIT
            );
        } while ($selector->getPaging()->getStartIndex() < $totalNumEntries);
        printf("%d disapproved ads were found.\n", $disapprovedAdsCount);
    }

    public static function main()
    {
        // Generate a refreshable OAuth2 credential for authentication.
        $oAuth2Credential = (new OAuth2TokenBuilder())->fromFile()->build();

        // Construct an API session configured from a properties file and the
        // OAuth2 credentials above.
        $session = (new AdWordsSessionBuilder())->fromFile()->withOAuth2Credential($oAuth2Credential)->build();
        self::runExample(
            new AdWordsServices(),
            $session,
            intval(self::AD_GROUP_ID)
        );
    }
}

GetAllDisapprovedAds::main();

Get all disapproved ads in an ad group using AWQL

<?php
/**
 * Copyright 2017 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace Google\AdsApi\Examples\AdWords\v201809\CampaignManagement;

require __DIR__ . '/../../../../vendor/autoload.php';

use Google\AdsApi\AdWords\AdWordsServices;
use Google\AdsApi\AdWords\AdWordsSession;
use Google\AdsApi\AdWords\AdWordsSessionBuilder;
use Google\AdsApi\AdWords\Query\v201809\ServiceQueryBuilder;
use Google\AdsApi\AdWords\v201809\cm\AdGroupAdService;
use Google\AdsApi\AdWords\v201809\cm\PolicyApprovalStatus;
use Google\AdsApi\Common\OAuth2TokenBuilder;

/**
 * This example gets all disapproved ads in an ad group with AWQL. To get ad
 * groups, run BasicOperation/GetAdGroups.php.
 */
class GetAllDisapprovedAdsWithAwql
{

    const AD_GROUP_ID = 'INSERT_AD_GROUP_ID_HERE';
    const PAGE_LIMIT = 500;

    public static function runExample(
        AdWordsServices $adWordsServices,
        AdWordsSession $session,
        $adGroupId
    ) {
        $adGroupAdService = $adWordsServices->get($session, AdGroupAdService::class);

        // Create an AWQL query.
        $query = (new ServiceQueryBuilder())->select(['Id', 'PolicySummary'])
            ->where('AdGroupId')
            ->equalTo($adGroupId)
            ->where('CombinedApprovalStatus')
            ->equalTo(PolicyApprovalStatus::DISAPPROVED)
            ->orderByAsc('Id')
            ->limit(0, self::PAGE_LIMIT)
            ->build();

        // Create paging controls.
        $disapprovedAdsCount = 0;
        do {
            // Advance the paging offset in subsequent iterations only.
            if (isset($page)) {
                $query->nextPage();
            }

            // Make the query request.
            $page = $adGroupAdService->query(sprintf('%s', $query));

            // Display results from the query.
            if ($page->getEntries() !== null) {
                foreach ($page->getEntries() as $adGroupAd) {
                    $disapprovedAdsCount++;
                    $policySummary = $adGroupAd->getPolicySummary();
                    printf(
                        "Ad with ID %d and type '%s' was disapproved with the following policy topic entries:\n",
                        $adGroupAd->getAd()->getId(),
                        $adGroupAd->getAd()->getType()
                    );
                    // Display the policy topic entries related to the ad disapproval.
                    foreach ($policySummary->getPolicyTopicEntries() as $policyTopicEntry) {
                        printf(
                            "  topic id: %s, topic name: '%s', Help Center URL: %s\n",
                            $policyTopicEntry->getPolicyTopicId(),
                            $policyTopicEntry->getPolicyTopicName(),
                            $policyTopicEntry->getPolicyTopicHelpCenterUrl()
                        );
                        // Display the attributes and values that triggered the policy
                        // topic.
                        if ($policyTopicEntry->getPolicyTopicEvidences() === null) {
                            continue;
                        }
                        foreach ($policyTopicEntry->getPolicyTopicEvidences() as $evidence) {
                            printf(
                                "    evidence type: %s\n",
                                $evidence->getPolicyTopicEvidenceType()
                            );
                            $evidenceTextList = $evidence->getEvidenceTextList();
                            if ($evidenceTextList === null) {
                                continue;
                            }
                            for ($i = 0; $i < count($evidenceTextList); $i++) {
                                printf(
                                    "      evidence text[%d]: %s\n",
                                    $i,
                                    $evidenceTextList[$i]
                                );
                            }
                        }
                    }
                }
            }
        } while ($query->hasNext($page));
        printf("%d disapproved ads were found.\n", $disapprovedAdsCount);
    }

    public static function main()
    {
        // Generate a refreshable OAuth2 credential for authentication.
        $oAuth2Credential = (new OAuth2TokenBuilder())->fromFile()->build();

        // Construct an API session configured from a properties file and the
        // OAuth2 credentials above.
        $session = (new AdWordsSessionBuilder())->fromFile()->withOAuth2Credential($oAuth2Credential)->build();
        self::runExample(
            new AdWordsServices(),
            $session,
            intval(self::AD_GROUP_ID)
        );
    }
}

GetAllDisapprovedAdsWithAwql::main();

Get all campaigns with a specific label

<?php
/**
 * Copyright 2017 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace Google\AdsApi\Examples\AdWords\v201809\CampaignManagement;

require __DIR__ . '/../../../../vendor/autoload.php';

use Google\AdsApi\AdWords\AdWordsServices;
use Google\AdsApi\AdWords\AdWordsSession;
use Google\AdsApi\AdWords\AdWordsSessionBuilder;
use Google\AdsApi\AdWords\v201809\cm\CampaignService;
use Google\AdsApi\AdWords\v201809\cm\OrderBy;
use Google\AdsApi\AdWords\v201809\cm\Paging;
use Google\AdsApi\AdWords\v201809\cm\Predicate;
use Google\AdsApi\AdWords\v201809\cm\PredicateOperator;
use Google\AdsApi\AdWords\v201809\cm\Selector;
use Google\AdsApi\AdWords\v201809\cm\SortOrder;
use Google\AdsApi\Common\OAuth2TokenBuilder;

/**
 * This example gets all campaigns with a specific label. To add a label to
 * campaigns, run AddCampaignLabels.php.
 */
class GetCampaignsByLabel
{

    const LABEL_ID = 'INSERT_LABEL_ID_HERE';
    const PAGE_LIMIT = 500;

    public static function runExample(
        AdWordsServices $adWordsServices,
        AdWordsSession $session,
        $labelId
    ) {
        $campaignService = $adWordsServices->get($session, CampaignService::class);

        // Create a selector to select all campaigns by the specified label.
        $selector = new Selector();
        $selector->setFields(['Id', 'Name', 'Labels']);
        // Labels filtering is performed by ID. You can use CONTAINS_ANY to select
        // campaigns with any of the label IDs, CONTAINS_ALL to select campaigns
        // with all of the label IDs, or CONTAINS_NONE to select campaigns with none
        // of the label IDs.
        $selector->setPredicates(
            [
                new Predicate('Labels', PredicateOperator::CONTAINS_ANY, [$labelId])
            ]
        );
        $selector->setOrdering([new OrderBy('Name', SortOrder::ASCENDING)]);
        $selector->setPaging(new Paging(0, self::PAGE_LIMIT));

        $totalNumEntries = 0;
        do {
            // Retrieve campaigns one page at a time, continuing to request
            // pages until all campaigns have been retrieved.
            $page = $campaignService->get($selector);

            // Print out some information for each campaign.
            if ($page->getEntries() !== null) {
                $totalNumEntries = $page->getTotalNumEntries();
                foreach ($page->getEntries() as $campaign) {
                    printf(
                        "Campaign with name '%s' and ID %d and labels '%s' was found.\n",
                        $campaign->getName(),
                        $campaign->getId(),
                        implode(
                            ', ',
                            array_map(
                                function ($label) {
                                    return sprintf('%d/%s', $label->getId(), $label->getName());
                                },
                                $campaign->getLabels()
                            )
                        )
                    );
                }
            }

            $selector->getPaging()->setStartIndex(
                $selector->getPaging()->getStartIndex() + self::PAGE_LIMIT
            );
        } while ($selector->getPaging()->getStartIndex() < $totalNumEntries);

        printf("Number of results found: %d\n", $totalNumEntries);
    }

    public static function main()
    {
        // Generate a refreshable OAuth2 credential for authentication.
        $oAuth2Credential = (new OAuth2TokenBuilder())->fromFile()->build();

        // Construct an API session configured from a properties file and the
        // OAuth2 credentials above.
        $session = (new AdWordsSessionBuilder())->fromFile()->withOAuth2Credential($oAuth2Credential)->build();
        self::runExample(
            new AdWordsServices(),
            $session,
            intval(self::LABEL_ID)
        );
    }
}

GetCampaignsByLabel::main();

Graduate a trial

<?php
/**
 * Copyright 2017 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace Google\AdsApi\Examples\AdWords\v201809\CampaignManagement;

require __DIR__ . '/../../../../vendor/autoload.php';

use Google\AdsApi\AdWords\AdWordsServices;
use Google\AdsApi\AdWords\AdWordsSession;
use Google\AdsApi\AdWords\AdWordsSessionBuilder;
use Google\AdsApi\AdWords\v201809\cm\Budget;
use Google\AdsApi\AdWords\v201809\cm\BudgetBudgetDeliveryMethod;
use Google\AdsApi\AdWords\v201809\cm\BudgetOperation;
use Google\AdsApi\AdWords\v201809\cm\BudgetService;
use Google\AdsApi\AdWords\v201809\cm\Money;
use Google\AdsApi\AdWords\v201809\cm\Operator;
use Google\AdsApi\AdWords\v201809\cm\Trial;
use Google\AdsApi\AdWords\v201809\cm\TrialOperation;
use Google\AdsApi\AdWords\v201809\cm\TrialService;
use Google\AdsApi\AdWords\v201809\cm\TrialStatus;
use Google\AdsApi\Common\OAuth2TokenBuilder;

/**
 * This example shows how to graduate a trial.
 * See the Campaign Drafts and Experiments guide for more information:
 * https://developers.google.com/adwords/api/docs/guides/campaign-drafts-experiments
 */
class GraduateTrial
{

    const TRIAL_ID = 'INSERT_TRIAL_ID_HERE';

    public static function runExample(
        AdWordsServices $adWordsServices,
        AdWordsSession $session,
        $trialId
    ) {
        $trialService = $adWordsServices->get($session, TrialService::class);
        $budgetService = $adWordsServices->get($session, BudgetService::class);

        // To graduate a trial, you must specify a different budget from the base
        // campaign. The base campaign (in order to have had a trial based on it)
        // must have a non-shared budget, so it cannot be shared with the new
        // independent campaign created by graduation.
        $budget = new Budget();
        $budget->setName('Trial Budget #' . uniqid());
        $money = new Money();
        $money->setMicroAmount(50000000);
        $budget->setAmount($money);
        $budget->setDeliveryMethod(BudgetBudgetDeliveryMethod::STANDARD);

        // Create a budget operation and add it to the operations list.
        $operations = [];
        $operation = new BudgetOperation();
        $operation->setOperand($budget);
        $operation->setOperator(Operator::ADD);
        $operations[] = $operation;

        // Create the budget on the server.
        $budget = $budgetService->mutate($operations)->getValue()[0];

        // Create a trial.
        $trial = new Trial();
        $trial->setId($trialId);
        $trial->setBudgetId($budget->getBudgetId());
        $trial->setStatus(TrialStatus::GRADUATED);

        // Create a trial operation and add it to the operations list.
        $operations = [];
        $operation = new TrialOperation();
        $operation->setOperand($trial);
        $operation->setOperator(Operator::SET);
        $operations[] = $operation;

        // Update the trial on the server.
        $trial = $trialService->mutate($operations)->getValue()[0];

        // Graduation is a synchronous operation, so the campaign is already ready.
        // If you promote instead, make sure to see the polling scheme demonstrated
        // in AddTrial.php to wait for the asynchronous operation to finish.
        printf(
            "Trial with ID %d graduated. Campaign with ID %d was given a new budget"
            . " ID %d and is no longer dependent on this trial.\n",
            $trial->getId(),
            $trial->getTrialCampaignId(),
            $budget->getBudgetId()
        );
    }

    public static function main()
    {
        // Generate a refreshable OAuth2 credential for authentication.
        $oAuth2Credential = (new OAuth2TokenBuilder())->fromFile()->build();

        // Construct an API session configured from a properties file and the
        // OAuth2 credentials above.
        $session = (new AdWordsSessionBuilder())->fromFile()->withOAuth2Credential($oAuth2Credential)->build();
        self::runExample(new AdWordsServices(), $session, intval(self::TRIAL_ID));
    }
}

GraduateTrial::main();

Set ad parameters for a keyword ad group criterion

<?php
/**
 * Copyright 2017 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace Google\AdsApi\Examples\AdWords\v201809\CampaignManagement;

require __DIR__ . '/../../../../vendor/autoload.php';

use Google\AdsApi\AdWords\AdWordsServices;
use Google\AdsApi\AdWords\AdWordsSession;
use Google\AdsApi\AdWords\AdWordsSessionBuilder;
use Google\AdsApi\AdWords\v201809\cm\AdParam;
use Google\AdsApi\AdWords\v201809\cm\AdParamOperation;
use Google\AdsApi\AdWords\v201809\cm\AdParamService;
use Google\AdsApi\AdWords\v201809\cm\Operator;
use Google\AdsApi\Common\OAuth2TokenBuilder;

/**
 * This example sets ad parameters for a keyword. To get keywords, run
 * BasicOperations/GetKeywords.php.
 */
class SetAdParameters
{

    const AD_GROUP_ID = 'INSERT_AD_GROUP_ID_HERE';
    const KEYWORD_ID = 'INSERT_KEYWORD_ID_HERE';

    public static function runExample(
        AdWordsServices $adWordsServices,
        AdWordsSession $session,
        $adGroupId,
        $keywordId
    ) {
        $adParamService = $adWordsServices->get($session, AdParamService::class);

        // Create ad parameters.
        $adParam1 = new AdParam($adGroupId, $keywordId, '100', 1);
        $adParam2 = new AdParam($adGroupId, $keywordId, '$40', 2);

        $adParamOperations = [];

        $adParamOperation1 = new AdParamOperation();
        $adParamOperation1->setOperand($adParam1);
        $adParamOperation1->setOperator(Operator::SET);
        $adParamOperations[] = $adParamOperation1;

        $adParamOperation2 = new AdParamOperation();
        $adParamOperation2->setOperand($adParam2);
        $adParamOperation2->setOperator(Operator::SET);
        $adParamOperations[] = $adParamOperation2;

        // Add ad params on the server.
        $adParams = $adParamService->mutate($adParamOperations);

        // Print out some information about added ad parameters.
        foreach ($adParams as $adParam) {
            printf(
                "Ad parameter with insertion text '%s' and parameter index %d was set.\n",
                $adParam->getInsertionText(),
                $adParam->getParamIndex()
            );
        }
    }

    public static function main()
    {
        // Generate a refreshable OAuth2 credential for authentication.
        $oAuth2Credential = (new OAuth2TokenBuilder())->fromFile()->build();

        // Construct an API session configured from a properties file and the
        // OAuth2 credentials above.
        $session = (new AdWordsSessionBuilder())->fromFile()->withOAuth2Credential($oAuth2Credential)->build();
        self::runExample(
            new AdWordsServices(),
            $session,
            intval(self::AD_GROUP_ID),
            intval(self::KEYWORD_ID)
        );
    }
}

SetAdParameters::main();

Set a bid modifier on a campaign

<?php
/**
 * Copyright 2017 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace Google\AdsApi\Examples\AdWords\v201809\CampaignManagement;

require __DIR__ . '/../../../../vendor/autoload.php';

use Google\AdsApi\AdWords\AdWordsServices;
use Google\AdsApi\AdWords\AdWordsSession;
use Google\AdsApi\AdWords\AdWordsSessionBuilder;
use Google\AdsApi\AdWords\v201809\cm\CampaignCriterion;
use Google\AdsApi\AdWords\v201809\cm\CampaignCriterionOperation;
use Google\AdsApi\AdWords\v201809\cm\CampaignCriterionService;
use Google\AdsApi\AdWords\v201809\cm\Operator;
use Google\AdsApi\AdWords\v201809\cm\Platform;
use Google\AdsApi\Common\OAuth2TokenBuilder;

/**
 * This example sets a bid modifier on a campaign.
 */
class SetBidModifier
{

    const CAMPAIGN_ID = 'INSERT_CAMPAIGN_ID_HERE';
    // Bid modifiers are float number, not percentages, e.g., 1.5 means 50% more
    // bidding.
    const BID_MODIFIER = 'INSERT_BID_MODIFIER_HERE';

    public static function runExample(
        AdWordsServices $adWordsServices,
        AdWordsSession $session,
        $campaignId,
        $bidModifier
    ) {
        $campaignCriterionService = $adWordsServices->get($session, CampaignCriterionService::class);

        // Create a mobile platform. The ID can be found in the documentation.
        // https://developers.google.com/adwords/api/docs/appendix/platforms
        $mobile = new Platform();
        $mobile->setId(30001); // HighEndMobile = 30001

        // Create a criterion with modified bid.
        $criterion = new CampaignCriterion();
        $criterion->setCampaignId($campaignId);
        $criterion->setCriterion($mobile);
        $criterion->setBidModifier($bidModifier);

        // Create a campaign criterion operation and add it to the operations list.
        $operation = new CampaignCriterionOperation();
        $operation->setOperator(Operator::SET);
        $operation->setOperand($criterion);
        $operations = [$operation];

        // Update campaign criteria on the server.
        $results = $campaignCriterionService->mutate($operations);

        // Print out some information about the updated campaign criterion.
        foreach ($results->getValue() as $campaignCriterion) {
            printf(
                "Campaign criterion with campaign ID %d, criterion ID %d, "
                . "and type '%s' was modified with bid %.2f.\n",
                $campaignCriterion->getCampaignId(),
                $campaignCriterion->getCriterion()->getId(),
                $campaignCriterion->getCriterion()->getType(),
                $campaignCriterion->getBidModifier()
            );
        }
    }

    public static function main()
    {
        // Generate a refreshable OAuth2 credential for authentication.
        $oAuth2Credential = (new OAuth2TokenBuilder())->fromFile()->build();

        // Construct an API session configured from a properties file and the
        // OAuth2 credentials above.
        $session = (new AdWordsSessionBuilder())->fromFile()->withOAuth2Credential($oAuth2Credential)->build();
        self::runExample(
            new AdWordsServices(),
            $session,
            intval(self::CAMPAIGN_ID),
            floatval(self::BID_MODIFIER)
        );
    }
}

SetBidModifier::main();

Validate text ad through setValidateOnly header

<?php
/**
 * Copyright 2017 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace Google\AdsApi\Examples\AdWords\v201809\CampaignManagement;

require __DIR__ . '/../../../../vendor/autoload.php';

use Google\AdsApi\AdWords\AdWordsServices;
use Google\AdsApi\AdWords\AdWordsSession;
use Google\AdsApi\AdWords\AdWordsSessionBuilder;
use Google\AdsApi\AdWords\v201809\cm\AdGroupAd;
use Google\AdsApi\AdWords\v201809\cm\AdGroupAdOperation;
use Google\AdsApi\AdWords\v201809\cm\AdGroupAdService;
use Google\AdsApi\AdWords\v201809\cm\ApiException;
use Google\AdsApi\AdWords\v201809\cm\ExpandedTextAd;
use Google\AdsApi\AdWords\v201809\cm\Operator;
use Google\AdsApi\Common\OAuth2TokenBuilder;

/**
 * This example validates a text ad without creating it using the validateOnly
 * mode, which can be useful when checking for policy violations.
 */
class ValidateTextAd
{

    const AD_GROUP_ID = 'INSERT_AD_GROUP_ID_HERE';

    public static function runExample(
        AdWordsServices $adWordsServices,
        AdWordsSession $session,
        $adGroupId
    ) {
        $session->setValidateOnly(true);
        $adGroupAdService = $adWordsServices->get($session, AdGroupAdService::class);

        $operations = [];
        // Create invalid expanded text ad.
        $expandedTextAd = new ExpandedTextAd();
        $expandedTextAd->setHeadlinePart1('Luxury Cruise to Mars !!!');
        $expandedTextAd->setHeadlinePart2('Visit the Red Planet in style.');
        $expandedTextAd->setDescription(
            'Low-gravity fun for all astronauts in orbit.'
        );
        $expandedTextAd->setFinalUrls(['http://www.example.com']);

        // Create ad group ad.
        $adGroupAd = new AdGroupAd();
        $adGroupAd->setAdGroupId($adGroupId);
        $adGroupAd->setAd($expandedTextAd);

        // Create ad group ad operation and add it to the list.
        $operation = new AdGroupAdOperation();
        $operation->setOperand($adGroupAd);
        $operation->setOperator(Operator::ADD);
        $operations[] = $operation;

        try {
            $adGroupAdService->mutate($operations);
            printf("The expanded text ad is valid.\n");
        } catch (ApiException $e) {
            $errors = $e->getErrors();
            if (count($errors) > 0) {
                printf("The expanded text ad is invalid for the following reasons:\n");
                foreach ($errors as $error) {
                    printf(
                        "  %s @ %s\n",
                        $error->getErrorString(),
                        $error->getFieldPath()
                    );
                }
            }
        }
    }

    public static function main()
    {
        // Generate a refreshable OAuth2 credential for authentication.
        $oAuth2Credential = (new OAuth2TokenBuilder())->fromFile()->build();

        // Construct an API session configured from a properties file and the
        // OAuth2 credentials above.
        $session = (new AdWordsSessionBuilder())->fromFile()->withOAuth2Credential($oAuth2Credential)->build();
        self::runExample(
            new AdWordsServices(),
            $session,
            intval(self::AD_GROUP_ID)
        );
    }
}

ValidateTextAd::main();