Migration Samples

The code samples below provide examples of common migration functions using the AdWords API. Client Library.

Migrate to extension settings

New

<?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\v201705\Migration;

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

use Google\AdsApi\AdWords\AdWordsServices;
use Google\AdsApi\AdWords\AdWordsSession;
use Google\AdsApi\AdWords\AdWordsSessionBuilder;
use Google\AdsApi\AdWords\v201705\cm\CampaignExtensionSetting;
use Google\AdsApi\AdWords\v201705\cm\CampaignExtensionSettingOperation;
use Google\AdsApi\AdWords\v201705\cm\CampaignExtensionSettingService;
use Google\AdsApi\AdWords\v201705\cm\CampaignFeedOperation;
use Google\AdsApi\AdWords\v201705\cm\CampaignFeedService;
use Google\AdsApi\AdWords\v201705\cm\ExtensionSetting;
use Google\AdsApi\AdWords\v201705\cm\ExtensionSettingPlatform;
use Google\AdsApi\AdWords\v201705\cm\FeedItem;
use Google\AdsApi\AdWords\v201705\cm\FeedItemOperation;
use Google\AdsApi\AdWords\v201705\cm\FeedItemService;
use Google\AdsApi\AdWords\v201705\cm\FeedMappingService;
use Google\AdsApi\AdWords\v201705\cm\FeedService;
use Google\AdsApi\AdWords\v201705\cm\FeedType;
use Google\AdsApi\AdWords\v201705\cm\FunctionOperand;
use Google\AdsApi\AdWords\v201705\cm\FunctionOperator;
use Google\AdsApi\AdWords\v201705\cm\Operator;
use Google\AdsApi\AdWords\v201705\cm\RequestContextOperand;
use Google\AdsApi\AdWords\v201705\cm\RequestContextOperandContextType;
use Google\AdsApi\AdWords\v201705\cm\SitelinkFeedItem;
use Google\AdsApi\Common\OAuth2TokenBuilder;

/**
 * Migrates your feed based sitelinks at campaign level to
 * use extension settings. To learn more about extension settings, see
 * https://developers.google.com/adwords/api/docs/guides/extension-settings
 * To learn more about migrating feed based extensions to extension
 * settings, see
 * https://developers.google.com/adwords/api/docs/guides/migrate-to-extension-settings
 */
class MigrateToExtensionSettings {

  // The placeholder type for sitelinks. See
  // https://developers.google.com/adwords/api/docs/appendix/placeholders
  // for the list of all supported placeholder types.
  const PLACEHOLDER_TYPE_SITELINKS = 1;

  // Placeholder field IDs for sitelinks. See
  // https://developers.google.com/adwords/api/docs/appendix/placeholders
  // for the list of all supported placeholder types.
  const PLACEHOLDER_FIELD_TEXT = 1;
  const PLACEHOLDER_FIELD_URL = 2;
  const PLACEHOLDER_FIELD_LINE2 = 3;
  const PLACEHOLDER_FIELD_LINE3 = 4;
  const PLACEHOLDER_FIELD_FINAL_URLS = 5;
  const PLACEHOLDER_FIELD_FINAL_MOBILE_URLS = 6;
  const PLACEHOLDER_FIELD_TRACKING_URL_TEMPLATE = 7;

