/// <summary>
    /// Runs the code example.
    /// </summary>
    /// <param name="user">The AdWords user.</param>
    /// <param name="adGroupId">Id of the ad group to which ads are added.
    /// </param>
    public void Run(AdWordsUser user, long adGroupId) {
      // Get the AdGroupAdService.
      AdGroupAdService service =
          (AdGroupAdService) user.GetService(AdWordsService.v201506.AdGroupAdService);

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

      for (int i = 0; i < NUM_ITEMS; i++) {
        // Create the text ad.
        TextAd textAd = new TextAd();
        textAd.headline = "Luxury Cruise to Mars";
        textAd.description1 = "Visit the Red Planet in style.";
        textAd.description2 = "Low-gravity fun for everyone!";
        textAd.displayUrl = "www.example.com";
        textAd.finalUrls = new string[] { "http://www.example.com/" + i };

        AdGroupAd textAdGroupAd = new AdGroupAd();
        textAdGroupAd.adGroupId = adGroupId;
        textAdGroupAd.ad = textAd;

        // Optional: Set the status.
        textAdGroupAd.status = AdGroupAdStatus.PAUSED;

        // Create the operation.
        AdGroupAdOperation operation = new AdGroupAdOperation();
        [email protected] = Operator.ADD;
        operation.operand = textAdGroupAd;

        operations.Add(operation);
      }

      AdGroupAdReturnValue retVal = null;

      try {
        // Create the ads.
        retVal = service.mutate(operations.ToArray());

        // Display the results.
        if (retVal != null && retVal.value != null) {
          // If you are adding multiple type of Ads, then you may need to check
          // for
          //
          // if (adGroupAd.ad is TextAd) { ... }
          //
          // to identify the ad type.
          foreach (AdGroupAd adGroupAd in retVal.value) {
            Console.WriteLine("New text ad with id = \"{0}\" and displayUrl = \"{1}\" was created.",
                adGroupAd.ad.id, adGroupAd.ad.displayUrl);
          }
        } else {
          Console.WriteLine("No text ads were created.");
        }
      } catch (Exception ex) {
        throw new System.ApplicationException("Failed to create text ad.", ex);
      }
    }
    /// <summary>
    /// Runs the code example.
    /// </summary>
    /// <param name="user">The AdWords user.</param>
    /// <param name="adGroupId">Id of the ad group to which text ads are
    /// added.</param>
    public void Run(AdWordsUser user, long adGroupId) {
      // Get the AdGroupAdService.
      AdGroupAdService adGroupAdService =
          (AdGroupAdService) user.GetService(AdWordsService.v201506.AdGroupAdService);

      // Set the validateOnly headers.
      adGroupAdService.RequestHeader.validateOnly = true;

      // Create your text ad.
      TextAd textAd = new TextAd();
      textAd.headline = "Luxury Cruise to Mars";
      textAd.description1 = "Visit the Red Planet in style.";
      textAd.description2 = "Low-gravity fun for everyone!!";
      textAd.displayUrl = "www.example.com";
      textAd.finalUrls = new string[] { "http://www.example.com" };

      AdGroupAd textAdGroupAd = new AdGroupAd();
      textAdGroupAd.adGroupId = adGroupId;
      textAdGroupAd.ad = textAd;

      AdGroupAdOperation textAdOperation = new AdGroupAdOperation();
      [email protected] = Operator.ADD;
      textAdOperation.operand = textAdGroupAd;

      try {
        AdGroupAdReturnValue retVal = adGroupAdService.mutate(
            (new AdGroupAdOperation[] {textAdOperation}));
        // Since validation is ON, result will be null.
        Console.WriteLine("text ad validated successfully.");
      } catch (AdWordsApiException e) {
        // This block will be hit if there is a validation error from the server.
        Console.WriteLine("There were validation error(s) while adding text ad.");

        if (e.ApiException != null) {
          foreach (ApiError error in ((ApiException) e.ApiException).errors) {
            Console.WriteLine("  Error type is '{0}' and fieldPath is '{1}'.",
                error.ApiErrorType, error.fieldPath);
          }
        }
      } catch (Exception e) {
        throw new System.ApplicationException("Failed to validate text ad.", e);
      }
    }
    /// <summary>
    /// Runs the code example.
    /// </summary>
    /// <param name="user">The AdWords user.</param>
    /// <param name="adGroupId">ID of the ad group to which ad is added.
    /// </param>
    public void Run(AdWordsUser user, long adGroupId) {
      // Get the AdGroupAdService.
      AdGroupAdService service =
          (AdGroupAdService) user.GetService(AdWordsService.v201506.AdGroupAdService);

      // Create the text ad.
      TextAd textAd = new TextAd();
      textAd.headline = "Luxury Cruise to Mars";
      textAd.description1 = "Visit the Red Planet in style.";
      textAd.description2 = "Low-gravity fun for everyone!";
      textAd.displayUrl = "www.example.com";

      // Specify a tracking URL for 3rd party tracking provider. You may
      // specify one at customer, campaign, ad group, ad, criterion or
      // feed item levels.
      textAd.trackingUrlTemplate =
          "http://tracker.example.com/?season={_season}&promocode={_promocode}&u={lpurl}";

      // Since your tracking URL has two custom parameters, provide their
      // values too. This can be provided at campaign, ad group, ad, criterion
      // or feed item levels.
      CustomParameter seasonParameter = new CustomParameter();
      seasonParameter.key = "season";
      seasonParameter.value = "christmas";

      CustomParameter promoCodeParameter = new CustomParameter();
      promoCodeParameter.key = "promocode";
      promoCodeParameter.value = "NYC123";

      textAd.urlCustomParameters = new CustomParameters();
      textAd.urlCustomParameters.parameters =
          new CustomParameter[] { seasonParameter, promoCodeParameter };

      // Specify a list of final URLs. This field cannot be set if URL field is
      // set. This may be specified at ad, criterion and feed item levels.
      textAd.finalUrls = new string[] {
        "http://www.example.com/cruise/space/",
        "http://www.example.com/locations/mars/"
      };

      // Specify a list of final mobile URLs. This field cannot be set if URL
      // field is set, or finalUrls is unset. This may be specified at ad,
      // criterion and feed item levels.
      textAd.finalMobileUrls = new string[] {
        "http://mobile.example.com/cruise/space/",
        "http://mobile.example.com/locations/mars/"
      };

      AdGroupAd textAdGroupAd = new AdGroupAd();
      textAdGroupAd.adGroupId = adGroupId;
      textAdGroupAd.ad = textAd;

      // Optional: Set the status.
      textAdGroupAd.status = AdGroupAdStatus.PAUSED;

      // Create the operation.
      AdGroupAdOperation operation = new AdGroupAdOperation();
      [email protected] = Operator.ADD;
      operation.operand = textAdGroupAd;

      AdGroupAdReturnValue retVal = null;

      try {
        // Create the ads.
        retVal = service.mutate(new AdGroupAdOperation[] { operation });

        // Display the results.
        if (retVal != null && retVal.value != null) {
          AdGroupAd newAdGroupAd = retVal.value[0];
          Console.WriteLine("New text ad with ID = {0} and display URL = \"{1}\" was " +
              "created.", newAdGroupAd.ad.id, newAdGroupAd.ad.displayUrl);
          Console.WriteLine("Upgraded URL properties:");
          TextAd newTextAd = (TextAd) newAdGroupAd.ad;

          Console.WriteLine("  Final URLs: {0}", string.Join(", ", newTextAd.finalUrls));
          Console.WriteLine("  Final Mobile URLs: {0}",
              string.Join(", ", newTextAd.finalMobileUrls));
          Console.WriteLine("  Tracking URL template: {0}", newTextAd.trackingUrlTemplate);
          Console.WriteLine("  Final App URLs: {0}",
              string.Join(", ", newTextAd.finalAppUrls.Select(finalAppUrl =>
                  finalAppUrl.url).ToArray()));

          List<string> parameters = new List<string>();
          foreach (CustomParameter customParam in newTextAd.urlCustomParameters.parameters) {
            parameters.Add(string.Format("{0}={1}", customParam.key, customParam.value));
          }
          Console.WriteLine("  Custom parameters: {0}", string.Join(", ", parameters.ToArray()));
        } else {
          Console.WriteLine("No text ads were created.");
        }
      } catch (Exception e) {
        throw new System.ApplicationException("Failed to create text ad.", e);
      }
    }
    /// <summary>
    /// Creates text ads that use ad customizations for the specified ad group
    /// IDs.
    /// </summary>
    /// <param name="user">The AdWords user.</param>
    /// <param name="adGroupIds">IDs of the ad groups to which customized ads
    /// are added.</param>
    /// <param name="feedName">Name of the feed to be used.</param>
    private static void CreateAdsWithCustomizations(AdWordsUser user, long[] adGroupIds,
        string feedName) {
      // Get the AdGroupAdService.
      AdGroupAdService adGroupAdService = (AdGroupAdService) user.GetService(
          AdWordsService.v201506.AdGroupAdService);

      TextAd textAd = new TextAd();
      textAd.headline = string.Format("Luxury Cruise to {{={0}.Name}}", feedName);
      textAd.description1 = string.Format("Only {{={0}.Price}}", feedName);
      textAd.description2 = string.Format("Offer ends in {{=countdown({0}.Date)}}!", feedName);
      textAd.finalUrls = new string[] { "http://www.example.com" };
      textAd.displayUrl = "www.example.com";

      // We add the same ad to both ad groups. When they serve, they will show
      // different values, since they match different feed items.
      List<AdGroupAdOperation> adGroupAdOperations = new List<AdGroupAdOperation>();
      foreach (long adGroupId in adGroupIds) {
        AdGroupAd adGroupAd = new AdGroupAd();
        adGroupAd.adGroupId = adGroupId;
        adGroupAd.ad = textAd;

        AdGroupAdOperation adGroupAdOperation = new AdGroupAdOperation();
        adGroupAdOperation.operand = adGroupAd;
        [email protected] = Operator.ADD;

        adGroupAdOperations.Add(adGroupAdOperation);
      }

      AdGroupAdReturnValue adGroupAdReturnValue = adGroupAdService.mutate(
          adGroupAdOperations.ToArray());

      foreach (AdGroupAd addedAd in adGroupAdReturnValue.value) {
        Console.WriteLine("Created an ad with ID {0}, type '{1}' and status '{2}'.",
            addedAd.ad.id, addedAd.ad.AdType, addedAd.status);
      }
    }
    /// <summary>
    /// Runs the code example.
    /// </summary>
    /// <param name="user">The AdWords user.</param>
    /// <param name="adGroupId">Id of the ad group to which ads are added.
    /// </param>
    public void Run(AdWordsUser user, long adGroupId) {
      // Get the AdGroupAdService.
      AdGroupAdService service =
          (AdGroupAdService) user.GetService(AdWordsService.v201506.AdGroupAdService);

      // Create the text ad.
      TextAd textAd = new TextAd();
      textAd.headline = "Luxury Cruise to Mars";
      textAd.description1 = "Visit the Red Planet in style.";
      textAd.description2 = "Low-gravity fun for everyone!!";
      textAd.displayUrl = "www.example.com";
      textAd.finalUrls = new string[] { "http://www.example.com" };

      AdGroupAd textadGroupAd = new AdGroupAd();
      textadGroupAd.adGroupId = adGroupId;
      textadGroupAd.ad = textAd;

      // Create the operations.
      AdGroupAdOperation textAdOperation = new AdGroupAdOperation();
      [email protected] = Operator.ADD;
      textAdOperation.operand = textadGroupAd;

      try {
        AdGroupAdReturnValue retVal = null;

        // Setup two arrays, one to hold the list of all operations to be
        // validated, and another to hold the list of operations that cannot be
        // fixed after validation.
        List<AdGroupAdOperation> allOperations = new List<AdGroupAdOperation>();
        List<AdGroupAdOperation> operationsToBeRemoved = new List<AdGroupAdOperation>();

        allOperations.Add(textAdOperation);

        try {
          // Validate the operations.
          service.RequestHeader.validateOnly = true;
          retVal = service.mutate(allOperations.ToArray());
        } catch (AdWordsApiException e) {
          ApiException innerException = e.ApiException as ApiException;
          if (innerException == null) {
            throw new Exception("Failed to retrieve ApiError. See inner exception for more " +
                "details.", e);
          }

          // Examine each ApiError received from the server.
          foreach (ApiError apiError in innerException.errors) {
            int index = ErrorUtilities.GetOperationIndex(apiError.fieldPath);
            if (index == -1) {
              // This API error is not associated with an operand, so we cannot
              // recover from this error by removing one or more operations.
              // Rethrow the exception for manual inspection.
              throw;
            }

            // Handle policy violation errors.
            if (apiError is PolicyViolationError) {
              PolicyViolationError policyError = (PolicyViolationError) apiError;

              if (policyError.isExemptable) {
                // If the policy violation error is exemptable, add an exemption
                // request.
                List<ExemptionRequest> exemptionRequests = new List<ExemptionRequest>();
                if (allOperations[index].exemptionRequests != null) {
                  exemptionRequests.AddRange(allOperations[index].exemptionRequests);
                }

                ExemptionRequest exemptionRequest = new ExemptionRequest();
                exemptionRequest.key = policyError.key;
                exemptionRequests.Add(exemptionRequest);
                allOperations[index].exemptionRequests = exemptionRequests.ToArray();
              } else {
                // Policy violation error is not exemptable, remove this
                // operation from the list of operations.
                operationsToBeRemoved.Add(allOperations[index]);
              }
            } else {
              // This is not a policy violation error, remove this operation
              // from the list of operations.
              operationsToBeRemoved.Add(allOperations[index]);
            }
          }
          // Remove all operations that aren't exemptable.
          foreach (AdGroupAdOperation operation in operationsToBeRemoved) {
            allOperations.Remove(operation);
          }
        }

        if (allOperations.Count > 0) {
          // Perform the operations exemptible of a policy violation.
          service.RequestHeader.validateOnly = false;
          retVal = service.mutate(allOperations.ToArray());

          // Display the results.
          if (retVal != null && retVal.value != null && retVal.value.Length > 0) {
            foreach (AdGroupAd newAdGroupAd in retVal.value) {
              Console.WriteLine("New ad with id = \"{0}\" and displayUrl = \"{1}\" was created.",
                  newAdGroupAd.ad.id, newAdGroupAd.ad.displayUrl);
            }
          } else {
            Console.WriteLine("No ads were created.");
          }
        } else {
          Console.WriteLine("There are no ads to create after policy violation checks.");
        }
      } catch (Exception e) {
        throw new System.ApplicationException("Failed to create ads.", e);
      }
    }
    /// <summary>
    /// Runs the code example.
    /// </summary>
    /// <param name="user">The AdWords user.</param>
    /// <param name="adGroupId">Id of the ad group that contains the criterion.
    /// </param>
    /// <param name="criterionId">Id of the keyword for which the ad
    /// parameters are set.</param>
    public void Run(AdWordsUser user, long adGroupId, long criterionId) {
      // Get the AdGroupAdService.
      AdGroupAdService adGroupAdService = (AdGroupAdService) user.GetService(
          AdWordsService.v201506.AdGroupAdService);

      // Get the AdParamService.
      AdParamService adParamService = (AdParamService) user.GetService(
          AdWordsService.v201506.AdParamService);

      // Create the text ad.
      TextAd textAd = new TextAd();
      textAd.finalUrls = new string[] { "http://www.example.com" };
      textAd.displayUrl = "example.com";
      textAd.headline = " Mars Cruises";
      textAd.description1 = "Low-gravity fun for {param1:cheap}.";
      textAd.description2 = "Only {param2:a few} seats left!";

      AdGroupAd adOperand = new AdGroupAd();
      adOperand.adGroupId = adGroupId;
      adOperand.status = AdGroupAdStatus.ENABLED;
      adOperand.ad = textAd;

      // Create the operation.
      AdGroupAdOperation adOperation = new AdGroupAdOperation();
      adOperation.operand = adOperand;
      [email protected] = Operator.ADD;

      try {
        // Create the text ad.
        AdGroupAdReturnValue retVal = adGroupAdService.mutate(
            new AdGroupAdOperation[] {adOperation});

        // Display the results.
        if (retVal != null && retVal.value != null && retVal.value.Length > 0) {
          Console.WriteLine("Text ad with id ='{0}' was successfully added.",
              retVal.value[0].ad.id);
        } else {
          Console.WriteLine("No text ads were created.");
          return;
        }
      } catch (Exception ex) {
        Console.WriteLine("Failed to create text ads. Exception says \"{0}\"", ex.Message);
        return;
      }

      // Create the ad param for price.
      AdParam priceParam = new AdParam();
      priceParam.adGroupId = adGroupId;
      priceParam.criterionId = criterionId;
      priceParam.paramIndex = 1;
      priceParam.insertionText = "$100";

      // Create the ad param for seats.
      AdParam seatParam = new AdParam();
      seatParam.adGroupId = adGroupId;
      seatParam.criterionId = criterionId;
      seatParam.paramIndex = 2;
      seatParam.insertionText = "50";

      // Create the operations.
      AdParamOperation priceOperation = new AdParamOperation();
      [email protected] = Operator.SET;
      priceOperation.operand = priceParam;

      AdParamOperation seatOperation = new AdParamOperation();
      [email protected] = Operator.SET;
      seatOperation.operand = seatParam;

      try {
        // Set the ad parameters.
        AdParam [] newAdParams = adParamService.mutate(new AdParamOperation[]
            {priceOperation, seatOperation});

        // Display the results.
        if (newAdParams != null) {
          Console.WriteLine("Ad parameters were successfully updated.");
        } else {
          Console.WriteLine("No ad parameters were set.");
        }
      } catch (Exception ex) {
        throw new System.ApplicationException("Failed to set ad parameters.", ex);
      }
    }
    /// <summary>
    /// Creates a test textad for running further tests.
    /// </summary>
    /// <param name="user">The AdWords user.</param>
    /// <param name="adGroupId">The adgroup id for which the ad is created.
    /// </param>
    /// <param name="hasAdParam">True, if an ad param placeholder should be
    /// added.</param>
    /// <returns>The text ad id.</returns>
    public long CreateTextAd(AdWordsUser user, long adGroupId, bool hasAdParam) {
      AdGroupAdService adGroupAdService =
          (AdGroupAdService) user.GetService(AdWordsService.v201506.AdGroupAdService);
      AdGroupAdOperation adGroupAdOperation = new AdGroupAdOperation();
      [email protected] = Operator.ADD;
      adGroupAdOperation.operand = new AdGroupAd();
      adGroupAdOperation.operand.adGroupId = adGroupId;
      TextAd ad = new TextAd();

      ad.headline = "Luxury Cruise to Mars";
      ad.description1 = "Visit the Red Planet in style.";
      if (hasAdParam) {
        ad.description2 = "Low-gravity fun for {param1:cheap}!";
      } else {
        ad.description2 = "Low-gravity fun for everyone!";
      }
      ad.displayUrl = "example.com";
      ad.finalUrls = new string[] { "http://www.example.com" };

      adGroupAdOperation.operand.ad = ad;

      AdGroupAdReturnValue retVal =
          adGroupAdService.mutate(new AdGroupAdOperation[] { adGroupAdOperation });
      return retVal.value[0].ad.id;
    }