Client library for the Google Ads API providing comprehensive access to advertising management, reporting, and analytics capabilities.
—
Conversion action management and conversion data upload including conversion action configuration, offline conversion uploads, and conversion value optimization. The Google Ads API provides comprehensive conversion tracking capabilities for measuring and optimizing advertising performance.
Conversion action management operations for creating and configuring conversion tracking including website conversions, phone call conversions, and app conversions.
def mutate_conversion_actions(
self,
request: Optional[MutateConversionActionsRequest] = None,
customer_id: Optional[str] = None,
operations: Optional[Sequence[ConversionActionOperation]] = None,
partial_failure: bool = False,
validate_only: bool = False,
response_content_type: Optional[ResponseContentTypeEnum.ResponseContentType] = None
) -> MutateConversionActionsResponse:
"""
Create, update, or remove conversion actions.
Args:
request: The request object containing all parameters
customer_id: Required customer ID for the account
operations: List of conversion action operations to perform
partial_failure: Continue processing on individual failures
validate_only: Validate operations without executing
response_content_type: Type of response content to return
Returns:
MutateConversionActionsResponse with operation results
"""
def get_conversion_action(
self,
request: Optional[GetConversionActionRequest] = None,
resource_name: Optional[str] = None
) -> ConversionAction:
"""
Retrieve a conversion action by resource name.
Args:
request: The request object
resource_name: Conversion action resource name (customers/{customer_id}/conversionActions/{conversion_action_id})
Returns:
ConversionAction resource object
"""Conversion data upload operations for importing offline conversions, call conversions, and other conversion events that occur outside of the web tracking environment.
def upload_conversions(
self,
request: Optional[UploadConversionsRequest] = None,
customer_id: Optional[str] = None,
conversions: Optional[Sequence[Conversion]] = None,
partial_failure: bool = False,
validate_only: bool = False
) -> UploadConversionsResponse:
"""
Upload offline conversions.
Args:
request: The request object
customer_id: Required customer ID
conversions: List of conversion data to upload
partial_failure: Continue on individual failures
validate_only: Validate without uploading
Returns:
UploadConversionsResponse with upload results
"""
def upload_call_conversions(
self,
request: Optional[UploadCallConversionsRequest] = None,
customer_id: Optional[str] = None,
conversions: Optional[Sequence[CallConversion]] = None,
partial_failure: bool = False,
validate_only: bool = False
) -> UploadCallConversionsResponse:
"""
Upload call conversion data.
Args:
request: The request object
customer_id: Required customer ID
conversions: List of call conversion data
partial_failure: Continue on individual failures
validate_only: Validate without uploading
Returns:
UploadCallConversionsResponse with results
"""
def upload_click_conversions(
self,
request: Optional[UploadClickConversionsRequest] = None,
customer_id: Optional[str] = None,
conversions: Optional[Sequence[ClickConversion]] = None,
partial_failure: bool = False,
validate_only: bool = False
) -> UploadClickConversionsResponse:
"""
Upload click conversion data.
Args:
request: The request object
customer_id: Required customer ID
conversions: List of click conversion data
partial_failure: Continue on individual failures
validate_only: Validate without uploading
Returns:
UploadClickConversionsResponse with results
"""Conversion adjustment operations for modifying previously uploaded conversion data including conversion value adjustments and conversion restatements.
def upload_conversion_adjustments(
self,
request: Optional[UploadConversionAdjustmentsRequest] = None,
customer_id: Optional[str] = None,
conversion_adjustments: Optional[Sequence[ConversionAdjustment]] = None,
partial_failure: bool = False,
validate_only: bool = False
) -> UploadConversionAdjustmentsResponse:
"""
Upload conversion adjustments to modify existing conversions.
Args:
request: The request object
customer_id: Required customer ID
conversion_adjustments: List of conversion adjustments
partial_failure: Continue on individual failures
validate_only: Validate without uploading
Returns:
UploadConversionAdjustmentsResponse with results
"""Custom variable management for enhanced conversion tracking including custom dimensions and conversion value modifiers for advanced attribution and analysis.
def mutate_conversion_custom_variables(
self,
request: Optional[MutateConversionCustomVariablesRequest] = None,
customer_id: Optional[str] = None,
operations: Optional[Sequence[ConversionCustomVariableOperation]] = None,
partial_failure: bool = False,
validate_only: bool = False,
response_content_type: Optional[ResponseContentTypeEnum.ResponseContentType] = None
) -> MutateConversionCustomVariablesResponse:
"""
Create, update, or remove conversion custom variables.
Args:
request: The request object
customer_id: Required customer ID
operations: List of custom variable operations
partial_failure: Continue on individual failures
validate_only: Validate without executing
response_content_type: Response content type
Returns:
MutateConversionCustomVariablesResponse with results
"""from google.ads.googleads.client import GoogleAdsClient
from google.ads.googleads.errors import GoogleAdsException
def create_website_conversion_action(client, customer_id, conversion_name, value_settings=None):
"""Create a website conversion action for tracking web conversions."""
conversion_action_service = client.get_service("ConversionActionService")
# Create conversion action operation
operation = client.get_type("ConversionActionOperation")
conversion_action = operation.create
# Set basic properties
conversion_action.name = conversion_name
conversion_action.category = client.enums.ConversionActionCategoryEnum.PURCHASE
conversion_action.type_ = client.enums.ConversionActionTypeEnum.WEBPAGE
conversion_action.status = client.enums.ConversionActionStatusEnum.ENABLED
# Configure value settings
value_settings = value_settings or {}
conversion_action.value_settings.default_value = value_settings.get('default_value', 1.0)
conversion_action.value_settings.default_currency_code = value_settings.get('currency_code', 'USD')
conversion_action.value_settings.always_use_default_value = value_settings.get('always_use_default', False)
# Set counting type
conversion_action.counting_type = client.enums.ConversionActionCountingTypeEnum.ONE_PER_CLICK
# Set click-through conversion window
conversion_action.click_through_lookback_window_days = 30
# Set view-through conversion window
conversion_action.view_through_lookback_window_days = 1
# Configure attribution settings
conversion_action.attribution_model_settings.attribution_model = client.enums.ConversionAttributionModelEnum.LAST_CLICK
conversion_action.attribution_model_settings.data_driven_model_status = client.enums.ConversionAttributionModelEnum.LAST_CLICK
# Set tag generation settings
tag_settings = conversion_action.tag_settings
tag_settings.tag_code_type = client.enums.TrackingCodeTypeEnum.WEBPAGE
tag_settings.cross_domain_tracking_enabled = True
try:
response = conversion_action_service.mutate_conversion_actions(
customer_id=customer_id,
operations=[operation]
)
conversion_action_resource_name = response.results[0].resource_name
print(f"Created conversion action: {conversion_action_resource_name}")
# Get the generated tag snippet
conversion_action_response = conversion_action_service.get_conversion_action(
resource_name=conversion_action_resource_name
)
tag_snippets = conversion_action_response.tag_snippets
for snippet in tag_snippets:
print(f"Tag Type: {snippet.type_.name}")
print(f"Global Site Tag: {snippet.global_site_tag}")
print(f"Event Snippet: {snippet.event_snippet}")
return conversion_action_resource_name
except GoogleAdsException as ex:
print(f"Request failed with status {ex.error.code().name}")
for error in ex.failure.errors:
print(f"Error: {error.message}")
return None
# Example usage
value_settings = {
'default_value': 25.0,
'currency_code': 'USD',
'always_use_default': False
}
conversion_action = create_website_conversion_action(
client,
customer_id,
"Purchase Conversion",
value_settings
)def create_phone_call_conversion_action(client, customer_id, conversion_name, phone_number):
"""Create a phone call conversion action for call tracking."""
conversion_action_service = client.get_service("ConversionActionService")
operation = client.get_type("ConversionActionOperation")
conversion_action = operation.create
# Set basic properties
conversion_action.name = conversion_name
conversion_action.category = client.enums.ConversionActionCategoryEnum.PHONE_CALL_LEAD
conversion_action.type_ = client.enums.ConversionActionTypeEnum.PHONE_CALL_LEAD
conversion_action.status = client.enums.ConversionActionStatusEnum.ENABLED
# Set call counting type
conversion_action.counting_type = client.enums.ConversionActionCountingTypeEnum.ONE_PER_CALL
# Configure phone call conversion settings
phone_call_details = conversion_action.phone_call_details
phone_call_details.phone_number = phone_number
phone_call_details.conversion_reporting_state = client.enums.CallConversionReportingStateEnum.USE_RESOURCE_LEVEL_CALL_CONVERSION_ACTION
# Set minimum call duration (in seconds)
phone_call_details.call_conversion_action = conversion_action.resource_name
# Set value settings
conversion_action.value_settings.default_value = 50.0
conversion_action.value_settings.default_currency_code = 'USD'
response = conversion_action_service.mutate_conversion_actions(
customer_id=customer_id,
operations=[operation]
)
return response.results[0].resource_namedef create_app_conversion_action(client, customer_id, conversion_name, app_id, event_type):
"""Create an app conversion action for mobile app tracking."""
conversion_action_service = client.get_service("ConversionActionService")
operation = client.get_type("ConversionActionOperation")
conversion_action = operation.create
# Set basic properties
conversion_action.name = conversion_name
conversion_action.category = client.enums.ConversionActionCategoryEnum.DOWNLOAD
conversion_action.type_ = client.enums.ConversionActionTypeEnum.APP_INSTALL
conversion_action.status = client.enums.ConversionActionStatusEnum.ENABLED
# Configure app details
app_details = conversion_action.app_details
app_details.app_id = app_id
app_details.app_store = client.enums.MobileAppVendorEnum.APPLE_APP_STORE # or GOOGLE_APP_STORE
# Set counting and attribution
conversion_action.counting_type = client.enums.ConversionActionCountingTypeEnum.ONE_PER_INSTALL
conversion_action.post_install_conversion_window_days = 30
response = conversion_action_service.mutate_conversion_actions(
customer_id=customer_id,
operations=[operation]
)
return response.results[0].resource_nameimport datetime
import hashlib
def upload_store_sales_conversions(client, customer_id, conversion_action_resource_name, sales_data):
"""Upload offline store sales conversion data."""
conversion_upload_service = client.get_service("ConversionUploadService")
conversions = []
for sale in sales_data:
conversion = client.get_type("Conversion")
# Set conversion action
conversion.conversion_action = conversion_action_resource_name
# Set conversion date and time
conversion_date_time = datetime.datetime.strptime(sale['date_time'], '%Y-%m-%d %H:%M:%S')
conversion.conversion_date_time = conversion_date_time.strftime('%Y-%m-%d %H:%M:%S+00:00')
# Set conversion value
conversion.conversion_value = sale['value']
conversion.currency_code = sale.get('currency_code', 'USD')
# Set user identifiers for customer matching
if 'email' in sale:
# Hash the email for privacy
hashed_email = hashlib.sha256(sale['email'].lower().encode()).hexdigest()
conversion.user_identifiers.append(
client.get_type("UserIdentifier", hashed_email=hashed_email)
)
if 'phone' in sale:
# Hash the phone number
hashed_phone = hashlib.sha256(sale['phone'].encode()).hexdigest()
conversion.user_identifiers.append(
client.get_type("UserIdentifier", hashed_phone_number=hashed_phone)
)
# Set order ID if available
if 'order_id' in sale:
conversion.order_id = sale['order_id']
# Add custom variables if configured
if 'custom_variables' in sale:
for var_name, var_value in sale['custom_variables'].items():
custom_variable = client.get_type("CustomVariable")
custom_variable.conversion_custom_variable = f"customers/{customer_id}/conversionCustomVariables/{var_name}"
custom_variable.value = var_value
conversion.custom_variables.append(custom_variable)
conversions.append(conversion)
try:
response = conversion_upload_service.upload_conversions(
customer_id=customer_id,
conversions=conversions,
partial_failure=True
)
if response.partial_failure_error:
print("Some conversions failed to upload:")
for error in response.partial_failure_error.details:
print(f"Error: {error}")
print(f"Successfully uploaded {len(response.results)} conversions")
return response.results
except GoogleAdsException as ex:
print(f"Conversion upload failed: {ex.error.code().name}")
for error in ex.failure.errors:
print(f"Error: {error.message}")
return []
# Example usage
sales_data = [
{
'date_time': '2024-01-15 14:30:00',
'value': 125.50,
'currency_code': 'USD',
'email': 'customer1@example.com',
'order_id': 'ORDER_001',
'custom_variables': {
'store_location': 'NYC_Store_1',
'product_category': 'Electronics'
}
},
{
'date_time': '2024-01-15 16:45:00',
'value': 89.99,
'currency_code': 'USD',
'phone': '+1-555-123-4567',
'order_id': 'ORDER_002'
}
]
upload_store_sales_conversions(client, customer_id, conversion_action_resource_name, sales_data)def upload_call_conversions(client, customer_id, call_conversion_data):
"""Upload call conversion data for phone call tracking."""
conversion_upload_service = client.get_service("ConversionUploadService")
call_conversions = []
for call_data in call_conversion_data:
call_conversion = client.get_type("CallConversion")
# Set caller ID
call_conversion.caller_id = call_data['caller_id']
# Set call start time
call_start_time = datetime.datetime.strptime(call_data['call_start_time'], '%Y-%m-%d %H:%M:%S')
call_conversion.call_start_date_time = call_start_time.strftime('%Y-%m-%d %H:%M:%S+00:00')
# Set conversion action
call_conversion.conversion_action = call_data['conversion_action_resource_name']
# Set conversion date time (when the conversion occurred)
conversion_time = datetime.datetime.strptime(call_data['conversion_time'], '%Y-%m-%d %H:%M:%S')
call_conversion.conversion_date_time = conversion_time.strftime('%Y-%m-%d %H:%M:%S+00:00')
# Set conversion value
if 'value' in call_data:
call_conversion.conversion_value = call_data['value']
call_conversion.currency_code = call_data.get('currency_code', 'USD')
call_conversions.append(call_conversion)
response = conversion_upload_service.upload_call_conversions(
customer_id=customer_id,
conversions=call_conversions,
partial_failure=True
)
return response.resultsdef create_conversion_custom_variable(client, customer_id, variable_name, variable_tag):
"""Create a conversion custom variable for enhanced tracking."""
conversion_custom_variable_service = client.get_service("ConversionCustomVariableService")
operation = client.get_type("ConversionCustomVariableOperation")
custom_variable = operation.create
custom_variable.name = variable_name
custom_variable.tag = variable_tag
custom_variable.status = client.enums.ConversionCustomVariableStatusEnum.ENABLED
# Set the family (determines how the variable can be used)
custom_variable.family = client.enums.ConversionCustomVariableFamilyEnum.STANDARD
# Set cardinality type
custom_variable.cardinality_type = client.enums.ConversionCustomVariableCardinalityTypeEnum.BELOW_ALL_LIMITS
try:
response = conversion_custom_variable_service.mutate_conversion_custom_variables(
customer_id=customer_id,
operations=[operation]
)
return response.results[0].resource_name
except GoogleAdsException as ex:
print(f"Custom variable creation failed: {ex.error.code().name}")
for error in ex.failure.errors:
print(f"Error: {error.message}")
return None
# Example usage
store_location_variable = create_conversion_custom_variable(
client,
customer_id,
"Store Location",
"store_location"
)
product_category_variable = create_conversion_custom_variable(
client,
customer_id,
"Product Category",
"product_category"
)def adjust_conversion_values(client, customer_id, adjustment_data):
"""Upload conversion adjustments to modify existing conversions."""
conversion_adjustment_upload_service = client.get_service("ConversionAdjustmentUploadService")
conversion_adjustments = []
for adjustment in adjustment_data:
conversion_adjustment = client.get_type("ConversionAdjustment")
# Set the original conversion to adjust
conversion_adjustment.conversion_action = adjustment['conversion_action_resource_name']
# Set adjustment date and time
adjustment_time = datetime.datetime.strptime(adjustment['adjustment_date_time'], '%Y-%m-%d %H:%M:%S')
conversion_adjustment.adjustment_date_time = adjustment_time.strftime('%Y-%m-%d %H:%M:%S+00:00')
# Set adjustment type
conversion_adjustment.adjustment_type = adjustment['adjustment_type'] # ENHANCEMENT, RESTATEMENT, RETRACTION
# Set user identifiers to match the original conversion
if 'order_id' in adjustment:
conversion_adjustment.order_id = adjustment['order_id']
if 'user_identifiers' in adjustment:
for identifier in adjustment['user_identifiers']:
user_id = client.get_type("UserIdentifier")
if 'hashed_email' in identifier:
user_id.hashed_email = identifier['hashed_email']
elif 'hashed_phone' in identifier:
user_id.hashed_phone_number = identifier['hashed_phone']
conversion_adjustment.user_identifiers.append(user_id)
# Set new conversion value (for restatements/enhancements)
if 'new_value' in adjustment:
conversion_adjustment.restatement_value.adjusted_value = adjustment['new_value']
conversion_adjustment.restatement_value.currency_code = adjustment.get('currency_code', 'USD')
conversion_adjustments.append(conversion_adjustment)
try:
response = conversion_adjustment_upload_service.upload_conversion_adjustments(
customer_id=customer_id,
conversion_adjustments=conversion_adjustments,
partial_failure=True
)
print(f"Successfully processed {len(response.results)} conversion adjustments")
return response.results
except GoogleAdsException as ex:
print(f"Conversion adjustment upload failed: {ex.error.code().name}")
for error in ex.failure.errors:
print(f"Error: {error.message}")
return []def get_conversion_performance(client, customer_id, start_date, end_date):
"""Get conversion performance report by conversion action."""
googleads_service = client.get_service("GoogleAdsService")
query = f'''
SELECT
conversion_action.id,
conversion_action.name,
conversion_action.category,
conversion_action.type,
conversion_action.status,
metrics.conversions,
metrics.conversions_value,
metrics.cost_per_conversion,
metrics.conversion_rate,
metrics.value_per_conversion,
metrics.all_conversions,
metrics.all_conversions_value
FROM conversion_action
WHERE segments.date BETWEEN '{start_date}' AND '{end_date}'
ORDER BY metrics.conversions DESC
'''
response = googleads_service.search(
customer_id=customer_id,
query=query
)
conversion_performance = []
for row in response:
conversion_action = row.conversion_action
metrics = row.metrics
performance_data = {
'conversion_action_id': conversion_action.id,
'name': conversion_action.name,
'category': conversion_action.category.name,
'type': conversion_action.type_.name,
'status': conversion_action.status.name,
'conversions': metrics.conversions,
'conversions_value': metrics.conversions_value,
'cost_per_conversion': metrics.cost_per_conversion / 1_000_000 if metrics.cost_per_conversion else 0,
'conversion_rate': metrics.conversion_rate,
'value_per_conversion': metrics.value_per_conversion,
'all_conversions': metrics.all_conversions,
'all_conversions_value': metrics.all_conversions_value
}
conversion_performance.append(performance_data)
return conversion_performance# Conversion action types
class ConversionAction:
resource_name: str
id: Optional[int]
name: Optional[str]
status: ConversionActionStatusEnum.ConversionActionStatus
type_: ConversionActionTypeEnum.ConversionActionType
origin: ConversionOriginEnum.ConversionOrigin
primary_for_goal: Optional[bool]
category: ConversionActionCategoryEnum.ConversionActionCategory
owner_customer: Optional[str]
include_in_conversions_metric: Optional[bool]
click_through_lookback_window_days: Optional[int]
view_through_lookback_window_days: Optional[int]
value_settings: ValueSettings
counting_type: ConversionActionCountingTypeEnum.ConversionActionCountingType
attribution_model_settings: AttributionModelSettings
tag_snippets: List[TagSnippet]
phone_call_details: PhoneCallDetails
mobile_app_details: MobileAppDetails
third_party_app_analytics_settings: ThirdPartyAppAnalyticsSettings
firebase_settings: FirebaseSettings
google_analytics_4_settings: GoogleAnalytics4Settings
class ValueSettings:
default_value: Optional[float]
default_currency_code: Optional[str]
always_use_default_value: Optional[bool]
class AttributionModelSettings:
attribution_model: ConversionAttributionModelEnum.ConversionAttributionModel
data_driven_model_status: ConversionAttributionModelEnum.ConversionAttributionModel
class PhoneCallDetails:
phone_number: Optional[str]
conversion_reporting_state: CallConversionReportingStateEnum.CallConversionReportingState
# Conversion upload types
class Conversion:
conversion_action: Optional[str]
conversion_date_time: Optional[str]
conversion_value: Optional[float]
currency_code: Optional[str]
order_id: Optional[str]
external_attribution_data: ExternalAttributionData
click_identifier: Optional[str]
job_id: Optional[int]
user_identifiers: List[UserIdentifier]
user_agent: Optional[str]
custom_variables: List[CustomVariable]
cart_data: CartData
consent: Consent
class CallConversion:
caller_id: Optional[str]
call_start_date_time: Optional[str]
conversion_action: Optional[str]
conversion_date_time: Optional[str]
conversion_value: Optional[float]
currency_code: Optional[str]
class ClickConversion:
gclid: Optional[str]
gbraid: Optional[str]
wbraid: Optional[str]
conversion_action: Optional[str]
conversion_date_time: Optional[str]
conversion_value: Optional[float]
currency_code: Optional[str]
order_id: Optional[str]
external_attribution_data: ExternalAttributionData
custom_variables: List[CustomVariable]
cart_data: CartData
user_identifiers: List[UserIdentifier]
consent: Consent
class ConversionAdjustment:
conversion_action: Optional[str]
adjustment_date_time: Optional[str]
adjustment_type: ConversionAdjustmentTypeEnum.ConversionAdjustmentType
order_id: Optional[str]
user_identifiers: List[UserIdentifier]
user_agent: Optional[str]
restatement_value: RestatementValue
class RestatementValue:
adjusted_value: Optional[float]
currency_code: Optional[str]
class UserIdentifier:
user_identifier_source: UserIdentifierSourceEnum.UserIdentifierSource
hashed_email: Optional[str]
hashed_phone_number: Optional[str]
mobile_id: Optional[str]
third_party_user_id: Optional[str]
address_info: OfflineUserAddressInfo
# Custom variable types
class ConversionCustomVariable:
resource_name: str
id: Optional[int]
name: Optional[str]
tag: Optional[str]
status: ConversionCustomVariableStatusEnum.ConversionCustomVariableStatus
owner_customer: Optional[str]
family: ConversionCustomVariableFamilyEnum.ConversionCustomVariableFamily
cardinality_type: ConversionCustomVariableCardinalityTypeEnum.ConversionCustomVariableCardinalityType
class CustomVariable:
conversion_custom_variable: Optional[str]
value: Optional[str]
# Operation types
class ConversionActionOperation:
update_mask: FieldMask
create: ConversionAction
update: ConversionAction
remove: str
class ConversionCustomVariableOperation:
update_mask: FieldMask
create: ConversionCustomVariable
update: ConversionCustomVariable
remove: str
# Request types
class UploadConversionsRequest:
customer_id: str
conversions: List[Conversion]
partial_failure: bool
validate_only: bool
debug_enabled: bool
job_id: int
class UploadCallConversionsRequest:
customer_id: str
conversions: List[CallConversion]
partial_failure: bool
validate_only: bool
class UploadClickConversionsRequest:
customer_id: str
conversions: List[ClickConversion]
partial_failure: bool
validate_only: bool
debug_enabled: bool
job_id: int
class UploadConversionAdjustmentsRequest:
customer_id: str
conversion_adjustments: List[ConversionAdjustment]
partial_failure: bool
validate_only: bool
job_id: int
# Response types
class MutateConversionActionsResponse:
partial_failure_error: Status
results: List[MutateConversionActionResult]
class MutateConversionActionResult:
resource_name: str
conversion_action: ConversionAction
class UploadConversionsResponse:
partial_failure_error: Status
results: List[ConversionUploadResult]
job_id: int
class ConversionUploadResult:
conversion_date_time: str
conversion_action: str
order_id: str
class UploadCallConversionsResponse:
partial_failure_error: Status
results: List[CallConversionResult]
class UploadClickConversionsResponse:
partial_failure_error: Status
results: List[ClickConversionResult]
job_id: int
class UploadConversionAdjustmentsResponse:
partial_failure_error: Status
results: List[ConversionAdjustmentResult]
job_id: intInstall with Tessl CLI
npx tessl i tessl/pypi-google-ads