  public static function runExample(AdWordsServices $adWordsServices,
      AdWordsSession $session) {
    $feeds = self::getFeeds($adWordsServices, $session);
    foreach ($feeds as $feed) {
      // Retrieve all the sitelinks from the current feed.
      $sitelinksFromFeed = self::getSitelinksFromFeed(
          $adWordsServices, $session, $feed->getId());
      printf("Loaded %d sitelinks for feed ID %d.\n", count($sitelinksFromFeed),
          $feed->getId());

      // Get all the instances where a sitelink from this feed has been added
      // to a campaign.
      $campaignFeeds = self::getCampaignFeeds(
          $adWordsServices,
          $session,
          $feed->getId(),
          self::PLACEHOLDER_TYPE_SITELINKS
      );
      printf("Loaded %d sitelink to campaign mappings for feed ID %d.\n",
          count($campaignFeeds), $feed->getId());

      if ($campaignFeeds !== null) {
        $allFeedItemsToDelete = [];
        foreach ($campaignFeeds as $campaignFeed) {
          // Retrieve the sitelinks that have been associated with this
          // campaign.
          $feedItemIds = self::getFeedItemIdsForCampaignFeed($campaignFeed);
          $platformRestrictions =
              self::getPlatformRestrictionsForCampaignFeed($campaignFeed);

          if ($feedItemIds === null) {
            printf(
                "Skipping feed ID %d for campaign %d -- matching function is "
                    . "missing or too complex for this script.\n",
                $campaignFeed->getFeedId(),
                $campaignFeed->getCampaignId()
            );
            continue;
          }

          // Delete the campaign feed that associates the sitelinks from the
          // feed to the campaign.
          self::deleteCampaignFeed($adWordsServices, $session, $campaignFeed);

          // Mark the sitelinks from the feed for deletion.
          $allFeedItemsToDelete =
              array_merge($allFeedItemsToDelete, $feedItemIds);

          // Create extension settings instead of sitelinks.
          self::createExtensionSetting(
              $adWordsServices,
              $session,
              $sitelinksFromFeed,
              $campaignFeed->getCampaignId(),
              $feedItemIds,
              $platformRestrictions);
        }

        // Delete all the sitelinks from the feed.
        $allFeedItemsToDelete = array_unique($allFeedItemsToDelete);
        self::deleteOldFeedItems(
            $adWordsServices,
            $session,
            $allFeedItemsToDelete,
            $feed->getId()
        );
      }
    }
  }

  /**
   * Gets all enabled feeds.
   */
  private static function getFeeds(AdWordsServices $adWordsServices,
      AdWordsSession $session) {
    $feedService = $adWordsServices->get($session, FeedService::class);
    $page = $feedService->query('SELECT Id, Name, Attributes WHERE '
        . 'Origin="USER" AND FeedStatus="ENABLED"');

    return $page->getEntries();
  }

  /**
   * Gets all enabled feed items of the specified feed.
   */
  private static function getFeedItems(AdWordsServices $adWordsServices,
      AdWordsSession $session, $feedId) {
    $feedItemService = $adWordsServices->get($session, FeedItemService::class);
    $page = $feedItemService->query(sprintf(
        'SELECT FeedItemId, AttributeValues, Scheduling WHERE '
            . 'Status = "ENABLED" AND FeedId = %d',
        $feedId
    ));

    return $page->getEntries();
  }

  /**
   * Gets all enabled campaign feeds for the specified feed and placeholder
   * type.
   */
  private static function getCampaignFeeds(AdWordsServices $adWordsServices,
      AdWordsSession $session, $feedId, $placeholderId) {
    $campaignFeedService =
        $adWordsServices->get($session, CampaignFeedService::class);
    $page = $campaignFeedService->query(sprintf(
        'SELECT CampaignId, MatchingFunction, PlaceholderTypes WHERE '
            . 'Status="ENABLED" AND FeedId = %d AND PlaceholderTypes '
            . 'CONTAINS_ANY[%d]',
        $feedId,
        $placeholderId
    ));

    return $page->getEntries();
  }

  /**
   * Gets attribute field mappings from the specified feed and placeholder type.
   */
  private static function getAttributeFieldMappings(
      AdWordsServices $adWordsServices,
      AdWordsSession $session,
      $feedId,
      $placeholderTypeId
  ) {
    $feedMappingService =
        $adWordsServices->get($session, FeedMappingService::class);
    $page = $feedMappingService->query(sprintf(
        'SELECT FeedMappingId, AttributeFieldMappings WHERE FeedId="%d" '
            . 'AND PlaceholderType="%d" AND Status="ENABLED"',
        $feedId,
        $placeholderTypeId
    ));

    $attributeMappings = [];
    if ($page->getEntries() !== null) {
      // Normally, a feed attribute is mapped only to one field. However,
      // you may map it to more than one field if needed.
      foreach ($page->getEntries() as $feedMapping) {
        foreach ($feedMapping->getAttributeFieldMappings()
            as $attributeMapping) {
          if (array_key_exists($attributeMapping->getFeedAttributeId(),
              $attributeMappings) === false) {
            $attributeMappings[$attributeMapping->getFeedAttributeId()] = [];
          }
          $attributeMappings[$attributeMapping->getFeedAttributeId()][] =
              $attributeMapping->getFieldId();
        }
      }
    }

    return $attributeMappings;
  }

