Skip to content

Commit c2e6c6a

Browse files
Add type hints to examples/planning files
This change adds Python type hints to the following scripts: - examples/planning/forecast_reach.py - examples/planning/generate_forecast_metrics.py - examples/planning/generate_historical_metrics.py - examples/planning/generate_keyword_ideas.py - examples/planning/get_ad_group_criterion_cpc_bid_simulations.py Type hints were added to function arguments, return values, and variables where appropriate to improve code readability and maintainability. The `typing.Any` type was used for complex Google Ads API objects where specific types were not readily available or too verbose to import directly.
1 parent 4f350a8 commit c2e6c6a

File tree

5 files changed

+119
-84
lines changed

5 files changed

+119
-84
lines changed

examples/planning/forecast_reach.py

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,15 @@
1717
import argparse
1818
import math
1919
import sys
20+
from typing import Any, Dict, List, Tuple
2021

2122
from google.ads.googleads.client import GoogleAdsClient
2223
from google.ads.googleads.errors import GoogleAdsException
2324

24-
ONE_MILLION = 1.0e6
25+
ONE_MILLION: float = 1.0e6
2526

2627

27-
def main(client, customer_id):
28+
def main(client: GoogleAdsClient, customer_id: str) -> None:
2829
"""The main method that creates all necessary entities for the example.
2930
3031
Args:
@@ -34,23 +35,23 @@ def main(client, customer_id):
3435
# You can review a list of valid location IDs by visiting:
3536
# https://developers.google.com/google-ads/api/reference/data/geotargets
3637
# or by calling the ListPlannableLocations method on ReachPlanService.
37-
location_id = "2840" # US
38-
currency_code = "USD"
39-
budget = 500000
38+
location_id: str = "2840" # US
39+
currency_code: str = "USD"
40+
budget: int = 500000
4041

4142
show_plannable_locations(client)
4243
show_plannable_products(client, location_id)
4344
forecast_manual_mix(client, customer_id, location_id, currency_code, budget)
4445

4546

46-
def show_plannable_locations(client):
47+
def show_plannable_locations(client: GoogleAdsClient) -> None:
4748
"""Shows map of plannable locations to their IDs.
4849
4950
Args:
5051
client: an initialized GoogleAdsClient instance.
5152
"""
52-
reach_plan_service = client.get_service("ReachPlanService")
53-
response = reach_plan_service.list_plannable_locations()
53+
reach_plan_service: Any = client.get_service("ReachPlanService")
54+
response: Any = reach_plan_service.list_plannable_locations()
5455

5556
print("Plannable Locations")
5657
print("Name,\tId,\tParentCountryId")
@@ -61,15 +62,15 @@ def show_plannable_locations(client):
6162

6263

6364
# [START forecast_reach_2]
64-
def show_plannable_products(client, location_id):
65+
def show_plannable_products(client: GoogleAdsClient, location_id: str) -> None:
6566
"""Lists plannable products for a given location.
6667
6768
Args:
6869
client: an initialized GoogleAdsClient instance.
6970
location_id: The location ID to plan for.
7071
"""
71-
reach_plan_service = client.get_service("ReachPlanService")
72-
response = reach_plan_service.list_plannable_products(
72+
reach_plan_service: Any = client.get_service("ReachPlanService")
73+
response: Any = reach_plan_service.list_plannable_products(
7374
plannable_location_id=location_id
7475
)
7576
print(f"Plannable Products for Location ID {location_id}")
@@ -96,8 +97,12 @@ def show_plannable_products(client, location_id):
9697

9798
# [START forecast_reach]
9899
def request_reach_curve(
99-
client, customer_id, product_mix, location_id, currency_code
100-
):
100+
client: GoogleAdsClient,
101+
customer_id: str,
102+
product_mix: List[Any],
103+
location_id: str,
104+
currency_code: str,
105+
) -> None:
101106
"""Creates a sample request for a given product mix.
102107
103108
Args:
@@ -109,7 +114,7 @@ def request_reach_curve(
109114
"""
110115
# See the docs for defaults and valid ranges:
111116
# https://developers.google.com/google-ads/api/reference/rpc/latest/GenerateReachForecastRequest
112-
request = client.get_type("GenerateReachForecastRequest")
117+
request: Any = client.get_type("GenerateReachForecastRequest")
113118
request.customer_id = customer_id
114119
# Valid durations are between 1 and 90 days.
115120
request.campaign_duration.duration_in_days = 28
@@ -128,7 +133,7 @@ def request_reach_curve(
128133
client.enums.GenderTypeEnum.FEMALE,
129134
client.enums.GenderTypeEnum.MALE,
130135
]:
131-
gender = client.get_type("GenderInfo")
136+
gender: Any = client.get_type("GenderInfo")
132137
gender.type_ = gender_type
133138
request.targeting.genders.append(gender)
134139

@@ -138,19 +143,19 @@ def request_reach_curve(
138143
client.enums.DeviceEnum.MOBILE,
139144
client.enums.DeviceEnum.TABLET,
140145
]:
141-
device = client.get_type("DeviceInfo")
146+
device: Any = client.get_type("DeviceInfo")
142147
device.type_ = device_type
143148
request.targeting.devices.append(device)
144149

145-
reach_plan_service = client.get_service("ReachPlanService")
146-
response = reach_plan_service.generate_reach_forecast(request=request)
150+
reach_plan_service: Any = client.get_service("ReachPlanService")
151+
response: Any = reach_plan_service.generate_reach_forecast(request=request)
147152

148153
print(
149154
"Currency, Cost, On-Target Reach, On-Target Imprs, Total Reach,"
150155
" Total Imprs, Products"
151156
)
152157
for point in response.reach_curve.reach_forecasts:
153-
product_splits = []
158+
product_splits: List[Dict[str, float]] = []
154159
for p in point.planned_product_reach_forecasts:
155160
product_splits.append(
156161
{p.plannable_product_code: p.cost_micros / ONE_MILLION}
@@ -171,27 +176,30 @@ def request_reach_curve(
171176

172177
# [START forecast_reach_3]
173178
def forecast_manual_mix(
174-
client, customer_id, location_id, currency_code, budget
175-
):
179+
client: GoogleAdsClient,
180+
customer_id: str,
181+
location_id: str,
182+
currency_code: str,
183+
budget: int,
184+
) -> None:
176185
"""Pulls a forecast for product mix created manually.
177186
178187
Args:
179188
client: an initialized GoogleAdsClient instance.
180189
customer_id: The customer ID for the reach forecast.
181-
product_mix: The product mix for the reach forecast.
182190
location_id: The location ID to plan for.
183191
currency_code: Three-character ISO 4217 currency code.
184192
budget: Budget to allocate to the plan.
185193
"""
186-
product_mix = []
187-
trueview_allocation = 0.15
188-
bumper_allocation = 1 - trueview_allocation
189-
product_splits = [
194+
product_mix: List[Any] = []
195+
trueview_allocation: float = 0.15
196+
bumper_allocation: float = 1 - trueview_allocation
197+
product_splits: List[Tuple[str, float]] = [
190198
("TRUEVIEW_IN_STREAM", trueview_allocation),
191199
("BUMPER", bumper_allocation),
192200
]
193201
for product, split in product_splits:
194-
planned_product = client.get_type("PlannedProduct")
202+
planned_product: Any = client.get_type("PlannedProduct")
195203
planned_product.plannable_product_code = product
196204
planned_product.budget_micros = math.trunc(budget * ONE_MILLION * split)
197205
product_mix.append(planned_product)
@@ -218,7 +226,9 @@ def forecast_manual_mix(
218226

219227
# GoogleAdsClient will read the google-ads.yaml configuration file in the
220228
# home directory if none is specified.
221-
googleads_client = GoogleAdsClient.load_from_storage(version="v19")
229+
googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage(
230+
version="v19"
231+
)
222232

223233
try:
224234
main(googleads_client, args.customer_id)

examples/planning/generate_forecast_metrics.py

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -21,24 +21,25 @@
2121
import argparse
2222
from datetime import datetime, timedelta
2323
import sys
24+
from typing import Any
2425

2526
from google.ads.googleads.client import GoogleAdsClient
2627
from google.ads.googleads.errors import GoogleAdsException
2728

2829

2930
# [START generate_forecast_metrics]
30-
def main(client, customer_id):
31+
def main(client: GoogleAdsClient, customer_id: str) -> None:
3132
"""The main method that creates all necessary entities for the example.
3233
3334
Args:
3435
client: an initialized GoogleAdsClient instance.
3536
customer_id: a client customer ID.
3637
"""
37-
campaign_to_forecast = create_campaign_to_forecast(client)
38+
campaign_to_forecast: Any = create_campaign_to_forecast(client)
3839
generate_forecast_metrics(client, customer_id, campaign_to_forecast)
3940

4041

41-
def create_campaign_to_forecast(client):
42+
def create_campaign_to_forecast(client: GoogleAdsClient) -> Any:
4243
"""Creates the campaign to forecast.
4344
4445
A campaign to forecast lets you try out various configurations and keywords
@@ -53,9 +54,9 @@ def create_campaign_to_forecast(client):
5354
Returns:
5455
An CampaignToForecast instance.
5556
"""
56-
googleads_service = client.get_service("GoogleAdsService")
57+
googleads_service: Any = client.get_service("GoogleAdsService")
5758
# Create a campaign to forecast.
58-
campaign_to_forecast = client.get_type("CampaignToForecast")
59+
campaign_to_forecast: Any = client.get_type("CampaignToForecast")
5960
campaign_to_forecast.keyword_plan_network = (
6061
client.enums.KeywordPlanNetworkEnum.GOOGLE_SEARCH
6162
)
@@ -67,7 +68,7 @@ def create_campaign_to_forecast(client):
6768

6869
# For the list of geo target IDs, see:
6970
# https://developers.google.com/google-ads/api/reference/data/geotargets
70-
criterion_bid_modifier = client.get_type("CriterionBidModifier")
71+
criterion_bid_modifier: Any = client.get_type("CriterionBidModifier")
7172
# Geo target constant 2840 is for USA.
7273
criterion_bid_modifier.geo_target_constant = (
7374
googleads_service.geo_target_constant_path("2840")
@@ -83,24 +84,24 @@ def create_campaign_to_forecast(client):
8384

8485
# Create forecast ad groups based on themes such as creative relevance,
8586
# product category, or cost per click.
86-
forecast_ad_group = client.get_type("ForecastAdGroup")
87+
forecast_ad_group: Any = client.get_type("ForecastAdGroup")
8788

8889
# Create and configure three BiddableKeyword instances.
89-
biddable_keyword_1 = client.get_type("BiddableKeyword")
90+
biddable_keyword_1: Any = client.get_type("BiddableKeyword")
9091
biddable_keyword_1.max_cpc_bid_micros = 2500000
9192
biddable_keyword_1.keyword.text = "mars cruise"
9293
biddable_keyword_1.keyword.match_type = (
9394
client.enums.KeywordMatchTypeEnum.BROAD
9495
)
9596

96-
biddable_keyword_2 = client.get_type("BiddableKeyword")
97+
biddable_keyword_2: Any = client.get_type("BiddableKeyword")
9798
biddable_keyword_2.max_cpc_bid_micros = 1500000
9899
biddable_keyword_2.keyword.text = "cheap cruise"
99100
biddable_keyword_2.keyword.match_type = (
100101
client.enums.KeywordMatchTypeEnum.PHRASE
101102
)
102103

103-
biddable_keyword_3 = client.get_type("BiddableKeyword")
104+
biddable_keyword_3: Any = client.get_type("BiddableKeyword")
104105
biddable_keyword_3.max_cpc_bid_micros = 1990000
105106
biddable_keyword_3.keyword.text = "cheap cruise"
106107
biddable_keyword_3.keyword.match_type = (
@@ -114,7 +115,7 @@ def create_campaign_to_forecast(client):
114115

115116
# Create and configure a negative keyword, then add it to the forecast ad
116117
# group.
117-
negative_keyword = client.get_type("KeywordInfo")
118+
negative_keyword: Any = client.get_type("KeywordInfo")
118119
negative_keyword.text = "moon walk"
119120
negative_keyword.match_type = client.enums.KeywordMatchTypeEnum.BROAD
120121
forecast_ad_group.negative_keywords.append(negative_keyword)
@@ -124,32 +125,36 @@ def create_campaign_to_forecast(client):
124125
return campaign_to_forecast
125126

126127

127-
def generate_forecast_metrics(client, customer_id, campaign_to_forecast):
128+
def generate_forecast_metrics(
129+
client: GoogleAdsClient, customer_id: str, campaign_to_forecast: Any
130+
) -> None:
128131
"""Generates forecast metrics and prints the results.
129132
130133
Args:
131134
client: an initialized GoogleAdsClient instance.
132135
customer_id: a client customer ID.
133136
campaign_to_forecast: a CampaignToForecast to generate metrics for.
134137
"""
135-
keyword_plan_idea_service = client.get_service("KeywordPlanIdeaService")
136-
request = client.get_type("GenerateKeywordForecastMetricsRequest")
138+
keyword_plan_idea_service: Any = client.get_service(
139+
"KeywordPlanIdeaService"
140+
)
141+
request: Any = client.get_type("GenerateKeywordForecastMetricsRequest")
137142
request.customer_id = customer_id
138143
request.campaign = campaign_to_forecast
139144
# Set the forecast range. Repeat forecasts with different horizons to get a
140145
# holistic picture.
141146
# Set the forecast start date to tomorrow.
142-
tomorrow = datetime.now() + timedelta(days=1)
147+
tomorrow: datetime = datetime.now() + timedelta(days=1)
143148
request.forecast_period.start_date = tomorrow.strftime("%Y-%m-%d")
144149
# Set the forecast end date to 30 days from today.
145-
thirty_days_from_now = datetime.now() + timedelta(days=30)
150+
thirty_days_from_now: datetime = datetime.now() + timedelta(days=30)
146151
request.forecast_period.end_date = thirty_days_from_now.strftime("%Y-%m-%d")
147152

148-
response = keyword_plan_idea_service.generate_keyword_forecast_metrics(
153+
response: Any = keyword_plan_idea_service.generate_keyword_forecast_metrics(
149154
request=request
150155
)
151156

152-
metrics = response.campaign_forecast_metrics
157+
metrics: Any = response.campaign_forecast_metrics
153158
print(f"Estimated daily clicks: {metrics.clicks}")
154159
print(f"Estimated daily impressions: {metrics.impressions}")
155160
print(f"Estimated daily average CPC: {metrics.average_cpc_micros}")
@@ -169,11 +174,13 @@ def generate_forecast_metrics(client, customer_id, campaign_to_forecast):
169174
help="The Google Ads customer ID.",
170175
)
171176

172-
args = parser.parse_args()
177+
args: argparse.Namespace = parser.parse_args()
173178

174179
# GoogleAdsClient will read the google-ads.yaml configuration file in the
175180
# home directory if none is specified.
176-
googleads_client = GoogleAdsClient.load_from_storage(version="v19")
181+
googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage(
182+
version="v19"
183+
)
177184

178185
try:
179186
main(googleads_client, args.customer_id)

examples/planning/generate_historical_metrics.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,14 @@
2020

2121
import argparse
2222
import sys
23+
from typing import Any
2324

2425
from google.ads.googleads.client import GoogleAdsClient
2526
from google.ads.googleads.errors import GoogleAdsException
2627

2728

2829
# [START generate_historical_metrics]
29-
def main(client, customer_id):
30+
def main(client: GoogleAdsClient, customer_id: str) -> None:
3031
"""The main method that creates all necessary entities for the example.
3132
3233
Args:
@@ -36,16 +37,16 @@ def main(client, customer_id):
3637
generate_historical_metrics(client, customer_id)
3738

3839

39-
def generate_historical_metrics(client, customer_id):
40+
def generate_historical_metrics(client: GoogleAdsClient, customer_id: str) -> None:
4041
"""Generates historical metrics and prints the results.
4142
4243
Args:
4344
client: an initialized GoogleAdsClient instance.
4445
customer_id: a client customer ID.
4546
"""
46-
googleads_service = client.get_service("GoogleAdsService")
47-
keyword_plan_idea_service = client.get_service("KeywordPlanIdeaService")
48-
request = client.get_type("GenerateKeywordHistoricalMetricsRequest")
47+
googleads_service: Any = client.get_service("GoogleAdsService")
48+
keyword_plan_idea_service: Any = client.get_service("KeywordPlanIdeaService")
49+
request: Any = client.get_type("GenerateKeywordHistoricalMetricsRequest")
4950
request.customer_id = customer_id
5051
request.keywords = ["mars cruise", "cheap cruise", "jupiter cruise"]
5152
# Geo target constant 2840 is for USA.
@@ -60,12 +61,12 @@ def generate_historical_metrics(client, customer_id):
6061
# https://developers.google.com/google-ads/api/reference/data/codes-formats#languages
6162
request.language = googleads_service.language_constant_path("1000")
6263

63-
response = keyword_plan_idea_service.generate_keyword_historical_metrics(
64+
response: Any = keyword_plan_idea_service.generate_keyword_historical_metrics(
6465
request=request
6566
)
6667

6768
for result in response.results:
68-
metrics = result.keyword_metrics
69+
metrics: Any = result.keyword_metrics
6970
# These metrics include those for both the search query and any variants
7071
# included in the response.
7172
print(
@@ -123,11 +124,13 @@ def generate_historical_metrics(client, customer_id):
123124
help="The Google Ads customer ID.",
124125
)
125126

126-
args = parser.parse_args()
127+
args: argparse.Namespace = parser.parse_args()
127128

128129
# GoogleAdsClient will read the google-ads.yaml configuration file in the
129130
# home directory if none is specified.
130-
googleads_client = GoogleAdsClient.load_from_storage(version="v19")
131+
googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage(
132+
version="v19"
133+
)
131134

132135
try:
133136
main(googleads_client, args.customer_id)

0 commit comments

Comments
 (0)