Skip to content

Commit 6b13083

Browse files
authored
Add 2 Examples for Budget Recommendations (#905)
1 parent 459725a commit 6b13083

File tree

2 files changed

+260
-0
lines changed

2 files changed

+260
-0
lines changed
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
#!/usr/bin/env python
2+
# Copyright 2025 Google LLC
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# https://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
"""This example generates budget recommendations on-the-fly for Performance Max campaigns.
16+
17+
Use this example to get budget recommendations during campaign creation workflows.
18+
19+
This example uses the following:
20+
1) Performance Max for the campaign type
21+
2) United States for the geo targeting
22+
3) Maximize Conversion Value for the bidding strategy
23+
24+
To get impact metrics for a custom budget, run get_recommendation_impact_metrics.py.
25+
"""
26+
27+
28+
import argparse
29+
import sys
30+
31+
from google.ads.googleads.client import GoogleAdsClient
32+
from google.ads.googleads.errors import GoogleAdsException
33+
34+
35+
def main(client, customer_id):
36+
"""The main method that creates all necessary entities for the example.
37+
38+
Args:
39+
client: an initialized GoogleAdsClient instance.
40+
customer_id: a client customer ID.
41+
"""
42+
recommendation_service = client.get_service("RecommendationService")
43+
request = client.get_type("GenerateRecommendationsRequest")
44+
45+
request.customer_id = customer_id
46+
request.recommendation_types = ["CAMPAIGN_BUDGET"]
47+
request.advertising_channel_type = client.enums.AdvertisingChannelTypeEnum.PERFORMANCE_MAX
48+
request.bidding_info.bidding_strategy_type = "MAXIMIZE_CONVERSION_VALUE"
49+
request.positive_locations_ids = [2840] # 2840 is for United States
50+
request.asset_group_info = [{ "final_url": "https://www.your-company.com/" }]
51+
52+
results = recommendation_service.generate_recommendations(request)
53+
54+
recommendations = results.recommendations
55+
56+
# Initialize a list to store all budget recommendations with impact metrics.
57+
budget_recommendations_list = []
58+
# Initialize a list to store budget recommendation amounts.
59+
budget_amounts = []
60+
61+
# Get budget recommendations with their associated impact metrics.
62+
for rec in recommendations:
63+
campaign_budget_rec = rec.campaign_budget_recommendation
64+
# Loop through the budget options in the campaign budget recommendation
65+
# to compile a list of budget amounts and their respective potential
66+
# impact metrics. If you have a campaign creation interface,
67+
# you could display this information for end users to decide which
68+
# budget amount best aligns with their goals.
69+
for budget_option in campaign_budget_rec.budget_options:
70+
impact = budget_option.impact
71+
budget_amount = budget_option.budget_amount_micros
72+
if budget_amount > 0:
73+
budget_data = {
74+
"budget_amount": round((budget_amount/1000000), 2),
75+
"potential_metrics": impact.potential_metrics
76+
}
77+
budget_recommendations_list.append(budget_data)
78+
budget_amounts.append(round((budget_amount/1000000), 2))
79+
80+
print(f"budget_recommendations_list:\n{budget_recommendations_list}")
81+
"""
82+
budget_recommendations_list:
83+
[{'budget_amount': 44.56, 'potential_metrics': cost_micros: 311920000
84+
conversions: 2.1
85+
conversions_value: 82.537178980480363
86+
}, ...}]
87+
"""
88+
89+
print(f"budget_amounts:\n{budget_amounts}")
90+
"""
91+
budget_amounts:
92+
[44.56, 55.7, 66.84]
93+
"""
94+
95+
96+
if __name__ == "__main__":
97+
parser = argparse.ArgumentParser(description=("Generate budget recommendations for a Performance Max campaign."))
98+
# The following argument(s) should be provided to run the example.
99+
parser.add_argument(
100+
"-c",
101+
"--customer_id",
102+
type=str,
103+
required=True,
104+
help="The Google Ads customer ID.",
105+
)
106+
107+
args = parser.parse_args()
108+
109+
# GoogleAdsClient will read the google-ads.yaml configuration file in the
110+
# home directory if none is specified.
111+
googleads_client = GoogleAdsClient.load_from_storage(version="v18")
112+
113+
try:
114+
main(googleads_client, args.customer_id)
115+
except GoogleAdsException as ex:
116+
print(
117+
f'Request with ID "{ex.request_id}" failed with status '
118+
f'"{ex.error.code().name}" and includes the following errors:'
119+
)
120+
for error in ex.failure.errors:
121+
print(f'Error with message "{error.message}".')
122+
if error.location:
123+
for field_path_element in error.location.field_path_elements:
124+
print(f"\t\tOn field: {field_path_element.field_name}")
125+
sys.exit(1)
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
#!/usr/bin/env python
2+
# Copyright 2025 Google LLC
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# https://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
"""This example is to get impact metrics for a custom budget.
16+
17+
Use this example to get impact metrics for a given budget amount.
18+
19+
This example uses the following:
20+
1) Performance Max for the campaign type
21+
2) United States for the geo targeting
22+
3) Maximize Conversions Value for the bidding strategy
23+
24+
To get budget recommendations, run generate_budget_recommendations.py.
25+
"""
26+
27+
28+
import argparse
29+
import sys
30+
31+
from google.ads.googleads.client import GoogleAdsClient
32+
from google.ads.googleads.errors import GoogleAdsException
33+
34+
35+
def main(client, customer_id, user_provided_budget_amount):
36+
"""The main method that creates all necessary entities for the example.
37+
38+
Args:
39+
client: an initialized GoogleAdsClient instance.
40+
customer_id: a client customer ID.
41+
user_provided_budget_amount: a user-provided budget amount (not in micros), to retrieve impact metrics for.
42+
"""
43+
recommendation_service = client.get_service("RecommendationService")
44+
request = client.get_type("GenerateRecommendationsRequest")
45+
46+
request.customer_id = customer_id
47+
request.recommendation_types = ["CAMPAIGN_BUDGET"]
48+
request.advertising_channel_type = client.enums.AdvertisingChannelTypeEnum.PERFORMANCE_MAX
49+
request.bidding_info.bidding_strategy_type = "MAXIMIZE_CONVERSION_VALUE"
50+
request.positive_locations_ids = [2840] # 2840 is for United States
51+
request.asset_group_info = [{ "final_url": "https://www.your-company.com/" }]
52+
# Multiply the user-provided budget by 1,000,000 to convert to micros, as required for current_budget
53+
request.budget_info.current_budget = round((user_provided_budget_amount*1000000), 2)
54+
55+
results = recommendation_service.generate_recommendations(request)
56+
57+
recommendations = results.recommendations
58+
59+
# List to store impact metrics for user input budget
60+
budget_impact_metrics = []
61+
62+
# Get impact metrics for custom budget.
63+
for rec in recommendations:
64+
campaign_budget_rec = rec.campaign_budget_recommendation
65+
# Loop through the budget options in the campaign budget recommendation
66+
# to compile a list of budget amounts and their respective potential
67+
# impact metrics. If you have a campaign creation interface,
68+
# you could display this information for end users to decide which
69+
# budget amount best aligns with their goals.
70+
for budget_option in campaign_budget_rec.budget_options:
71+
if hasattr(budget_option, 'impact'):
72+
impact = budget_option.impact
73+
budget_amount = budget_option.budget_amount_micros
74+
if budget_amount/1000000 == user_provided_budget_amount:
75+
budget_data = {
76+
"budget_amount": round((budget_amount/1000000), 2),
77+
"potential_metrics": impact.potential_metrics
78+
}
79+
budget_impact_metrics.append(budget_data)
80+
else:
81+
print("impact metrics not found for this budget amount.")
82+
83+
print(f"budget_impact_metrics:\n{budget_impact_metrics}")
84+
"""
85+
budget_impact_metrics:
86+
[{'budget_amount': 100.0, 'potential_metrics': cost_micros: 700000000
87+
conversions: 12
88+
conversions_value: 481.12592352792007
89+
}]
90+
"""
91+
92+
93+
if __name__ == "__main__":
94+
parser = argparse.ArgumentParser(description=("Get impact metrics for Performance Max budget."))
95+
# The following argument(s) should be provided to run the example.
96+
parser.add_argument(
97+
"-c",
98+
"--customer_id",
99+
type=str,
100+
required=True,
101+
help="The Google Ads customer ID.",
102+
)
103+
parser.add_argument(
104+
"-b",
105+
"--user_provided_budget_amount",
106+
type=int,
107+
required=True,
108+
help=(
109+
"A budget amount (not in micros) advertiser wants to use."
110+
),
111+
)
112+
113+
args = parser.parse_args()
114+
115+
# GoogleAdsClient will read the google-ads.yaml configuration file in the
116+
# home directory if none is specified.
117+
googleads_client = GoogleAdsClient.load_from_storage(version="v18")
118+
119+
try:
120+
main(
121+
googleads_client,
122+
args.customer_id,
123+
args.user_provided_budget_amount,
124+
)
125+
except GoogleAdsException as ex:
126+
print(
127+
f'Request with ID "{ex.request_id}" failed with status '
128+
f'"{ex.error.code().name}" and includes the following errors:'
129+
)
130+
for error in ex.failure.errors:
131+
print(f'Error with message "{error.message}".')
132+
if error.location:
133+
for field_path_element in error.location.field_path_elements:
134+
print(f"\t\tOn field: {field_path_element.field_name}")
135+
sys.exit(1)

0 commit comments

Comments
 (0)