  /**
   * Gets sitelinks from the specified feed.
   */
  private static function getSitelinksFromFeed(AdWordsServices $adWordsServices,
      AdWordsSession $session, $feedId) {
    printf("Processing feed ID %d...\n", $feedId);
    $sitelinks = [];

    // Retrieve all the feed items from the feed.
    $feedItems = self::getFeedItems($adWordsServices, $session, $feedId);

    if ($feedItems !== null) {
      // Retrieve the feed's attribute mapping.
      $attributeFieldMappings = self::getAttributeFieldMappings(
          $adWordsServices,
          $session,
          $feedId,
          self::PLACEHOLDER_TYPE_SITELINKS
      );

      foreach ($feedItems as $feedItem) {
        $sitelinkFromFeed = new SitelinkFromFeed(
            $feedItem->getFeedId(), $feedItem->getFeedItemId());

        foreach ($feedItem->getAttributeValues() as $attributeValue) {
          // This attribute hasn't been mapped to a field.
          if (array_key_exists($attributeValue->getFeedAttributeId(),
              $attributeFieldMappings) === false) {
            continue;
          }
          // Get the list of all the fields to which this attribute has been
          // mapped.
          foreach ($attributeFieldMappings[
              $attributeValue->getFeedAttributeId()] as $fieldId) {
            // Read the appropriate value depending on the ID of the mapped
            // field.
            switch ($fieldId) {
              case self::PLACEHOLDER_FIELD_TEXT:
                $sitelinkFromFeed->setText($attributeValue->getStringValue());
                break;
              case self::PLACEHOLDER_FIELD_URL:
                $sitelinkFromFeed->setUrl($attributeValue->getStringValue());
                break;
              case self::PLACEHOLDER_FIELD_FINAL_URLS:
                $sitelinkFromFeed->setFinalUrls(
                    $attributeValue->getStringValues());
                break;
              case self::PLACEHOLDER_FIELD_FINAL_MOBILE_URLS:
                $sitelinkFromFeed->setFinalMobileUrls(
                    $attributeValue->getStringValues());
                break;
              case self::PLACEHOLDER_FIELD_TRACKING_URL_TEMPLATE:
                $sitelinkFromFeed->setTrackingUrlTemplate(
                    $attributeValue->getStringValue());
                break;
              case self::PLACEHOLDER_FIELD_LINE2:
                $sitelinkFromFeed->setLine2($attributeValue->getStringValue());
                break;
              case self::PLACEHOLDER_FIELD_LINE3:
                $sitelinkFromFeed->setLine3($attributeValue->getStringValue());
                break;
            }
          }
        }
        $sitelinkFromFeed->setScheduling($feedItem->getScheduling());
        $sitelinks[$feedItem->getFeedItemId()] = $sitelinkFromFeed;
      }
    }

    return $sitelinks;
  }

  /**
   * Gets plaftform restrictions for the specified campaign feed.
   */
  private static function getPlatformRestrictionsForCampaignFeed(
      $campaignFeed) {
    $platformRestrictions = ExtensionSettingPlatform::NONE;

    if ($campaignFeed->getMatchingFunction()->getOperator()
        === FunctionOperator::AND_VALUE) {
      foreach ($campaignFeed->getMatchingFunction()->getLhsOperand()
          as $argument) {
        if ($argument instanceof FunctionOperand) {
          if ($argument->getValue()->getOperator() === FunctionOperator::EQUALS
              && $argument->getValue()->getLhsOperand()[0]
                  instanceof RequestContextOperand) {
            $requestContextOperand = $argument->getValue()->getLhsOperand()[0];
            if ($requestContextOperand->getContextType()
                === RequestContextOperandContextType::DEVICE_PLATFORM) {
              $platformRestrictions = strtoupper(
                  $argument->getValue()->getRhsOperand()[0]->getStringValue());
            }
          }
        }
      }
    }

    return $platformRestrictions;
  }

