#!/usr/bin/perl -w
use
lib
"$Bin/../../lib"
;
qw(FIFTEEN_OR_TWENTY_SECONDS)
;
qw(AGE_RANGE_18_65_UP)
;
use
Google::Ads::GoogleAds::V11::Services::ReachPlanService::GenerateReachForecastRequest;
my
$customer_id
=
"INSERT_CUSTOMER_ID_HERE"
;
sub
forecast_reach {
my
(
$api_client
,
$customer_id
) =
@_
;
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_manual_mix(
$reach_plan_service
,
$customer_id
,
$location_id
,
$currency_code
,
$budget_micros
);
forecast_suggested_mix(
$reach_plan_service
,
$customer_id
,
$location_id
,
$currency_code
,
$budget_micros
);
return
1;
}
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;
}
}
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};
}
}
}
sub
forecast_manual_mix {
my
(
$reach_plan_service
,
$customer_id
,
$location_id
,
$currency_code
,
$budget_micros
) =
@_
;
my
$product_mix
= [];
my
$trueview_allocation
= 0.15;
my
$bumper_allocation
= 1 -
$trueview_allocation
;
push
@$product_mix
,
Google::Ads::GoogleAds::V11::Services::ReachPlanService::PlannedProduct->
new({
plannableProductCode
=>
"TRUEVIEW_IN_STREAM"
,
budgetMicros
=>
int
(
$budget_micros
*
$trueview_allocation
)});
push
@$product_mix
,
Google::Ads::GoogleAds::V11::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
);
}
sub
forecast_suggested_mix {
my
(
$reach_plan_service
,
$customer_id
,
$location_id
,
$currency_code
,
$budget_micros
) =
@_
;
my
$preferences
=
Google::Ads::GoogleAds::V11::Services::ReachPlanService::Preferences->new({
hasGuaranteedPrice
=>
"true"
,
startsWithSound
=>
"true"
,
isSkippable
=>
"false"
,
topContentOnly
=>
"true"
,
adLength
=> FIFTEEN_OR_TWENTY_SECONDS
});
my
$mix_response
=
$reach_plan_service
->generate_product_mix_ideas({
customerId
=>
$customer_id
,
plannableLocationId
=>
$location_id
,
preferences
=>
$preferences
,
currencyCode
=>
$currency_code
,
budgetMicros
=>
$budget_micros
,
});
my
$product_mix
= [];
foreach
my
$product
(@{
$mix_response
->{productAllocation}}) {
push
@$product_mix
,
Google::Ads::GoogleAds::V11::Services::ReachPlanService::PlannedProduct->
new({
plannableProductCode
=>
$product
->{plannableProductCode},
budgetMicros
=>
$product
->{budgetMicros}});
}
my
$reach_request
=
build_reach_request(
$customer_id
,
$product_mix
,
$location_id
,
$currency_code
);
pull_reach_curve(
$reach_plan_service
,
$reach_request
);
}
sub
build_reach_request {
my
(
$customer_id
,
$product_mix
,
$location_id
,
$currency_code
) =
@_
;
my
$duration
=
Google::Ads::GoogleAds::V11::Services::ReachPlanService::CampaignDuration->
new({
durationInDays
=> 28
});
my
$genders
= [
Google::Ads::GoogleAds::V11::Common::GenderInfo->new({
type
=> FEMALE
}
),
Google::Ads::GoogleAds::V11::Common::GenderInfo->new({
type
=> MALE
})];
my
$devices
= [
Google::Ads::GoogleAds::V11::Common::DeviceInfo->new({
type
=> DESKTOP
}
),
Google::Ads::GoogleAds::V11::Common::DeviceInfo->new({
type
=> MOBILE
}
),
Google::Ads::GoogleAds::V11::Common::DeviceInfo->new({
type
=> TABLET
})];
my
$targeting
=
Google::Ads::GoogleAds::V11::Services::ReachPlanService::Targeting->new({
plannableLocationId
=>
$location_id
,
ageRange
=> AGE_RANGE_18_65_UP,
genders
=>
$genders
,
devices
=>
$devices
});
return
Google::Ads::GoogleAds::V11::Services::ReachPlanService::GenerateReachForecastRequest
->new({
customerId
=>
$customer_id
,
currencyCode
=>
$currency_code
,
campaignDuration
=>
$duration
,
cookieFrequencyCap
=> 0,
minEffectiveFrequency
=> 1,
targeting
=>
$targeting
,
plannedProducts
=>
$product_mix
});
}
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"
;
}
}
if
(abs_path($0) ne abs_path(__FILE__)) {
return
1;
}
my
$api_client
= Google::Ads::GoogleAds::Client->new();
$api_client
->set_die_on_faults(1);
GetOptions(
"customer_id=s"
=> \
$customer_id
);
pod2usage(2)
if
not check_params(
$customer_id
);
forecast_reach(
$api_client
,
$customer_id
=~ s/-//gr);