Java
// Copyright 2020 Google LLC // // 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 // // https://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 com.google.ads.googleads.examples.planning ; import com.beust.jcommander.Parameter ; import com.google.ads.googleads.examples.utils.ArgumentNames ; import com.google.ads.googleads.examples.utils.CodeSampleParams ; import com.google.ads.googleads.lib.GoogleAdsClient ; import com.google.ads.googleads.v21.common.DeviceInfo ; import com.google.ads.googleads.v21.common.GenderInfo ; import com.google.ads.googleads.v21.enums.DeviceEnum.Device ; import com.google.ads.googleads.v21.enums.GenderTypeEnum.GenderType ; import com.google.ads.googleads.v21.enums.ReachPlanAgeRangeEnum.ReachPlanAgeRange ; import com.google.ads.googleads.v21.errors.GoogleAdsError ; import com.google.ads.googleads.v21.errors.GoogleAdsException ; import com.google.ads.googleads.v21.services.CampaignDuration ; import com.google.ads.googleads.v21.services.GenerateReachForecastRequest ; import com.google.ads.googleads.v21.services.GenerateReachForecastResponse ; import com.google.ads.googleads.v21.services.ListPlannableLocationsRequest ; import com.google.ads.googleads.v21.services.ListPlannableLocationsResponse ; import com.google.ads.googleads.v21.services.ListPlannableProductsRequest ; import com.google.ads.googleads.v21.services.ListPlannableProductsResponse ; import com.google.ads.googleads.v21.services.PlannableLocation ; import com.google.ads.googleads.v21.services.PlannedProduct ; import com.google.ads.googleads.v21.services.PlannedProductReachForecast ; import com.google.ads.googleads.v21.services.ProductMetadata ; import com.google.ads.googleads.v21.services.ReachForecast ; import com.google.ads.googleads.v21.services.ReachPlanServiceClient ; import com.google.ads.googleads.v21.services.Targeting ; import com.google.common.base.Joiner ; import java.io.FileNotFoundException ; import java.io.IOException ; import java.util.ArrayList ; import java.util.Arrays ; import java.util.List ; /** * Demonstrates how to interact with the ReachPlanService to find plannable locations and product * codes, build a media plan, and generate a video ads reach forecast. */ public class ForecastReach { private static class ForecastReachParams extends CodeSampleParams { @Parameter ( names = ArgumentNames . CUSTOMER_ID , required = true ) private Long customerId ; } public static void main ( String [] args ) { ForecastReachParams params = new ForecastReachParams (); if ( ! params . parseArguments ( args )) { // Either pass the required parameters for this example on the command line, or insert them // into the code here. See the parameter class definition above for descriptions. params . customerId = Long . parseLong ( "INSERT_CUSTOMER_ID_HERE" ); } GoogleAdsClient googleAdsClient ; try { googleAdsClient = GoogleAdsClient . newBuilder (). fromPropertiesFile (). build (); } catch ( FileNotFoundException fnfe ) { System . err . printf ( "Failed to load GoogleAdsClient configuration from file. Exception: %s%n" , fnfe ); return ; } catch ( IOException ioe ) { System . err . printf ( "Failed to create GoogleAdsClient. Exception: %s%n" , ioe ); return ; } try { new ForecastReach (). runExample ( googleAdsClient , params . customerId ); } catch ( GoogleAdsException gae ) { // GoogleAdsException is the base class for most exceptions thrown by an API request. // Instances of this exception have a message and a GoogleAdsFailure that contains a // collection of GoogleAdsErrors that indicate the underlying causes of the // GoogleAdsException. System . err . printf ( "Request ID %s failed due to GoogleAdsException. Underlying errors:%n" , gae . getRequestId ()); int i = 0 ; for ( GoogleAdsError googleAdsError : gae . getGoogleAdsFailure (). getErrorsList ()) { System . err . printf ( " Error %d: %s%n" , i ++ , googleAdsError ); } } } /** * Runs the example. * * @param googleAdsClient the Google Ads API client. * @param customerId the customer ID for the reach forecast. */ private void runExample ( GoogleAdsClient googleAdsClient , long customerId ) { String locationId = "2840" ; // US String currencyCode = "USD" ; long budgetMicros = 5_000_000L ; // $5 USD try ( ReachPlanServiceClient reachPlanServiceClient = googleAdsClient . getLatestVersion (). createReachPlanServiceClient ()) { showPlannableLocations ( reachPlanServiceClient ); showPlannableProducts ( reachPlanServiceClient , locationId ); forecastManualMix ( reachPlanServiceClient , customerId , locationId , currencyCode , budgetMicros ); } } /** * Maps friendly names of plannable locations to location IDs usable with ReachPlanServiceClient. * * @param reachPlanServiceClient instance of Reach Plan Service client. */ private void showPlannableLocations ( ReachPlanServiceClient reachPlanServiceClient ) { ListPlannableLocationsRequest request = ListPlannableLocationsRequest . newBuilder (). build (); ListPlannableLocationsResponse response = reachPlanServiceClient . listPlannableLocations ( request ); System . out . println ( "Plannable Locations:" ); for ( PlannableLocation location : response . getPlannableLocationsList ()) { System . out . printf ( "Name: %s, ID: %s, ParentCountryId: %s%n" , location . getName (), location . getId (), location . getParentCountryId ()); } } /** * Lists plannable products for a given location. * * @param reachPlanServiceClient instance of Reach Plan Service client. * @param locationId location ID to plan for. To find a valid location ID, either see * https://developers.google.com/google-ads/api/reference/data/geotargets or call * ReachPlanServiceClient.listPlannableLocations(). */ private void showPlannableProducts ( ReachPlanServiceClient reachPlanServiceClient , String locationId ) { ListPlannableProductsRequest request = ListPlannableProductsRequest . newBuilder (). setPlannableLocationId ( locationId ). build (); ListPlannableProductsResponse response = reachPlanServiceClient . listPlannableProducts ( request ); System . out . printf ( "Plannable Products for location %s:%n" , locationId ); for ( ProductMetadata product : response . getProductMetadataList ()) { System . out . printf ( "%s:%n" , product . getPlannableProductCode ()); System . out . println ( "Age Ranges:" ); for ( ReachPlanAgeRange ageRange : product . getPlannableTargeting (). getAgeRangesList ()) { System . out . printf ( "\t- %s%n" , ageRange ); } System . out . println ( "Genders:" ); for ( GenderInfo gender : product . getPlannableTargeting (). getGendersList ()) { System . out . printf ( "\t- %s%n" , gender . getType ()); } System . out . println ( "Devices:" ); for ( DeviceInfo device : product . getPlannableTargeting (). getDevicesList ()) { System . out . printf ( "\t- %s%n" , device . getType ()); } } } /** * Creates a base request to generate a reach forecast. * * @param customerId the customer ID for the reach forecast. * @param productMix the product mix for the reach forecast. * @param locationId location ID to plan for. To find a valid location ID, either see * https://developers.google.com/google-ads/api/reference/data/geotargets or call * ReachPlanServiceClient.ListPlannableLocations. * @param currencyCode three-character ISO 4217 currency code. * @return populated GenerateReachForecastRequest object. */ private GenerateReachForecastRequest buildReachRequest ( Long customerId , List<PlannedProduct> productMix , String locationId , String currencyCode ) { CampaignDuration duration = CampaignDuration . newBuilder (). setDurationInDays ( 28 ). build (); List<GenderInfo> genders = Arrays . asList ( GenderInfo . newBuilder (). setType ( GenderType . FEMALE ). build (), GenderInfo . newBuilder (). setType ( GenderType . MALE ). build ()); List<DeviceInfo> devices = Arrays . asList ( DeviceInfo . newBuilder (). setType ( Device . DESKTOP ). build (), DeviceInfo . newBuilder (). setType ( Device . MOBILE ). build (), DeviceInfo . newBuilder (). setType ( Device . TABLET ). build ()); Targeting targeting = Targeting . newBuilder () . setPlannableLocationId ( locationId ) . setAgeRange ( ReachPlanAgeRange . AGE_RANGE_18_65_UP ) . addAllGenders ( genders ) . addAllDevices ( devices ) . build (); // See the docs for defaults and valid ranges: // https://developers.google.com/google-ads/api/reference/rpc/latest/GenerateReachForecastRequest return GenerateReachForecastRequest . newBuilder () . setCustomerId ( Long . toString ( customerId )) . setCurrencyCode ( currencyCode ) . setCampaignDuration ( duration ) . setTargeting ( targeting ) . setMinEffectiveFrequency ( 1 ) . addAllPlannedProducts ( productMix ) . build (); } /** * Pulls and prints the reach curve for the given request. * * @param reachPlanServiceClient instance of Reach Plan Service client. * @param request an already-populated reach curve request. */ private void getReachCurve ( ReachPlanServiceClient reachPlanServiceClient , GenerateReachForecastRequest request ) { GenerateReachForecastResponse response = reachPlanServiceClient . generateReachForecast ( request ); System . out . println ( "Reach curve output:" ); System . out . println ( "Currency, Cost Micros, On-Target Reach, On-Target Imprs, Total Reach, Total Imprs," + " Products" ); for ( ReachForecast point : response . getReachCurve (). getReachForecastsList ()) { System . out . printf ( "%s, \"" , Joiner . on ( ", " ) . join ( request . getCurrencyCode (), String . valueOf ( point . getCostMicros ()), String . valueOf ( point . getForecast (). getOnTargetReach ()), String . valueOf ( point . getForecast (). getOnTargetImpressions ()), String . valueOf ( point . getForecast (). getTotalReach ()), String . valueOf ( point . getForecast (). getTotalImpressions ()))); for ( PlannedProductReachForecast product : point . getPlannedProductReachForecastsList ()) { System . out . printf ( "[Product: %s, " , product . getPlannableProductCode ()); System . out . printf ( "Budget Micros: %s]" , product . getCostMicros ()); } System . out . printf ( "\"%n" ); } } /** * Pulls a forecast for a budget split 15% and 85% between two products. * * @param reachPlanServiceClient instance of Reach Plan Service client. * @param customerId the customer ID for the reach forecast. * @param locationId location ID to plan for. To find a valid location ID, either see * https://developers.google.com/google-ads/api/reference/data/geotargets or call * ReachPlanServiceClient.listPlannableLocations(). * @param currencyCode three-character ISO 4217 currency code. * @param budgetMicros budget in currency to plan for. */ private void forecastManualMix ( ReachPlanServiceClient reachPlanServiceClient , long customerId , String locationId , String currencyCode , long budgetMicros ) { List<PlannedProduct> productMix = new ArrayList <> (); // Set up a ratio to split the budget between two products. double trueviewAllocation = 0.15 ; double bumperAllocation = 1 - trueviewAllocation ; // See listPlannableProducts on ReachPlanService to retrieve a list // of valid PlannableProductCode's for a given location: // https://developers.google.com/google-ads/api/reference/rpc/latest/ReachPlanService productMix . add ( PlannedProduct . newBuilder () . setPlannableProductCode ( "TRUEVIEW_IN_STREAM" ) . setBudgetMicros (( long ) ( budgetMicros * bumperAllocation )) . build ()); productMix . add ( PlannedProduct . newBuilder () . setPlannableProductCode ( "BUMPER" ) . setBudgetMicros (( long ) ( budgetMicros * bumperAllocation )) . build ()); GenerateReachForecastRequest request = buildReachRequest ( customerId , productMix , locationId , currencyCode ); getReachCurve ( reachPlanServiceClient , request ); } }
C#
// Copyright 2019 Google LLC // // 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. using CommandLine ; using Google.Ads.Gax.Examples ; using Google.Ads.GoogleAds.Lib ; using Google.Ads.GoogleAds.V21.Common ; using Google.Ads.GoogleAds.V21.Errors ; using Google.Ads.GoogleAds.V21.Services ; using System ; using System.Collections.Generic ; using static Google . Ads . GoogleAds . V21 . Enums . DeviceEnum . Types ; using static Google . Ads . GoogleAds . V21 . Enums . GenderTypeEnum . Types ; using static Google . Ads . GoogleAds . V21 . Enums . ReachPlanAgeRangeEnum . Types ; namespace Google.Ads.GoogleAds.Examples.V21 { /// <summary> /// This example demonstrates how to interact with the ReachPlanService to find plannable /// locations and product codes, build a media plan, and generate a video ads reach forecast. /// </summary> public class ForecastReach : ExampleBase { /// <summary> /// Command line options for running the <see cref="ForecastReach"/> example. /// </summary> public class Options : OptionsBase { /// <summary> /// The Google Ads customer ID for which the call is made. /// </summary> [Option("customerId", Required = true, HelpText = "The Google Ads customer ID for which the call is made.")] public long CustomerId { get ; set ; } } /// <summary> /// Main method, to run this code example as a standalone application. /// </summary> /// <param name="args">The command line arguments.</param> public static void Main ( string [] args ) { Options options = ExampleUtilities . ParseCommandLine<Options> ( args ); ForecastReach codeExample = new ForecastReach (); Console . WriteLine ( codeExample . Description ); codeExample . Run ( new GoogleAdsClient (), options . CustomerId ); } /// <summary> /// Returns a description about the code example. /// </summary> public override string Description = > "This example demonstrates how to interact with the ReachPlanService to find " + "plannable locations and product codes, build a media plan, and generate a video ads " + "reach forecast." ; /// <summary> /// Runs the code example, showing a typical series of calls to the /// <see cref="Services.V21.ReachPlanService"/>. /// </summary> /// <param name="client">The Google Ads API client.</param> /// <param name="customerId">The Google Ads customer ID for which the call is made.</param> public void Run ( GoogleAdsClient client , long customerId ) { string locationId = "2840" ; // US string currencyCode = "USD" ; long budgetMicros = 5 _000_000L ; ReachPlanServiceClient reachPlanService = client . GetService ( Services . V21 . ReachPlanService ); try { ShowPlannableLocations ( reachPlanService ); ShowPlannableProducts ( reachPlanService , locationId ); ForecastMix ( reachPlanService , customerId . ToString (), locationId , currencyCode , budgetMicros ); } catch ( GoogleAdsException e ) { Console . WriteLine ( "Failure:" ); Console . WriteLine ( $"Message: {e.Message}" ); Console . WriteLine ( $"Failure: {e.Failure}" ); Console . WriteLine ( $"Request ID: {e.RequestId}" ); throw ; } } /// <summary> /// Maps friendly names of plannable locations to location IDs usable with /// <see cref="ReachPlanServiceClient"/>. /// </summary> /// <param name="reachPlanService">Instance of Reach Plan Service client.</param> public void ShowPlannableLocations ( ReachPlanServiceClient reachPlanService ) { ListPlannableLocationsRequest request = new ListPlannableLocationsRequest (); ListPlannableLocationsResponse response = reachPlanService . ListPlannableLocations ( request ); Console . WriteLine ( "Plannable Locations:" ); Console . WriteLine ( "Name,\tId,\t,ParentCountryId" ); foreach ( PlannableLocation location in response . PlannableLocations ) { Console . WriteLine ( $"\"{location.Name}\",\t{location.Id},{location.ParentCountryId}" ); } } /// <summary> /// Lists plannable products for a given location. /// </summary> /// <param name="reachPlanService">Instance of Reach Plan Service client.</param> /// <param name="locationId">Location ID to plan for. To find a valid location ID, either /// see https://developers.google.com/google-ads/api/reference/data/geotargets or call /// <see cref="ReachPlanServiceClient.ListPlannableLocations"/>.</param> public void ShowPlannableProducts ( ReachPlanServiceClient reachPlanService , string locationId ) { ListPlannableProductsRequest request = new ListPlannableProductsRequest { PlannableLocationId = locationId }; ListPlannableProductsResponse response = reachPlanService . ListPlannableProducts ( request ); Console . WriteLine ( $"Plannable Products for location {locationId}:" ); foreach ( ProductMetadata product in response . ProductMetadata ) { Console . WriteLine ( $"{product.PlannableProductCode}:" ); Console . WriteLine ( "Age Ranges:" ); foreach ( ReachPlanAgeRange ageRange in product . PlannableTargeting . AgeRanges ) { Console . WriteLine ( $"\t- {ageRange}" ); } Console . WriteLine ( "Genders:" ); foreach ( GenderInfo gender in product . PlannableTargeting . Genders ) { Console . WriteLine ( $"\t- {gender.Type}" ); } Console . WriteLine ( "Devices:" ); foreach ( DeviceInfo device in product . PlannableTargeting . Devices ) { Console . WriteLine ( $"\t- {device.Type}" ); } } } /// <summary> /// Create a base request to generate a reach forecast. /// </summary> /// <param name="customerId">The customer ID for the reach forecast.</param> /// <param name="productMix">The product mix for the reach forecast.</param> /// <param name="locationId">Location ID to plan for. To find a valid location ID, either /// see https://developers.google.com/google-ads/api/reference/data/geotargets or call /// <see cref="ReachPlanServiceClient.ListPlannableLocations"/>.</param> /// <param name="currencyCode">Three-character ISO 4217 currency code.</param> public GenerateReachForecastRequest BuildReachRequest ( string customerId , List<PlannedProduct> productMix , string locationId , string currencyCode ) { // Valid durations are between 1 and 90 days. CampaignDuration duration = new CampaignDuration { DurationInDays = 28 }; GenderInfo [] genders = { new GenderInfo { Type = GenderType . Female }, new GenderInfo { Type = GenderType . Male } }; DeviceInfo [] devices = { new DeviceInfo { Type = Device . Desktop }, new DeviceInfo { Type = Device . Mobile }, new DeviceInfo { Type = Device . Tablet } }; Targeting targeting = new Targeting { PlannableLocationId = locationId , AgeRange = ReachPlanAgeRange . AgeRange1865Up , }; targeting . Genders . AddRange ( genders ); targeting . Devices . AddRange ( devices ); // See the docs for defaults and valid ranges: // https://developers.google.com/google-ads/api/reference/rpc/latest/GenerateReachForecastRequest GenerateReachForecastRequest request = new GenerateReachForecastRequest { CustomerId = customerId , CurrencyCode = currencyCode , CampaignDuration = duration , Targeting = targeting , MinEffectiveFrequency = 1 }; request . PlannedProducts . AddRange ( productMix ); return request ; } /// <summary> /// Retrieves and prints the reach curve for the given request. /// </summary> /// <param name="reachPlanService">Instance of Reach Plan Service client.</param> /// <param name="request">An already-populated reach curve request.</param> public void GetReachCurve ( ReachPlanServiceClient reachPlanService , GenerateReachForecastRequest request ) { GenerateReachForecastResponse response = reachPlanService . GenerateReachForecast ( request ); Console . WriteLine ( "Reach curve output:" ); Console . WriteLine ( "Currency, Cost Micros, On-Target Reach, On-Target Impressions, Total Reach," + " Total Impressions, Products" ); foreach ( ReachForecast point in response . ReachCurve . ReachForecasts ) { Console . Write ( $"{request.CurrencyCode}, " ); Console . Write ( $"{point.CostMicros}, " ); Console . Write ( $"{point.Forecast.OnTargetReach}, " ); Console . Write ( $"{point.Forecast.OnTargetImpressions}, " ); Console . Write ( $"{point.Forecast.TotalReach}, " ); Console . Write ( $"{point.Forecast.TotalImpressions}, " ); Console . Write ( "\"[" ); foreach ( PlannedProductReachForecast productReachForecast in point . PlannedProductReachForecasts ) { Console . Write ( $"(Product: {productReachForecast.PlannableProductCode}, " ); Console . Write ( $"Budget Micros: {productReachForecast.CostMicros}), " ); } Console . WriteLine ( "]\"" ); } } /// <summary> /// Gets a forecast for a budget split 15% and 85% between two products. /// </summary> /// <param name="reachPlanService">Instance of Reach Plan Service client.</param> /// <param name="customerId">The customer ID for the reach forecast.</param> /// <param name="locationId">Location ID to plan for. To find a valid location ID, either /// see https://developers.google.com/google-ads/api/reference/data/geotargets or call /// <see cref="ReachPlanServiceClient.ListPlannableLocations"/>.</param> /// <param name="currencyCode">Three-character ISO 4217 currency code.</param> /// <param name="budgetMicros">Budget in currency to plan for.</param> public void ForecastMix ( ReachPlanServiceClient reachPlanService , string customerId , string locationId , string currencyCode , long budgetMicros ) { List<PlannedProduct> productMix = new List<PlannedProduct> (); // Set up a ratio to split the budget between two products. double trueviewAllocation = 0.15 ; double bumperAllocation = 1 - trueviewAllocation ; // See listPlannableProducts on ReachPlanService to retrieve a list // of valid PlannableProductCode's for a given location: // https://developers.google.com/google-ads/api/reference/rpc/latest/ReachPlanService productMix . Add ( new PlannedProduct { PlannableProductCode = "TRUEVIEW_IN_STREAM" , BudgetMicros = Convert . ToInt64 ( budgetMicros * trueviewAllocation ) }); productMix . Add ( new PlannedProduct { PlannableProductCode = "BUMPER" , BudgetMicros = Convert . ToInt64 ( budgetMicros * bumperAllocation ) }); GenerateReachForecastRequest request = BuildReachRequest ( customerId , productMix , locationId , currencyCode ); GetReachCurve ( reachPlanService , request ); } } }
PHP
< ?php /** * Copyright 2020 Google LLC * * 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 * * https://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\Ads\GoogleAds\Examples\Planning; require __DIR__ . '/../../vendor/autoload.php'; use GetOpt\GetOpt; use Google\Ads\GoogleAds\Examples\Utils\ArgumentNames; use Google\Ads\GoogleAds\Examples\Utils\ArgumentParser; use Google\Ads\GoogleAds\Lib\OAuth2TokenBuilder; use Google\Ads\GoogleAds\Lib\V21\GoogleAdsClient; use Google\Ads\GoogleAds\Lib\V21\GoogleAdsClientBuilder; use Google\Ads\GoogleAds\Lib\V21\GoogleAdsException; use Google\Ads\GoogleAds\V21\Common\DeviceInfo; use Google\Ads\GoogleAds\V21\Common\GenderInfo; use Google\Ads\GoogleAds\V21\Enums\DeviceEnum\Device; use Google\Ads\GoogleAds\V21\Enums\GenderTypeEnum\GenderType; use Google\Ads\GoogleAds\V21\Enums\ReachPlanAgeRangeEnum\ReachPlanAgeRange; use Google\Ads\GoogleAds\V21\Errors\GoogleAdsError; use Google\Ads\GoogleAds\V21\Services\CampaignDuration; use Google\Ads\GoogleAds\V21\Services\GenerateReachForecastRequest; use Google\Ads\GoogleAds\V21\Services\ListPlannableLocationsRequest; use Google\Ads\GoogleAds\V21\Services\ListPlannableProductsRequest; use Google\Ads\GoogleAds\V21\Services\PlannableLocation; use Google\Ads\GoogleAds\V21\Services\PlannedProduct; use Google\Ads\GoogleAds\V21\Services\PlannedProductReachForecast; use Google\Ads\GoogleAds\V21\Services\ProductMetadata; use Google\Ads\GoogleAds\V21\Services\ReachForecast; use Google\Ads\GoogleAds\V21\Services\Targeting; use Google\ApiCore\ApiException; /** * This example demonstrates how to interact with the ReachPlanService to find plannable * locations and product codes, build a media plan, and generate a video ads reach forecast. */ class ForecastReach { private const CUSTOMER_ID = 'INSERT_CUSTOMER_ID_HERE'; private const CURRENCY_CODE = 'USD'; // You can get a valid location ID from // https://developers.google.com/adwords/api/docs/appendix/geotargeting or by calling // ListPlannableLocations on the ReachPlanService. private const LOCATION_ID = '2840'; // US private const BUDGET_MICROS = 5000000; // 5 public static function main() { // Either pass the required parameters for this example on the command line, or insert // them into the constants above. $options = (new ArgumentParser())->parseCommandArguments([ ArgumentNames::CUSTOMER_ID => GetOpt::REQUIRED_ARGUMENT ]); // Generate a refreshable OAuth2 credential for authentication. $oAuth2Credential = (new OAuth2TokenBuilder())->fromFile()->build(); // Construct a Google Ads client configured from a properties file and the // OAuth2 credentials above. $googleAdsClient = (new GoogleAdsClientBuilder()) ->fromFile() ->withOAuth2Credential($oAuth2Credential) ->build(); try { self::runExample( $googleAdsClient, $options[ArgumentNames::CUSTOMER_ID] ?: self::CUSTOMER_ID ); } catch (GoogleAdsException $googleAdsException) { printf( "Request with ID '%s' has failed.%sGoogle Ads failure details:%s", $googleAdsException->getRequestId(), PHP_EOL, PHP_EOL ); foreach ($googleAdsException->getGoogleAdsFailure()->getErrors() as $error) { /** @var GoogleAdsError $error */ printf( "\t%s: %s%s", $error->getErrorCode()->getErrorCode(), $error->getMessage(), PHP_EOL ); } exit(1); } catch (ApiException $apiException) { printf( "ApiException was thrown with message '%s'.%s", $apiException->getMessage(), PHP_EOL ); exit(1); } } /** * Runs the example. * * @param GoogleAdsClient $googleAdsClient the Google Ads API client * @param int $customerId the customer ID */ public static function runExample(GoogleAdsClient $googleAdsClient, int $customerId) { self::showPlannableLocations($googleAdsClient); self::showPlannableProducts($googleAdsClient); self::forecastManualMix($googleAdsClient, $customerId); } /** * Shows map of plannable locations to their IDs. * * @param GoogleAdsClient $googleAdsClient the Google Ads API client */ private static function showPlannableLocations(GoogleAdsClient $googleAdsClient) { $response = $googleAdsClient->getReachPlanServiceClient()->listPlannableLocations( new ListPlannableLocationsRequest() ); printf("Plannable Locations:%sName, Id, ParentCountryId%s", PHP_EOL, PHP_EOL); foreach ($response->getPlannableLocations() as $location) { /** @var PlannableLocation $location */ printf( "'%s', %s, %s%s", $location->getName(), $location->getId(), $location->getParentCountryId(), PHP_EOL ); } } /** * Lists plannable products for a given location. * * @param GoogleAdsClient $googleAdsClient the Google Ads API client */ private static function showPlannableProducts(GoogleAdsClient $googleAdsClient) { $response = $googleAdsClient->getReachPlanServiceClient()->listPlannableProducts( ListPlannableProductsRequest::build(self::LOCATION_ID) ); print 'Plannable Products for Location ID ' . self::LOCATION_ID . ':' . PHP_EOL; foreach ($response->getProductMetadata() as $product) { /** @var ProductMetadata $product */ print $product->getPlannableProductCode() . ':' . PHP_EOL; print 'Age Ranges:' . PHP_EOL; foreach ($product->getPlannableTargeting()->getAgeRanges() as $ageRange) { /** @var ReachPlanAgeRange $ageRange */ printf("\t- %s%s", ReachPlanAgeRange::name($ageRange), PHP_EOL); } print 'Genders:' . PHP_EOL; foreach ($product->getPlannableTargeting()->getGenders() as $gender) { /** @var GenderInfo $gender */ printf("\t- %s%s", GenderType::name($gender->getType()), PHP_EOL); } print 'Devices:' . PHP_EOL; foreach ($product->getPlannableTargeting()->getDevices() as $device) { /** @var DeviceInfo $device */ printf("\t- %s%s", Device::name($device->getType()), PHP_EOL); } } } /** * Retrieves and prints the reach curve for a given product mix. * * @param GoogleAdsClient $googleAdsClient the Google Ads API client * @param int $customerId the customer ID * @param array $productMix the product mix for the reach forecast * @param string $locationId the location ID to plan for. You can get a valid location ID from * https://developers.google.com/adwords/api/docs/appendix/geotargeting or * by calling ListPlannableLocations on the ReachPlanService. * @param string $currencyCode three-character ISO 4217 currency code */ private static function getReachCurve( GoogleAdsClient $googleAdsClient, int $customerId, array $productMix, string $locationId, string $currencyCode ) { // Valid durations are between 1 and 90 days. $duration = new CampaignDuration(['duration_in_days' => 28]); $targeting = new Targeting([ 'plannable_location_id' => $locationId, 'age_range' => ReachPlanAgeRange::AGE_RANGE_18_65_UP, 'genders' => [ new GenderInfo(['type' => GenderType::FEMALE]), new GenderInfo(['type' => GenderType::MALE]) ], 'devices' => [ new DeviceInfo(['type' => Device::DESKTOP]), new DeviceInfo(['type' => Device::MOBILE]), new DeviceInfo(['type' => Device::TABLET]) ] ]); // See the docs for defaults and valid ranges: // https://developers.google.com/google-ads/api/reference/rpc/latest/GenerateReachForecastRequest $response = $googleAdsClient->getReachPlanServiceClient()->generateReachForecast( GenerateReachForecastRequest::build($customerId, $duration, $productMix) ->setCurrencyCode($currencyCode) ->setTargeting($targeting) ); printf( "Reach curve output:%sCurrency, Cost Micros, On-Target Reach, On-Target Imprs," . " Total Reach, Total Imprs, Products%s", PHP_EOL, PHP_EOL ); foreach ($response->getReachCurve()->getReachForecasts() as $point) { $products = ''; /** @var ReachForecast $point */ foreach ($point->getPlannedProductReachForecasts() as $plannedProductReachForecast) { /** @var PlannedProductReachForecast $plannedProductReachForecast */ $products .= sprintf( '(Product: %s, Budget Micros: %s)', $plannedProductReachForecast->getPlannableProductCode(), $plannedProductReachForecast->getCostMicros() ); } printf( "%s, %d, %d, %d, %d, %d, %s%s", $currencyCode, $point->getCostMicros(), $point->getForecast()->getOnTargetReach(), $point->getForecast()->getOnTargetImpressions(), $point->getForecast()->getTotalReach(), $point->getForecast()->getTotalImpressions(), $products, PHP_EOL ); } } /** * Gets a forecast for product mix created manually. * * @param GoogleAdsClient $googleAdsClient the Google Ads API client * @param int $customerId the customer ID */ private static function forecastManualMix(GoogleAdsClient $googleAdsClient, int $customerId) { // Set up a ratio to split the budget between two products. $trueviewAllocation = floatval(0.15); $bumperAllocation = floatval(1 - $trueviewAllocation); // See listPlannableProducts on ReachPlanService to retrieve a list // of valid PlannableProductCode's for a given location: // https://developers.google.com/google-ads/api/reference/rpc/latest/ReachPlanService $productMix = [ new PlannedProduct([ 'plannable_product_code' => 'TRUEVIEW_IN_STREAM', 'budget_micros' => self::BUDGET_MICROS * $trueviewAllocation ]), new PlannedProduct([ 'plannable_product_code' => 'BUMPER', 'budget_micros' => self::BUDGET_MICROS * $bumperAllocation ]) ]; self::getReachCurve( $googleAdsClient, $customerId, $productMix, self::LOCATION_ID, self::CURRENCY_CODE ); } } ForecastReach::main();
Python
#!/usr/bin/env python # Copyright 2019 Google LLC # # 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 # # https://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. """This code example generates a video ads reach forecast.""" import argparse import math import sys from google.ads.googleads.client import GoogleAdsClient from google.ads.googleads.errors import GoogleAdsException from google.ads.googleads.v21.enums.types.reach_plan_age_range import ( ReachPlanAgeRangeEnum , ) from google.ads.googleads.v21.enums.types.gender_type import GenderTypeEnum from google.ads.googleads.v21.enums.types.device import DeviceEnum from google.ads.googleads.v21.common.types.criteria import ( GenderInfo , DeviceInfo , ) from google.ads.googleads.v21.services.services.reach_plan_service.client import ( ReachPlanServiceClient , ) from google.ads.googleads.v21.services.types.reach_plan_service import ( ListPlannableLocationsResponse , PlannableLocation , ListPlannableProductsResponse , ProductMetadata , GenerateReachForecastRequest , GenerateReachForecastResponse , ReachForecast , PlannedProductReachForecast , PlannedProduct , ) ONE_MILLION = 1.0e6 def main ( client : GoogleAdsClient , customer_id : str ): """The main method that creates all necessary entities for the example. Args: client: an initialized GoogleAdsClient instance. customer_id: a client customer ID. """ # You can review a list of valid location IDs by visiting: # https://developers.google.com/google-ads/api/reference/data/geotargets # or by calling the ListPlannableLocations method on ReachPlanService. location_id = "2840" # US currency_code = "USD" budget = 500000 show_plannable_locations ( client ) show_plannable_products ( client , location_id ) forecast_manual_mix ( client , customer_id , location_id , currency_code , budget ) def show_plannable_locations ( client : GoogleAdsClient ): """Shows map of plannable locations to their IDs. Args: client: an initialized GoogleAdsClient instance. """ reach_plan_service : ReachPlanServiceClient = client . get_service ( "ReachPlanService" ) response : ListPlannableLocationsResponse = ( reach_plan_service . list_plannable_locations () ) print ( "Plannable Locations" ) print ( "Name, \t Id, \t ParentCountryId" ) location : PlannableLocation for location in response . plannable_locations : print ( f "' { location . name } ', \t { location . id } , \t { location . parent_country_id } " ) def show_plannable_products ( client : GoogleAdsClient , location_id : str ): """Lists plannable products for a given location. Args: client: an initialized GoogleAdsClient instance. location_id: The location ID to plan for. """ reach_plan_service : ReachPlanServiceClient = client . get_service ( "ReachPlanService" ) response : ListPlannableProductsResponse = ( reach_plan_service . list_plannable_products ( plannable_location_id = location_id ) ) print ( f "Plannable Products for Location ID { location_id } " ) product_metadata : ProductMetadata for product_metadata in response . product_metadata : print ( f " { product_metadata . plannable_product_code } : " f " { product_metadata . plannable_product_name } " ) print ( "Age Ranges:" ) age_range : ReachPlanAgeRangeEnum for age_range in product_metadata . plannable_targeting . age_ranges : print ( f " \t - { age_range . name } " ) print ( "Genders:" ) gender : GenderInfo for gender in product_metadata . plannable_targeting . genders : print ( f " \t - { gender . type_ . name } " ) print ( "Devices:" ) device : DeviceInfo for device in product_metadata . plannable_targeting . devices : print ( f " \t - { device . type_ . name } " ) def request_reach_curve ( client : GoogleAdsClient , customer_id : str , product_mix : list [ PlannedProduct ], location_id : str , currency_code : str , ): """Creates a sample request for a given product mix. Args: client: an initialized GoogleAdsClient instance. customer_id: The customer ID for the reach forecast. product_mix: The product mix for the reach forecast. location_id: The location ID to plan for. currency_code: Three-character ISO 4217 currency code. """ # See the docs for defaults and valid ranges: # https://developers.google.com/google-ads/api/reference/rpc/latest/GenerateReachForecastRequest request : GenerateReachForecastRequest = client . get_type ( "GenerateReachForecastRequest" ) request . customer_id = customer_id # Valid durations are between 1 and 90 days. request . campaign_duration . duration_in_days = 28 request . currency_code = currency_code request . cookie_frequency_cap = 0 request . min_effective_frequency = 1 request . planned_products = product_mix request . targeting . plannable_location_id = location_id request . targeting . age_range = ( client . enums . ReachPlanAgeRangeEnum . AGE_RANGE_18_65_UP ) # Add gender targeting to the request. gender_type : GenderTypeEnum for gender_type in [ client . enums . GenderTypeEnum . FEMALE , client . enums . GenderTypeEnum . MALE , ]: gender : GenderInfo = client . get_type ( "GenderInfo" ) gender . type_ = gender_type request . targeting . genders . append ( gender ) # Add device targeting to the request. device_type : DeviceEnum for device_type in [ client . enums . DeviceEnum . DESKTOP , client . enums . DeviceEnum . MOBILE , client . enums . DeviceEnum . TABLET , ]: device : DeviceInfo = client . get_type ( "DeviceInfo" ) device . type_ = device_type request . targeting . devices . append ( device ) reach_plan_service : ReachPlanServiceClient = client . get_service ( "ReachPlanService" ) response : GenerateReachForecastResponse = ( reach_plan_service . generate_reach_forecast ( request = request ) ) print ( "Currency, Cost, On-Target Reach, On-Target Imprs, Total Reach," " Total Imprs, Products" ) point : ReachForecast for point in response . reach_curve . reach_forecasts : product_splits = [] p : PlannedProductReachForecast for p in point . planned_product_reach_forecasts : product_splits . append ( { p . plannable_product_code : p . cost_micros / ONE_MILLION } ) print ( [ currency_code , point . cost_micros / ONE_MILLION , point . forecast . on_target_reach , point . forecast . on_target_impressions , point . forecast . total_reach , point . forecast . total_impressions , product_splits , ] ) def forecast_manual_mix ( client : GoogleAdsClient , customer_id : str , location_id : str , currency_code : str , budget : int , ): """Pulls a forecast for product mix created manually. Args: client: an initialized GoogleAdsClient instance. customer_id: The customer ID for the reach forecast. location_id: The location ID to plan for. currency_code: Three-character ISO 4217 currency code. budget: Budget to allocate to the plan. """ product_mix : list [ PlannedProduct ] = [] trueview_allocation = 0.15 bumper_allocation = 1 - trueview_allocation product_splits = [ ( "TRUEVIEW_IN_STREAM" , trueview_allocation ), ( "BUMPER" , bumper_allocation ), ] product : str split : float for product , split in product_splits : planned_product : PlannedProduct = client . get_type ( "PlannedProduct" ) planned_product . plannable_product_code = product planned_product . budget_micros = math . trunc ( budget * ONE_MILLION * split ) product_mix . append ( planned_product ) request_reach_curve ( client , customer_id , product_mix , location_id , currency_code ) if __name__ == "__main__" : parser = argparse . ArgumentParser ( description = "Generates video ads reach forecast." ) # The following argument(s) should be provided to run the example. parser . add_argument ( "-c" , "--customer_id" , type = str , required = True , help = "The Google Ads customer ID." , ) args = parser . parse_args () # GoogleAdsClient will read the google-ads.yaml configuration file in the # home directory if none is specified. googleads_client = GoogleAdsClient . load_from_storage ( version = "v21" ) try : main ( googleads_client , args . customer_id ) except GoogleAdsException as ex : print ( 'Request with ID " {} " failed with status " %s " and includes the ' "following errors:" . format ( ex . request_id , ex . error . code () . name ) ) for error in ex . failure . errors : print ( ' \t Error with message " {} ".' . format ( error . message )) if error . location : for field_path_element in error . location . field_path_elements : print ( " \t\t On field: {} " . format ( field_path_element . field_name ) ) sys . exit ( 1 )
Ruby
#!/usr/bin/env ruby # Encoding: utf-8 # # Copyright 2020 Google LLC # # 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 # # https://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. # # This example demonstrates how to interact with the ReachPlanService to find # plannable locations and product codes, build a media plan, and generate a # video ads reach forecast. require 'optparse' require 'google/ads/google_ads' def forecast_reach ( customer_id ) # GoogleAdsClient will read a config file from # ENV['HOME']/google_ads_config.rb when called without parameters client = Google :: Ads :: GoogleAds :: GoogleAdsClient . new reach_plan_service = client . service . reach_plan show_plannable_locations ( reach_plan_service ) show_plannable_products ( reach_plan_service ) forecast_manual_mix ( client , reach_plan_service , customer_id ) end # Shows map of plannable locations to their IDs. def show_plannable_locations ( reach_plan_service ) response = reach_plan_service . list_plannable_locations () puts "Plannable Locations:" puts "Name, Id, ParentCountryId" response . plannable_locations . each do | location | puts "' #{ location . name } ', #{ location . id } , #{ location . parent_country_id } " end end # Lists plannable products for a given location. def show_plannable_products ( reach_plan_service ) response = reach_plan_service . list_plannable_products ( plannable_location_id : LOCATION_ID , ) puts "Plannable Products for Location ID #{ LOCATION_ID } :" response . product_metadata . each do | product | puts " #{ product . plannable_product_code } :" puts "Age Ranges:" product . plannable_targeting . age_ranges . each do | age_range | puts " \t - #{ age_range } " end puts "Genders:" product . plannable_targeting . genders . each do | gender | puts " \t - #{ gender . type } " end puts "Devices:" product . plannable_targeting . devices . each do | device | puts " \t - #{ device . type } " end end end # Retrieves and prints the reach curve for a given product mix. def get_reach_curve ( client , reach_plan_service , customer_id , product_mix , location_id , currency_code ) duration = client . resource . campaign_duration do | d | # Valid durations are between 1 and 90 days. d . duration_in_days = 28 end targeting = client . resource . targeting do | t | t . plannable_location_id = location_id t . age_range = :AGE_RANGE_18_65_UP t . genders << client . resource . gender_info do | gender | gender . type = :FEMALE end t . genders << client . resource . gender_info do | gender | gender . type = :MALE end t . devices << client . resource . device_info do | device | device . type = :DESKTOP end t . devices << client . resource . device_info do | device | device . type = :MOBILE end t . devices << client . resource . device_info do | device | device . type = :TABLET end end # See the docs for defaults and valid ranges: # https://developers.google.com/google-ads/api/reference/rpc/latest/GenerateReachForecastRequest response = reach_plan_service . generate_reach_forecast ( customer_id : customer_id , campaign_duration : duration , planned_products : product_mix , currency_code : currency_code , targeting : targeting , ) puts "Reach curve output:" puts "Currency, Cost Micros, On-Target Reach, On-Target Imprs, " \ "Total Reach, Total Imprs, Products" response . reach_curve . reach_forecasts . each do | point | products = "" point . planned_product_reach_forecasts . each do | product | products += "(Product: #{ product . plannable_product_code } , " \ "Cost Micros: #{ product . cost_micros } )" end puts " #{ currency_code } , #{ point . cost_micros } , " \ " #{ point . forecast . on_target_reach } , " \ " #{ point . forecast . on_target_impressions } , " \ " #{ point . forecast . total_reach } , " \ " #{ point . forecast . total_impressions } , " \ " #{ products } " end end # Gets a forecast for product mix created manually. def forecast_manual_mix ( client , reach_plan_service , customer_id ) # Set up a ratio to split the budget between two products. trueview_allocation = 0 . 15 bumper_allocation = 1 - trueview_allocation # See listPlannableProducts on ReachPlanService to retrieve a list # of valid PlannableProductCode's for a given location: # https://developers.google.com/google-ads/api/reference/rpc/latest/ReachPlanService product_mix = [] product_mix << client . resource . planned_product do | p | p . plannable_product_code = 'TRUEVIEW_IN_STREAM' p . budget_micros = BUDGET_MICROS * trueview_allocation end product_mix << client . resource . planned_product do | p | p . plannable_product_code = 'BUMPER' p . budget_micros = BUDGET_MICROS * bumper_allocation end get_reach_curve ( client , reach_plan_service , customer_id , product_mix , LOCATION_ID , CURRENCY_CODE , ) end if __FILE__ == $0 CUSTOMER_ID = 'INSERT_CUSTOMER_ID_HERE' ; CURRENCY_CODE = 'USD' ; # You can get a valid location ID from # https://developers.google.com/adwords/api/docs/appendix/geotargeting # or by calling list_plannable_locations on the reach_plan service. LOCATION_ID = '2840' ; # US BUDGET_MICROS = 5_000_000 ; # 5 options = {} # The following parameter(s) should be provided to run the example. You can # either specify these by changing the INSERT_XXX_ID_HERE values below, or on # the command line. # # Parameters passed on the command line will override any parameters set in # code. # # Running the example with -h will print the command line usage. options [ :customer_id ] = 'INSERT_CUSTOMER_ID_HERE' OptionParser . new do | opts | opts . banner = sprintf ( 'Usage: %s [options]' , File . basename ( __FILE__ )) opts . separator '' opts . separator 'Options:' opts . on ( '-C' , '--customer-id CUSTOMER-ID' , String , 'Customer ID' ) do | v | options [ :customer_id ] = v end opts . separator '' opts . separator 'Help:' opts . on_tail ( '-h' , '--help' , 'Show this message' ) do puts opts exit end end . parse! begin forecast_reach ( options . fetch ( :customer_id ) . tr ( "-" , "" )) rescue Google :: Ads :: GoogleAds :: Errors :: GoogleAdsError = > e e . failure . errors . each do | error | STDERR . printf ( "Error with message: %s \n " , error . message ) if error . location error . location . field_path_elements . each do | field_path_element | STDERR . printf ( " \t On field: %s \n " , field_path_element . field_name ) end end error . error_code . to_h . each do | k , v | next if v == :UNSPECIFIED STDERR . printf ( " \t Type: %s \n\t Code: %s \n " , k , v ) end end raise end end
Perl
#!/usr/bin/perl -w # # Copyright 2019, Google LLC # # 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. # # This example demonstrates how to interact with the ReachPlanService to find # plannable locations and product codes, build a media plan, and generate a video # ads reach forecast. use strict ; use warnings ; use utf8 ; use FindBin qw($Bin) ; use lib "$Bin/../../lib" ; use Google::Ads::GoogleAds::Client ; use Google::Ads::GoogleAds::Utils::GoogleAdsHelper ; use Google::Ads::GoogleAds::V21::Common::GenderInfo ; use Google::Ads::GoogleAds::V21::Common::DeviceInfo ; use Google::Ads::GoogleAds::V21::Enums::ReachPlanAdLengthEnum qw(FIFTEEN_OR_TWENTY_SECONDS) ; use Google::Ads::GoogleAds::V21::Enums::GenderTypeEnum qw(MALE FEMALE) ; use Google::Ads::GoogleAds::V21::Enums::DeviceEnum qw(DESKTOP MOBILE TABLET) ; use Google::Ads::GoogleAds::V21::Enums::ReachPlanAgeRangeEnum qw(AGE_RANGE_18_65_UP) ; use Google::Ads::GoogleAds::V21::Services::ReachPlanService::PlannedProduct ; use Google::Ads::GoogleAds::V21::Services::ReachPlanService::CampaignDuration ; use Google::Ads::GoogleAds::V21::Services::ReachPlanService::Targeting ; use Google::Ads::GoogleAds::V21::Services::ReachPlanService::GenerateReachForecastRequest ; use Getopt::Long qw(:config auto_help) ; use Pod::Usage ; use Cwd qw(abs_path) ; # The following parameter(s) should be provided to run the example. You can # either specify these by changing the INSERT_XXX_ID_HERE values below, or on # the command line. # # Parameters passed on the command line will override any parameters set in # code. # # Running the example with -h will print the command line usage. my $customer_id = "INSERT_CUSTOMER_ID_HERE" ; sub forecast_reach { my ( $api_client , $customer_id ) = @_ ; # Location ID to plan for. You can get a valid location ID from # https://developers.google.com/google-ads/api/reference/data/geotargets or by # calling list_plannable_locations on the ReachPlanService. # Location ID 2840 is for USA. my $location_id = "2840" ; my $currency_code = "USD" ; my $budget_micros = 500_000_000_000 ; my $reach_plan_service = $api_client - > ReachPlanService (); show_plannable_locations ( $reach_plan_service ); show_plannable_products ( $reach_plan_service , $location_id ); forecast_mix ( $reach_plan_service , $customer_id , $location_id , $currency_code , $budget_micros ); return 1 ; } # Maps friendly names of plannable locations to location IDs usable with # ReachPlanService. sub show_plannable_locations { my ( $reach_plan_service ) = @_ ; my $response = $reach_plan_service - > list_plannable_locations (); print "Plannable Locations:\n" ; print "Name,\tId,\tParentCountryId\n" ; foreach my $location ( @ { $response - > { plannableLocations }}) { printf "'%s',\t%s,\t%d\n" , $location - > { name }, $location - > { id }, $location - > { parentCountryId } ? $location - > { parentCountryId } : 0 ; } } # Lists plannable products for a given location. sub show_plannable_products { my ( $reach_plan_service , $location_id ) = @_ ; my $response = $reach_plan_service - > list_plannable_products ({ plannableLocationId = > $location_id }); printf "Plannable Products for location %d:\n" , $location_id ; foreach my $product ( @ { $response - > { productMetadata }}) { printf "%s : '%s'\n" , $product - > { plannableProductCode }, $product - > { plannableProductName }; print "Age Ranges:\n" ; foreach my $age_range ( @ { $product - > { plannableTargeting }{ ageRanges }}) { printf "\t- %s\n" , $age_range ; } print "Genders:\n" ; foreach my $gender ( @ { $product - > { plannableTargeting }{ genders }}) { printf "\t- %s\n" , $gender - > { type }; } print "Devices:\n" ; foreach my $device ( @ { $product - > { plannableTargeting }{ devices }}) { printf "\t- %s\n" , $device - > { type }; } } } # Pulls a forecast for a budget split 15% and 85% between two products. sub forecast_mix { my ( $reach_plan_service , $customer_id , $location_id , $currency_code , $budget_micros ) = @_ ; my $product_mix = [] ; # Set up a ratio to split the budget between two products. my $trueview_allocation = 0.15 ; my $bumper_allocation = 1 - $trueview_allocation ; # See list_plannable_products on ReachPlanService to retrieve a list of valid # plannable product codes for a given location: # https://developers.google.com/google-ads/api/reference/rpc/latest/ReachPlanService push @$product_mix , Google::Ads::GoogleAds::V21::Services::ReachPlanService:: PlannedProduct - > new ({ plannableProductCode = > "TRUEVIEW_IN_STREAM" , budgetMicros = > int ( $budget_micros * $trueview_allocation )}); push @$product_mix , Google::Ads::GoogleAds::V21::Services::ReachPlanService:: PlannedProduct - > new ({ plannableProductCode = > "BUMPER" , budgetMicros = > int ( $budget_micros * $bumper_allocation )}); my $reach_request = build_reach_request ( $customer_id , $product_mix , $location_id , $currency_code ); pull_reach_curve ( $reach_plan_service , $reach_request ); } # Create a base request to generate a reach forecast. sub build_reach_request { my ( $customer_id , $product_mix , $location_id , $currency_code ) = @_ ; # Valid durations are between 1 and 90 days. my $duration = Google::Ads::GoogleAds::V21::Services::ReachPlanService:: CampaignDuration - > new ({ durationInDays = > 28 }); my $genders = [ Google::Ads::GoogleAds::V21::Common:: GenderInfo - > new ({ type = > FEMALE } ), Google::Ads::GoogleAds::V21::Common:: GenderInfo - > new ({ type = > MALE })]; my $devices = [ Google::Ads::GoogleAds::V21::Common:: DeviceInfo - > new ({ type = > DESKTOP } ), Google::Ads::GoogleAds::V21::Common:: DeviceInfo - > new ({ type = > MOBILE } ), Google::Ads::GoogleAds::V21::Common:: DeviceInfo - > new ({ type = > TABLET })]; my $targeting = Google::Ads::GoogleAds::V21::Services::ReachPlanService:: Targeting - > new ({ plannableLocationId = > $location_id , ageRange = > AGE_RANGE_18_65_UP , genders = > $genders , devices = > $devices }); # See the docs for defaults and valid ranges: # https://developers.google.com/google-ads/api/reference/rpc/latest/GenerateReachForecastRequest return Google::Ads::GoogleAds::V21::Services::ReachPlanService:: GenerateReachForecastRequest - > new ({ customerId = > $customer_id , currencyCode = > $currency_code , campaignDuration = > $duration , cookieFrequencyCap = > 0 , minEffectiveFrequency = > 1 , targeting = > $targeting , plannedProducts = > $product_mix }); } # Pulls and prints the reach curve for the given request. sub pull_reach_curve { my ( $reach_plan_service , $reach_request ) = @_ ; my $response = $reach_plan_service - > generate_reach_forecast ( $reach_request ); print "Reach curve output:\n" ; print "Currency,\tCost Micros,\tOn-Target Reach,\tOn-Target Imprs,\t" . "Total Reach,\tTotal Imprs,\tProducts\n" ; foreach my $point ( @ { $response - > { reachCurve }{ reachForecasts }}) { printf "%s,\t%d,\t%d,\t%d,\t%d,\t%d,\t'[" , $reach_request - > { currencyCode }, $point - > { costMicros }, $point - > { forecast }{ onTargetReach }, $point - > { forecast }{ onTargetImpressions }, $point - > { forecast }{ totalReach }, $point - > { forecast }{ totalImpressions }; foreach my $productReachForecast ( @ { $point - > { plannedProductReachForecasts }}) { printf "(Product: %s, Budget Micros: %d), " , $productReachForecast - > { plannableProductCode }, $productReachForecast - > { costMicros }; } print "]'\n" ; } } # Don't run the example if the file is being included. if ( abs_path ( $0 ) ne abs_path ( __FILE__ )) { return 1 ; } # Get Google Ads Client, credentials will be read from ~/googleads.properties. my $api_client = Google::Ads::GoogleAds:: Client - > new (); # By default examples are set to die on any server returned fault. $api_client - > set_die_on_faults ( 1 ); # Parameters passed on the command line will override any parameters set in code. GetOptions ( "customer_id=s" = > \ $customer_id ); # Print the help message if the parameters are not initialized in the code nor # in the command line. pod2usage ( 2 ) if not check_params ( $customer_id ); # Call the example. forecast_reach ( $api_client , $customer_id =~ s/-//g r ); =pod =head1 NAME forecast_reach =head1 DESCRIPTION This example demonstrates how to interact with the ReachPlanService to find plannable locations and product codes, build a media plan, and generate a video ads reach forecast. =head1 SYNOPSIS forecast_reach.pl [options] -help Show the help message. -customer_id The Google Ads customer ID. =cut