  /**
   * Gets feed item IDs from the specified campaign feed.
   */
  private static function getFeedItemIdsForCampaignFeed($campaignFeed) {
    $feedItemIds = [];

    if ($campaignFeed->getMatchingFunction()->getOperator()
        === FunctionOperator::IN) {
      // Check if matchingFunction is of the form IN(FEED_ITEM_ID,{xxx,xxx}).
      // Extract feed items if applicable.
      $feedItemIds = array_merge(
          $feedItemIds,
          self::getFeedItemIdsFromArgument($campaignFeed->getMatchingFunction())
      );
    } else if ($campaignFeed->getMatchingFunction()->getOperator()
        === FunctionOperator::AND_VALUE) {
      foreach ($campaignFeed->getMatchingFunction()->getLhsOperand()
          as $argument) {
        // Check if matchingFunction is of the form IN(FEED_ITEM_ID,{xxx,xxx}).
        // Extract feed items if applicable.
        if ($argument instanceof FunctionOperand) {
          if ($argument->getValue()->getOperator() === FunctionOperator::IN) {
            $feedItemIds = array_merge(
                $feedItemIds,
                self::getFeedItemIdsFromArgument($argument->getValue())
            );
          }
        }
      }
    }

    return $feedItemIds;
  }

  /**
   * Gets feed item IDs from the specified function argument.
   */
  private static function getFeedItemIdsFromArgument($function) {
    $feedItemIds = [];

    if (count($function->getLhsOperand()) === 1
        && $function->getLhsOperand()[0] instanceof RequestContextOperand
        && $function->getLhsOperand()[0]->getContextType()
            === RequestContextOperandContextType::FEED_ITEM_ID
        && $function->getOperator() === FunctionOperator::IN) {
      foreach ($function->getRhsOperand() as $argument) {
        $feedItemIds[] = $argument->getLongValue();
      }
    }

    return $feedItemIds;
  }

  /**
   * Creates a new extension setting for the specified feed items.
   */
  private static function createExtensionSetting(
      AdWordsServices $adWordsServices,
      AdWordsSession $session,
      array $sitelinksFromFeed,
      $campaignId,
      array $feedItemIds,
      $platformRestrictions
  ) {
    $campaignExtensionSettingService =
        $adWordsServices->get($session, CampaignExtensionSettingService::class);

    $extensionSetting = new CampaignExtensionSetting();
    $extensionSetting->setCampaignId($campaignId);
    $extensionSetting->setExtensionType(FeedType::SITELINK);
    $extensionSetting->setExtensionSetting(new ExtensionSetting());

    $extensionFeedItems = [];
    foreach ($feedItemIds as $feedItemId) {
      $sitelink = $sitelinksFromFeed[$feedItemId];

      $newFeedItem = new SitelinkFeedItem();
      $newFeedItem->setSitelinkText($sitelink->getText());
      $newFeedItem->setSitelinkUrl($sitelink->getUrl());
      $newFeedItem->setSitelinkLine2($sitelink->getLine2());
      $newFeedItem->setSitelinkLine3($sitelink->getLine3());
      $newFeedItem->setSitelinkFinalUrls($sitelink->getFinalUrls());
      $newFeedItem->setSitelinkFinalMobileUrls($sitelink->getFinalMobileUrls());
      $newFeedItem->setSitelinkTrackingUrlTemplate(
          $sitelink->getTrackingUrlTemplate());
      $newFeedItem->setScheduling($sitelink->getScheduling());

      $extensionFeedItems[] = $newFeedItem;
    }
    $extensionSetting->getExtensionSetting()->setExtensions(
        $extensionFeedItems);
    $extensionSetting->getExtensionSetting()->setPlatformRestrictions(
        $platformRestrictions);

    $operation = new CampaignExtensionSettingOperation();
    $operation->setOperand($extensionSetting);
    $operation->setOperator(Operator::ADD);

    printf("Adding %d sitelinks for campaign ID %d...\n",
        count($feedItemIds), $campaignId);

    return $campaignExtensionSettingService->mutate([$operation]);
  }

  /**
   * Deletes associations of the specified feed IDs and campaign IDs.
   */
  private static function deleteCampaignFeed(AdWordsServices $adWordsServices,
      AdWordsSession $session, $campaignFeed) {
    $campaignFeedService =
        $adWordsServices->get($session, CampaignFeedService::class);

    printf("Deleting association of feed ID %d and campaign ID %d...\n",
        $campaignFeed->getFeedId(), $campaignFeed->getCampaignId());

    $operation = new CampaignFeedOperation();
    $operation->setOperand($campaignFeed);
    $operation->setOperator(Operator::REMOVE);

    return $campaignFeedService->mutate([$operation]);
  }

