/// <summary>
    /// Creates a CustomerFeed that will associate the data holder's Feed with
    /// the ad customizer placeholder type.
    /// </summary>
    /// <param name="user">The AdWords user.</param>
    /// <param name="dataHolder">The data holder that contains metadata about
    /// the customizer Feed.</param>
    private static void CreateCustomerFeed(AdWordsUser user, CustomizersDataHolder dataHolder) {
      // Get the CustomerFeedService.
      CustomerFeedService customerFeedService = (CustomerFeedService) user.GetService(
          AdWordsService.v201409.CustomerFeedService);

      CustomerFeed customerFeed = new CustomerFeed();
      customerFeed.feedId = dataHolder.FeedId;
      customerFeed.placeholderTypes = new int[] { PLACEHOLDER_AD_CUSTOMIZER };

      // Create a matching function that will always evaluate to true.
      Function customerMatchingFunction = new Function();
      ConstantOperand constOperand = new ConstantOperand();
      constOperand.type = ConstantOperandConstantType.BOOLEAN;
      constOperand.booleanValue = true;
      customerMatchingFunction.lhsOperand = new FunctionArgumentOperand[] { constOperand };
      customerMatchingFunction.@operator = FunctionOperator.IDENTITY;
      customerFeed.matchingFunction = customerMatchingFunction;

      // Create an operation to add the customer feed.
      CustomerFeedOperation customerFeedOperation = new CustomerFeedOperation();
      customerFeedOperation.operand = customerFeed;
      customerFeedOperation.@operator = Operator.ADD;

      CustomerFeed addedCustomerFeed = customerFeedService.mutate(
          new CustomerFeedOperation[] { customerFeedOperation }).value[0];

      Console.WriteLine("Customer feed for feed ID {0} was added.", addedCustomerFeed.feedId);
    }
    /// <summary>
    /// Runs the code example.
    /// </summary>
    /// <param name="user">The AdWords user.</param>
    /// <param name="gmbEmailAddress">The email address for Google My Business
    /// account.</param>
    /// <param name="gmbAccessToken">The OAuth2 access token for Google
    /// My Business account.</param>
    /// <param name="businessAccountIdentifier">The account identifier for
    /// Google My Business account.</param>
    public void Run(AdWordsUser user, string gmbEmailAddress, string gmbAccessToken,
        string businessAccountIdentifier) {
      FeedService feedService = (FeedService) user.GetService(AdWordsService.v201409.FeedService);

      CustomerFeedService customerFeedService = (CustomerFeedService) user.GetService(
          AdWordsService.v201409.CustomerFeedService);

      // Create a feed that will sync to the Google My Business account
      // specified by gmbEmailAddress. Do not add FeedAttributes to this object,
      // as AdWords will add them automatically because this will be a
      // system generated feed.
      Feed gmbFeed = new Feed();
      gmbFeed.name = String.Format("Google My Business feed #{0}",
          ExampleUtilities.GetRandomString());

      PlacesLocationFeedData feedData = new PlacesLocationFeedData();
      feedData.emailAddress = gmbEmailAddress;
      feedData.businessAccountIdentifier = businessAccountIdentifier;

      OAuthInfo oAuthInfo = new OAuthInfo();
      oAuthInfo.httpMethod = "GET";

      // Permissions for the AdWords API scope will also cover GMB.
      oAuthInfo.httpRequestUrl = user.Config.GetDefaultOAuth2Scope();
      oAuthInfo.httpAuthorizationHeader = string.Format("Bearer {0}", gmbAccessToken);
      feedData.oAuthInfo = oAuthInfo;

      gmbFeed.systemFeedGenerationData = feedData;

      // Since this feed's feed items will be managed by AdWords,
      // you must set its origin to ADWORDS.
      gmbFeed.origin = FeedOrigin.ADWORDS;

      // Create an operation to add the feed.
      FeedOperation feedOperation = new FeedOperation();
      feedOperation.operand = gmbFeed;
      feedOperation.@operator = Operator.ADD;

      try {
        // Add the feed. Since it is a system generated feed, AdWords will
        // automatically:
        // 1. Set up the FeedAttributes on the feed.
        // 2. Set up a FeedMapping that associates the FeedAttributes of the
        //    feed with the placeholder fields of the LOCATION placeholder
        //    type.
        FeedReturnValue addFeedResult = feedService.mutate(new FeedOperation[] { feedOperation });
        Feed addedFeed = addFeedResult.value[0];
        Console.WriteLine("Added GMB feed with ID {0}", addedFeed.id);

        // Add a CustomerFeed that associates the feed with this customer for
        // the LOCATION placeholder type.
        CustomerFeed customerFeed = new CustomerFeed();
        customerFeed.feedId = addedFeed.id;
        customerFeed.placeholderTypes = new int[] { PLACEHOLDER_LOCATION };

        // Create a matching function that will always evaluate to true.
        Function customerMatchingFunction = new Function();
        ConstantOperand constOperand = new ConstantOperand();
        constOperand.type = ConstantOperandConstantType.BOOLEAN;
        constOperand.booleanValue = true;
        customerMatchingFunction.lhsOperand = new FunctionArgumentOperand[] { constOperand };
        customerMatchingFunction.@operator = FunctionOperator.IDENTITY;
        customerFeed.matchingFunction = customerMatchingFunction;

        // Create an operation to add the customer feed.
        CustomerFeedOperation customerFeedOperation = new CustomerFeedOperation();
        customerFeedOperation.operand = customerFeed;
        customerFeedOperation.@operator = Operator.ADD;

        // After the completion of the Feed ADD operation above the added feed
        // will not be available for usage in a CustomerFeed until the sync
        // between the AdWords and GMB accounts completes.  The loop below
        // will retry adding the CustomerFeed up to ten times with an
        // exponential back-off policy.
        CustomerFeed addedCustomerFeed = null;

        AdWordsAppConfig config = new AdWordsAppConfig();
        config.RetryCount = 10;

        ErrorHandler errorHandler = new ErrorHandler(config);
        do {
          try {
            CustomerFeedReturnValue customerFeedResult =
                customerFeedService.mutate(new CustomerFeedOperation[] { customerFeedOperation });
            addedCustomerFeed = customerFeedResult.value[0];

            Console.WriteLine("Added CustomerFeed for feed ID {0} and placeholder type {1}",
                addedCustomerFeed.feedId, addedCustomerFeed.placeholderTypes[0]);
            break;
          } catch (AdWordsApiException e) {
            ApiException apiException = (ApiException) e.ApiException;
            foreach (ApiError error in apiException.errors) {
              if (error is CustomerFeedError) {
                if ((error as CustomerFeedError).reason ==
                    CustomerFeedErrorReason.MISSING_FEEDMAPPING_FOR_PLACEHOLDER_TYPE) {
                  errorHandler.DoExponentialBackoff();
                  errorHandler.IncrementRetriedAttempts();
                } else {
                  throw;
                }
              }
            }
          }
        } while (errorHandler.HaveMoreRetryAttemptsLeft());

        // OPTIONAL: Create a CampaignFeed to specify which FeedItems to use at
        // the Campaign level.  This will be similar to the CampaignFeed in the
        // AddSiteLinks example, except you can also filter based on the
        // business name and category of each FeedItem by using a
        // FeedAttributeOperand in your matching function.

        // OPTIONAL: Create an AdGroupFeed for even more fine grained control
        // over which feed items are used at the AdGroup level.
      } catch (Exception ex) {
        throw new System.ApplicationException("Failed to create customer feed.", ex);
      }
    }
    /// <summary>
    /// Runs the code example.
    /// </summary>
    /// <param name="user">The AdWords user.</param>
    /// <param name="campaignId">Id of the campaign to which targeting criteria
    /// are added.</param>
    public void Run(AdWordsUser user, long campaignId) {
      // Get the CampaignCriterionService.
      CampaignCriterionService campaignCriterionService =
          (CampaignCriterionService) user.GetService(
              AdWordsService.v201409.CampaignCriterionService);

      // Create language criteria.
      // See http://code.google.com/apis/adwords/docs/appendix/languagecodes.html
      // for a detailed list of language codes.
      Language language1 = new Language();
      language1.id = 1002; // French
      CampaignCriterion languageCriterion1 = new CampaignCriterion();
      languageCriterion1.campaignId = campaignId;
      languageCriterion1.criterion = language1;

      Language language2 = new Language();
      language2.id = 1005; // Japanese
      CampaignCriterion languageCriterion2 = new CampaignCriterion();
      languageCriterion2.campaignId = campaignId;
      languageCriterion2.criterion = language2;

      // Target Tier 3 income group near Miami, Florida.
      LocationGroups incomeLocationGroups = new LocationGroups();

      IncomeOperand incomeOperand = new IncomeOperand();
      // Tiers are numbered 1-10, and represent 10% segments of earners.
      // For example, TIER_1 is the top 10%, TIER_2 is the 80-90%, etc.
      // Tiers 6 through 10 are grouped into TIER_6_TO_10.
      incomeOperand.tier = IncomeTier.TIER_3;

      GeoTargetOperand geoTargetOperand1 = new GeoTargetOperand();
      geoTargetOperand1.locations = new long[] {1015116}; // Miami, FL.

      incomeLocationGroups.matchingFunction = new Function();
      incomeLocationGroups.matchingFunction.lhsOperand =
          new FunctionArgumentOperand[] {incomeOperand};
      incomeLocationGroups.matchingFunction.@operator = FunctionOperator.AND;
      incomeLocationGroups.matchingFunction.rhsOperand =
          new FunctionArgumentOperand[] {geoTargetOperand1};

      CampaignCriterion locationGroupCriterion1 = new CampaignCriterion();
      locationGroupCriterion1.campaignId = campaignId;
      locationGroupCriterion1.criterion = incomeLocationGroups;

      // Target places of interest near Downtown Miami, Florida.
      LocationGroups interestLocationGroups = new LocationGroups();

      PlacesOfInterestOperand placesOfInterestOperand = new PlacesOfInterestOperand();
      placesOfInterestOperand.category = PlacesOfInterestOperandCategory.DOWNTOWN;

      GeoTargetOperand geoTargetOperand2 = new GeoTargetOperand();
      geoTargetOperand2.locations = new long[] { 1015116 }; // Miami, FL.

      interestLocationGroups.matchingFunction = new Function();
      interestLocationGroups.matchingFunction.lhsOperand =
          new FunctionArgumentOperand[] {placesOfInterestOperand};
      interestLocationGroups.matchingFunction.@operator = FunctionOperator.AND;
      interestLocationGroups.matchingFunction.rhsOperand =
          new FunctionArgumentOperand[] {geoTargetOperand2};

      CampaignCriterion locationGroupCriterion2 = new CampaignCriterion();
      locationGroupCriterion2.campaignId = campaignId;
      locationGroupCriterion2.criterion = interestLocationGroups;

      // Distance targeting. Area of 10 miles around targets above.
      ConstantOperand radius = new ConstantOperand();
      radius.type = ConstantOperandConstantType.DOUBLE;
      radius.unit = ConstantOperandUnit.MILES;
      radius.doubleValue = 10.0;
      LocationExtensionOperand distance = new LocationExtensionOperand();
      distance.radius = radius;

      LocationGroups radiusLocationGroups = new LocationGroups();
      radiusLocationGroups.matchingFunction = new Function();
      radiusLocationGroups.matchingFunction.@operator = FunctionOperator.IDENTITY;
      radiusLocationGroups.matchingFunction.lhsOperand = new FunctionArgumentOperand[] { distance };

      CampaignCriterion locationGroupCriterion3 = new CampaignCriterion();
      locationGroupCriterion3.campaignId = campaignId;
      locationGroupCriterion3.criterion = radiusLocationGroups;

      // Create location criteria.
      // See http://code.google.com/apis/adwords/docs/appendix/countrycodes.html
      // for a detailed list of country codes.
      Location location1 = new Location();
      location1.id = 2840; // USA
      CampaignCriterion locationCriterion1 = new CampaignCriterion();
      locationCriterion1.campaignId = campaignId;
      locationCriterion1.criterion = location1;

      Location location2 = new Location();
      location2.id = 2392; // Japan
      CampaignCriterion locationCriterion2 = new CampaignCriterion();
      locationCriterion2.campaignId = campaignId;
      locationCriterion2.criterion = location2;

      // Add a negative campaign keyword.
      NegativeCampaignCriterion negativeCriterion = new NegativeCampaignCriterion();
      negativeCriterion.campaignId = campaignId;

      Keyword keyword = new Keyword();
      keyword.matchType = KeywordMatchType.BROAD;
      keyword.text = "jupiter cruise";

      negativeCriterion.criterion = keyword;

      CampaignCriterion[] criteria = new CampaignCriterion[] {languageCriterion1,
          languageCriterion2, locationCriterion1, locationCriterion2, negativeCriterion,
          locationGroupCriterion1, locationGroupCriterion2, locationGroupCriterion3};

      List<CampaignCriterionOperation> operations = new List<CampaignCriterionOperation>();

      foreach (CampaignCriterion criterion in criteria) {
        CampaignCriterionOperation operation = new CampaignCriterionOperation();
        operation.@operator = Operator.ADD;
        operation.operand = criterion;
        operations.Add(operation);
      }

      try {
        // Set the campaign targets.
        CampaignCriterionReturnValue retVal = campaignCriterionService.mutate(operations.ToArray());

        if (retVal != null && retVal.value != null) {
          // Display campaign targets.
          foreach (CampaignCriterion criterion in retVal.value) {
            Console.WriteLine("Campaign criteria of type '{0}' was set to campaign with" +
                " id = '{1}'.", criterion.criterion.CriterionType, criterion.campaignId);
          }
        }
      } catch (Exception ex) {
        throw new System.ApplicationException("Failed to set Campaign criteria.", ex);
      }
    }