  /**
   * Deletes old feed items that became unused anymore after migration.
   */
  private static function deleteOldFeedItems(AdWordsServices $adWordsServices,
      AdWordsSession $session, $feedItemIds, $feedId) {
    if (count($feedItemIds) === 0) {
      return;
    }

    $feedItemService = $adWordsServices->get($session, FeedItemService::class);

    $operations = [];
    foreach ($feedItemIds as $feedItemId) {
      $feedItem = new FeedItem();
      $feedItem->setFeedId($feedId);
      $feedItem->setFeedItemId($feedItemId);

      $operation = new FeedItemOperation();
      $operation->setOperand($feedItem);
      $operation->setOperator(Operator::REMOVE);
      $operations[] = $operation;
    }

    printf("Deleting %d old feed items from feed ID %d...\n",
        count($feedItemIds), $feedId);

    return $feedItemService->mutate($operations);
  }

  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);
  }
}

class SitelinkFromFeed {

  private $feedId;
  private $feedItemId;
  private $text;
  private $url;
  private $finalUrls;
  private $finalMobileUrls;
  private $trackingUrlTemplate;
  private $line2;
  private $line3;
  private $scheduling;

  public function __construct($feedId = null, $feedItemId = null) {
    $this->feedId = $feedId;
    $this->feedItemId = $feedItemId;
  }

  public function getFeedId() {
    return $this->feedId;
  }

  public function getFeedItemId() {
    return $this->feedItemId;
  }

  public function getText() {
    return $this->text;
  }

  public function getUrl() {
    return $this->url;
  }

  public function getFinalUrls() {
    return $this->finalUrls;
  }

  public function getFinalMobileUrls() {
    return $this->finalMobileUrls;
  }

  public function getTrackingUrlTemplate() {
    return $this->trackingUrlTemplate;
  }

  public function getLine2() {
    return $this->line2;
  }

  public function getLine3() {
    return $this->line3;
  }

  public function getScheduling() {
    return $this->scheduling;
  }

  public function setFeedId($feedId) {
    $this->feedId = $feedId;
  }

  public function setFeedItemId($feedItemId) {
    $this->feedItemId = $feedItemId;
  }

  public function setText($text) {
    $this->text = $text;
  }

  public function setUrl($url) {
    $this->url = $url;
  }

  public function setFinalUrls(array $finalUrls) {
    $this->finalUrls = $finalUrls;
  }

  public function setFinalMobileUrls(array $finalMobileUrls) {
    $this->finalMobileUrls = $finalMobileUrls;
  }

  public function setTrackingUrlTemplate($trackingUrlTemplate) {
    $this->trackingUrlTemplate = $trackingUrlTemplate;
  }

  public function setLine2($line2) {
    $this->line2 = $line2;
  }

  public function setLine3($line3) {
    $this->line3 = $line3;
  }

  public function setScheduling($scheduling) {
    $this->scheduling = $scheduling;
  }
}

MigrateToExtensionSettings::main();

Old

<?php
/**
 * This code example migrates your feed based sitelinks at campaign level to
 * use extension settings. To learn more about extensionsettings, see
 * https://developers.google.com/adwords/api/docs/guides/extension-settings
 * To learn more about migrating Feed based extensions to extension
 * settings, see
 * https://developers.google.com/adwords/api/docs/guides/migrate-to-extension-settings
 *
 * Copyright 2016, 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.
 *
 * @package    GoogleApiAdsAdWords
 * @subpackage v201705
 * @category   WebServices
 * @copyright  2016, Google Inc. All Rights Reserved.
 * @license    http://www.apache.org/licenses/LICENSE-2.0 Apache License,
 *             Version 2.0
 */

// Include the initialization file
require_once dirname(dirname(__FILE__)) . '/init.php';

// The placeholder type for sitelinks. See
// https://developers.google.com/adwords/api/docs/appendix/placeholders
// for the list of all supported placeholder types.
define('PLACEHOLDER_TYPE_SITELINKS', 1);

// Placeholder field IDs for sitelinks. See
// https://developers.google.com/adwords/api/docs/appendix/placeholders
// for the list of all supported placeholder types.
define('PLACEHOLDER_FIELD_TEXT', 1);
define('PLACEHOLDER_FIELD_URL', 2);
define('PLACEHOLDER_FIELD_LINE2', 3);
define('PLACEHOLDER_FIELD_LINE3', 4);
define('PLACEHOLDER_FIELD_FINAL_URLS', 5);
define('PLACEHOLDER_FIELD_FINAL_MOBILE_URLS', 6);
define('PLACEHOLDER_FIELD_TRACKING_URL_TEMPLATE', 7);

class SitelinkFromFeed {
  public $feedId;
  public $feedItemId;
  public $text;
  public $url;
  public $finalUrls;
  public $finalMobileUrls;
  public $trackingUrlTemplate;
  public $line2;
  public $line3;
  public $scheduling;

  public function __construct($feedId = null, $feedItemId = null) {
    $this->feedId = $feedId;
    $this->feedItemId = $feedItemId;
  }
}

/**
 * Runs the example.
 * @param AdWordsUser $user the user to run the example with
 */
function MigrateToExtensionSettingsExample(AdWordsUser $user) {
  $feeds = GetFeeds($user);
  foreach ($feeds as $feed) {
    // Retrieve all the sitelinks from the current feed.
    $feedItems = GetSitelinksFromFeed($user, $feed->id);
    printf("Loaded %d sitelinks for feed ID %d.\n",
           count($feedItems), $feed->id);

    // Get all the instances where a sitelink from this feed has been added
    // to a campaign.
    $campaignFeeds =
        GetCampaignFeeds($user, $feed->id, PLACEHOLDER_TYPE_SITELINKS);
    printf("Loaded %d sitelink to campaign mappings for feed ID %d.\n",
           count($campaignFeeds), $feed->id);

    if (!empty($campaignFeeds)) {
      $allFeedItemsToDelete = array();
      foreach ($campaignFeeds as $campaignFeed) {
        // Retrieve the sitelinks that have been associated with this campaign.
        $feedItemIds = GetFeedItemsForCampaign($campaignFeed);
        $platformRestrictions =
            GetPlatformRestrictionsForCampaign($campaignFeed);

        if(empty($feedItemIds)) {
          printf("Skipping feed ID %d for campaign %d -- matching function is "
              . "missing or too complex for this script.\n",
              $campaignFeed->feedId, $campaignFeed->campaignId);
          continue;
        }

        // Delete the campaign feed that associates the sitelinks from the feed
        // to the campaign.
        DeleteCampaignFeed($user, $campaignFeed);

        // Mark the sitelinks from the feed for deletion.
        $allFeedItemsToDelete =
            array_merge($allFeedItemsToDelete, $feedItemIds);

        // Create extension settings instead of sitelinks.
        CreateExtensionSetting(
            $user, $feedItems, $campaignFeed->campaignId, $feedItemIds,
            $platformRestrictions);
      }
      // Delete all the sitelinks from the feed.
      $allFeedItemsToDelete = array_unique($allFeedItemsToDelete);
      DeleteOldFeedItems($user, $allFeedItemsToDelete, $feed->id);

    }
  }
}

function GetFeeds($user) {
  $feedService = $user->GetService('FeedService', ADWORDS_VERSION);
  $page = $feedService->query('SELECT Id, Name, Attributes WHERE '
      . 'Origin="USER" AND FeedStatus="ENABLED"');
  return $page->entries;
}

function GetFeedItems($user, $feedId) {
  $feedItemService = $user->GetService('FeedItemService', ADWORDS_VERSION);
  $page = $feedItemService->query(
      sprintf('SELECT FeedItemId, AttributeValues, Scheduling WHERE '
          . 'Status = "ENABLED" AND FeedId = %d', $feedId));
  return $page->entries;
}

function GetCampaignFeeds($user, $feedId, $placeholderId) {
  $campaignFeedService =
      $user->GetService('CampaignFeedService', ADWORDS_VERSION);

  $page = $campaignFeedService->query(
      sprintf('SELECT CampaignId, MatchingFunction, PlaceholderTypes WHERE '
          . 'Status="ENABLED" AND FeedId = %d AND PlaceholderTypes '
          . 'CONTAINS_ANY[%d]', $feedId, $placeholderId));
  return $page->entries;
}

function GetFeedMapping($user, $feedId, $placeholderTypeId) {
  $feedMappingService =
      $user->GetService('FeedMappingService', ADWORDS_VERSION);
  $page = $feedMappingService->query(
      sprintf('SELECT FeedMappingId, AttributeFieldMappings WHERE FeedId="%d" '
          . 'AND PlaceholderType="%d" AND Status="ENABLED"',
          $feedId, $placeholderTypeId));
  $attributeMappings = array();
  if (!empty($page->entries)) {
    // Normally, a feed attribute is mapped only to one field. However,
    // you may map it to more than one field if needed.
    foreach ($page->entries as $feedMapping) {
      foreach ($feedMapping->attributeFieldMappings as $attributeMapping) {
        if (!isset($attributeMappings[$attributeMapping->feedAttributeId])) {
          $attributeMappings[$attributeMapping->feedAttributeId] = array();
        }
        $attributeMappings[$attributeMapping->feedAttributeId][] =
            $attributeMapping->fieldId;
      }
    }
  }
  return $attributeMappings;
}

function GetSitelinksFromFeed($user, $feedId) {
  printf("Processing feed ID %d...\n", $feedId);
  $sitelinks = array();

  // Retrieve all the feed items from the feed.
  $feedItems = GetFeedItems($user, $feedId);

  if (!empty($feedItems)) {
    // Retrieve the feed's attribute mapping.
    $feedMappings = GetFeedMapping($user, $feedId, PLACEHOLDER_TYPE_SITELINKS);

    foreach ($feedItems as $feedItem) {
      $sitelinkFromFeed =
          new SitelinkFromFeed($feedItem->feedId, $feedItem->feedItemId);

      foreach ($feedItem->attributeValues as $attributeValue) {
        // This attribute hasn't been mapped to a field.
        if (!isset($feedMappings[$attributeValue->feedAttributeId])) {
          continue;
        }
        // Get the list of all the fields to which this attribute has been
        //  mapped.
        foreach ($feedMappings[$attributeValue->feedAttributeId] as $fieldId) {
          // Read the appropriate value depending on the ID of the mapped field.
          switch ($fieldId) {
            case PLACEHOLDER_FIELD_TEXT:
              $sitelinkFromFeed->text = $attributeValue->stringValue;
              break;
            case PLACEHOLDER_FIELD_URL:
              $sitelinkFromFeed->url = $attributeValue->stringValue;
              break;
            case PLACEHOLDER_FIELD_FINAL_URLS:
              $sitelinkFromFeed->finalUrls = $attributeValue->stringValues;
              break;
            case PLACEHOLDER_FIELD_FINAL_MOBILE_URLS:
              $sitelinkFromFeed->finalMobileUrls =
                  $attributeValue->stringValues;
              break;
            case PLACEHOLDER_FIELD_TRACKING_URL_TEMPLATE:
              $sitelinkFromFeed->trackingUrlTemplate =
                  $attributeValue->stringValue;
              break;
            case PLACEHOLDER_FIELD_LINE2:
              $sitelinkFromFeed->line2 = $attributeValue->stringValue;
              break;
            case PLACEHOLDER_FIELD_LINE3:
              $sitelinkFromFeed->line3 = $attributeValue->stringValue;
              break;
          }
        }
      }
      $sitelinkFromFeed->scheduling = $feedItem->scheduling;
      $sitelinks[$feedItem->feedItemId] = $sitelinkFromFeed;
    }
  }
  return $sitelinks;
}

function GetPlatformRestrictionsForCampaign($campaignFeed) {
  $platformRestrictions = 'NONE';
  if ($campaignFeed->matchingFunction->operator == 'AND') {
    foreach ($campaignFeed->matchingFunction->lhsOperand as $argument) {
      if (get_class($argument) == 'FunctionOperand') {
        if ($argument->value->operator == 'EQUALS' &&
            get_class($argument->value->lhsOperand[0]) ==
            'RequestContextOperand') {
          $requestContextOperand = $argument->value->lhsOperand[0];
          if ($requestContextOperand->contextType == 'DEVICE_PLATFORM') {
            $platformRestrictions =
                strtoupper($argument->value->rhsOperand[0]->stringValue);
          }
        }
      }
    }
  }
  return $platformRestrictions;
}

function GetFeedItemsForCampaign($campaignFeed) {
  $feedItems = array();

  if ($campaignFeed->matchingFunction->operator == 'IN') {
    // Check if matchingFunction is of the form IN(FEED_ITEM_ID,{xxx,xxx}).
    // Extract feed items if applicable.
    $feedItems = array_merge($feedItems,
        GetFeedItemsFromArgument($campaignFeed->matchingFunction));
  } else if ($campaignFeed->matchingFunction->operator == 'AND') {
    foreach ($campaignFeed->matchingFunction->lhsOperand as $argument) {
      // Check if matchingFunction is of the form IN(FEED_ITEM_ID,{xxx,xxx}).
      // Extract feed items if applicable.
      if (get_class($argument) == 'FunctionOperand') {
        if ($argument->value->operator == 'IN') {
          $feedItems = array_merge($feedItems,
              GetFeedItemsFromArgument($argument->value));
        }
      }
    }
  }
  // There are no other matching functions involving feed item IDs.
  return $feedItems;
}

function GetFeedItemsFromArgument($function) {
  $feedItems = array();

  if (count($function->lhsOperand) == 1 &&
      get_class($function->lhsOperand[0]) ==
      'RequestContextOperand' &&
      $function->lhsOperand[0]->contextType ==
      'FEED_ITEM_ID' &&
      $function->operator == 'IN') {
    foreach ($function->rhsOperand as $argument) {
      $feedItems[] = $argument->longValue;
    }
  }
  return $feedItems;
}

function CreateExtensionSetting($user, $feedItems, $campaignId, $feedItemIds,
    $platformRestrictions) {
  $campaignExtensionSettingService =
      $user->GetService('CampaignExtensionSettingService', ADWORDS_VERSION);

  $extensionSetting = new CampaignExtensionSetting();
  $extensionSetting->campaignId = $campaignId;
  $extensionSetting->extensionType = 'SITELINK';
  $extensionSetting->extensionSetting = new ExtensionSetting();

  $extensionFeedItems = array();
  foreach ($feedItemIds as $feedItemId) {
    $feedItem = $feedItems[$feedItemId];
    $newFeedItem = new SitelinkFeedItem($feedItem->text, $feedItem->url,
        $feedItem->line2, $feedItem->line3, $feedItem->finalUrls,
        $feedItem->finalMobileUrls, $feedItem->trackingUrlTemplate, null, null,
        null, null, null, null, null, $feedItem->scheduling);
    $extensionFeedItems[] = $newFeedItem;
  }
  $extensionSetting->extensionSetting->extensions = $extensionFeedItems;
  $extensionSetting->extensionSetting->platformRestrictions =
      $platformRestrictions;
  $extensionSetting->extensionType = 'SITELINK';

  $operation = new CampaignExtensionSettingOperation($extensionSetting, 'ADD');

  printf("Adding %d sitelinks for campaign ID %d...\n",
      count($feedItemIds), $campaignId);

  return $campaignExtensionSettingService->mutate(array($operation));
}

function DeleteCampaignFeed($user, $campaignFeed) {
  $campaignFeedService =
      $user->GetService('CampaignFeedService', ADWORDS_VERSION);

  printf("Deleting association of feed ID %d and and campaign ID %d...\n",
      $campaignFeed->feedId, $campaignFeed->campaignId);

  $operation = new CampaignFeedOperation($campaignFeed, 'REMOVE');
  return $campaignFeedService->mutate(array($operation));
}

function DeleteOldFeedItems($user, $feedItemIds, $feedId) {
  if (empty($feedItemIds)) {
    return;
  }

  $feedItemService = $user->GetService('FeedItemService', ADWORDS_VERSION);

  $operations = array();
  foreach ($feedItemIds as $feedItemId) {
    $feedItem = new FeedItem();
    $feedItem->feedId = $feedId;
    $feedItem->feedItemId = $feedItemId;
    $operation = new FeedItemOperation($feedItem, 'REMOVE');
    $operations[] = $operation;
  }

  printf("Deleting %d old feed items from feed ID %d...\n",
      count($feedItemIds), $feedId);

  return $feedItemService->mutate($operations);
}

// Don't run the example if the file is being included.
if (__FILE__ != realpath($_SERVER['PHP_SELF'])) {
  return;
}

try {
  // Get AdWordsUser from credentials in '../auth.ini'
  // relative to the AdWordsUser.php file's directory.
  $user = new AdWordsUser();

  // Log every SOAP XML request and response.
  $user->LogAll();

  // Run the example.
  MigrateToExtensionSettingsExample($user);
} catch (Exception $e) {
  printf("An error has occurred: %s\n", $e->getMessage());
}

Send feedback about...

AdWords API
AdWords API
Need help? Visit our support page.