Stay organized with collectionsSave and categorize content based on your preferences.
You can use the Google Ads API to importoffline call
conversionsinto Google Ads
in order to track when ads leads to phone calls and when those phone calls lead
to valuable customer actions.
Mapping to the Google Ads UI this is the same as using theUploadsconversion
source followed by choosingConversions from calls.
Create a call conversion
A few things to keep in mind when creating aCallConversion:
You must populate theconsentfield of theCallConversionobject.
If you encounter aTOO_RECENT_CONVERSION_ACTIONorTOO_RECENT_CALLresponse message to an import conversion request, wait 6 hours or 12 hours,
respectively, before retrying the failed rows.
It takes up to 3 hours for imported conversion statistics to appear in your
Google Ads account.
If a single request contains multiple operations for the same conversion,
aDUPLICATE_CALL_CONVERSION_IN_REQUESTerror is returned.
If a user manually copies a Google forwarding number and calls it, no
conversion can be recorded.
Import a call conversion
In order to associate your offline call conversions with a conversion action you
need the following information: the caller ID (phone number),
conversion date time, conversion action resource name and optionally the
conversion value and currency to theConversionUploadService.
For more details on the different inputs see ourHelp
Centerarticle. Thecode
examplealso describes the formats for the different inputs.
Requirements
The following requirements must be met when importing aCallConversion.
TheConversionActionexists in the Google Ads conversion customer of the
click's Google Ads account.
We recommend also setting theConversionAction.categoryto the
category that best describes your conversions.
In addition, the following conditions must be met:
At thetime of the call, conversion tracking was enabled in theGoogle Ads conversion customerof the call's Google Ads account.
Thecustomer_idof theUploadCallConversionsRequestmust be the customer ID of theGoogle Ads conversion
customerof
the call's Google Ads account. Otherwise, the conversion import will result in aConversionUploadError.INVALID_CUSTOMER_FOR_CALLerror.
Theconversion_valuemust be greater than or equal to zero.
Theconversion_date_timemust have atimezone specified,
and the format is asyyyy-mm-dd HH:mm:ss+|-HH:mm, for example:2022-01-01 19:32:45-05:00(ignoring daylight saving time)
. The timezone can be for any valid
value: it doesnothave to match the
account's timezone. However, if you plan on comparing your imported
conversion data with those in the Google Ads UI, we recommend using the same
timezone as your Google Ads account so that the conversion counts match.
defmain(client:GoogleAdsClient,customer_id:str,conversion_action_id:str,caller_id:str,call_start_date_time:str,conversion_date_time:str,conversion_value:float,conversion_custom_variable_id:Optional[str],conversion_custom_variable_value:Optional[str],ad_user_data_consent:Optional[str],):"""Imports offline call conversion values for calls related to your ads.Args:client: An initialized GoogleAdsClient instance.customer_id: The client customer ID string.conversion_action_id: The ID of the conversion action to upload to.caller_id: The caller ID from which this call was placed. Caller ID isexpected to be in E.164 format with preceding '+' sign,e.g. '+18005550100'.call_start_date_time: The date and time at which the call occurred. Theformat is 'yyyy-mm-dd hh:mm:ss+|-hh:mm',e.g. '2021-01-01 12:32:45-08:00'.conversion_date_time: The the date and time of the conversion (should beafter the click time). The format is 'yyyy-mm-dd hh:mm:ss+|-hh:mm',e.g. '2021-01-01 12:32:45-08:00'.conversion_value: The conversion value in the desired currency.conversion_custom_variable_id: The ID of the conversion customvariable to associate with the upload.conversion_custom_variable_value: The str value of the conversion customvariable to associate with the upload.ad_user_data_consent: The consent status for ad user data for allmembers in the job."""# Get the ConversionUploadService client.conversion_upload_service:ConversionUploadServiceClient=(client.get_service("ConversionUploadService"))# Create a call conversion in USD currency.call_conversion:CallConversion=client.get_type("CallConversion")call_conversion.conversion_action=client.get_service("ConversionActionService").conversion_action_path(customer_id,conversion_action_id)call_conversion.caller_id=caller_idcall_conversion.call_start_date_time=call_start_date_timecall_conversion.conversion_date_time=conversion_date_timecall_conversion.conversion_value=conversion_valuecall_conversion.currency_code="USD"ifconversion_custom_variable_idandconversion_custom_variable_value:conversion_custom_variable:CustomVariable=client.get_type("CustomVariable")conversion_custom_variable.conversion_custom_variable=(conversion_custom_variable_id)conversion_custom_variable.value=conversion_custom_variable_valuecall_conversion.custom_variables.append(conversion_custom_variable)# Specifies whether user consent was obtained for the data you are# uploading. For more details. see:# https://www.google.com/about/company/user-consent-policyifad_user_data_consent:call_conversion.consent.ad_user_data=client.enums.ConsentStatusEnum[ad_user_data_consent]# Issue a request to upload the call conversion.# Partial failure MUST be enabled for this request.request:UploadCallConversionsRequest=client.get_type("UploadCallConversionsRequest")request.customer_id=customer_idrequest.conversions=[call_conversion]request.partial_failure=True# NOTE: This request only uploads a single conversion, but if you have# multiple conversions to upload, it's most efficient to upload them in a# single request. See the following for per-request limits for reference:# https://developers.google.com/google-ads/api/docs/best-practices/quotas#conversion_upload_serviceupload_call_conversions_response:UploadCallConversionsResponse=(conversion_upload_service.upload_call_conversions(request=request))# Print any partial errors returned.ifupload_call_conversions_response.partial_failure_error:print("Partial error occurred: "f"'{upload_call_conversions_response.partial_failure_error.message}'")# Print the result if valid.uploaded_call_conversion:CallConversionResult=(upload_call_conversions_response.results[0])ifuploaded_call_conversion.call_start_date_time:print("Uploaded call conversion that occurred at "f"'{uploaded_call_conversion.call_start_date_time}' "f"for caller ID '{uploaded_call_conversion.caller_id}' ""to the conversion action with resource name "f"'{uploaded_call_conversion.conversion_action}'.")
defupload_call_conversion(customer_id,conversion_action_id,caller_id,call_start_date_time,conversion_date_time,conversion_value,conversion_custom_variable_id,conversion_custom_variable_value,ad_user_data_consent)# GoogleAdsClient will read a config file from# ENV['HOME']/google_ads_config.rb when called without parametersclient=Google::Ads::GoogleAds::GoogleAdsClient.new# Create a call conversion by specifying currency as USD.call_conversion=client.resource.call_conversiondo|c|c.conversion_action=client.path.conversion_action(customer_id,conversion_action_id)c.caller_id=caller_idc.call_start_date_time=call_start_date_timec.conversion_date_time=conversion_date_timec.conversion_value=conversion_valuec.currency_code="USD"ifconversion_custom_variable_id&&conversion_custom_variable_valuec.custom_variables<<client.resource.custom_variabledo|cv|cv.conversion_custom_variable=client.path.conversion_custom_variable(customer_id,conversion_custom_variable_id)cv.value=conversion_custom_variable_valueendendunlessad_user_data_consent.nil?c.consent=client.resource.consentdo|c|# Specifies whether user consent was obtained for the data you are# uploading. For more details, see:# https://www.google.com/about/company/user-consent-policyc.ad_user_data=ad_user_data_consentendendend# Issues a request to upload the call conversion.response=client.service.conversion_upload.upload_call_conversions(customer_id:customer_id,# NOTE: This request only uploads a single conversion, but if you have# multiple conversions to upload, it's most efficient to upload them in a# single request. See the following for per-request limits for reference:# https://developers.google.com/google-ads/api/docs/best-practices/quotas#conversion_upload_serviceconversions:[call_conversion],partial_failure:true)# Prints errors if any partial failure error is returned.ifresponse.partial_failure_errorfailures=client.decode_partial_failure_error(response.partial_failure_error)failures.eachdo|failure|failure.errors.eachdo|error|human_readable_error_path=error.location.field_path_elements.map{|location_info|iflocation_info.index"#{location_info.field_name}[#{location_info.index}]"else"#{location_info.field_name}"end}.join(" > ")errmsg="error occured while adding operations "\"#{human_readable_error_path}"\" with value:#{error.trigger.string_value}"\" because#{error.message.downcase}"putserrmsgendendelse# Print the result if valid.uploaded_call_conversion=response.results.firstputs"Uploaded call conversion that occurred at "\"#{uploaded_call_conversion.call_start_date_time}"\"for caller ID "\"#{uploaded_call_conversion.caller_id}"\"to the conversion action with resource name "\"#{uploaded_call_conversion.conversion_action}"endend
subupload_call_conversion{my($api_client,$customer_id,$conversion_action_id,$caller_id,$call_start_date_time,$conversion_date_time,$conversion_value,$conversion_custom_variable_id,$conversion_custom_variable_value,$ad_user_data_consent)=@_;# Create a call conversion by specifying currency as USD.my$call_conversion=Google::Ads::GoogleAds::V21::Services::ConversionUploadService::CallConversion->new({conversionAction=>Google::Ads::GoogleAds::V21::Utils::ResourceNames::conversion_action($customer_id,$conversion_action_id),callerId=>$caller_id,callStartDateTime=>$call_start_date_time,conversionDateTime=>$conversion_date_time,conversionValue=>$conversion_value,currencyCode=>"USD"});if($conversion_custom_variable_id&&$conversion_custom_variable_value){$call_conversion->{customVariables}=[Google::Ads::GoogleAds::V21::Services::ConversionUploadService::CustomVariable->new({conversionCustomVariable=>Google::Ads::GoogleAds::V21::Utils::ResourceNames::conversion_custom_variable($customer_id,$conversion_custom_variable_id),value=>$conversion_custom_variable_value})];}# Set the consent information, if provided.if($ad_user_data_consent){# Specify whether user consent was obtained for the data you are uploading.# See https://www.google.com/about/company/user-consent-policy for details.$call_conversion->{consent}=Google::Ads::GoogleAds::V21::Common::Consent->new({adUserData=>$ad_user_data_consent});}# Issue a request to upload the call conversion.# NOTE: This request contains a single conversion as a demonstration.# However, if you have multiple conversions to upload, it's best to# upload multiple conversions per request instead of sending a separate# request per conversion. See the following for per-request limits:# https://developers.google.com/google-ads/api/docs/best-practices/quotas#conversion_upload_servicemy$upload_call_conversions_response=$api_client->ConversionUploadService()->upload_call_conversions({customerId=>$customer_id,conversions=>[$call_conversion],partialFailure=>"true"});# Print any partial errors returned.if($upload_call_conversions_response->{partialFailureError}){printf"Partial error encountered: '%s'.\n",$upload_call_conversions_response->{partialFailureError}{message};}# Print the result if valid.my$uploaded_call_conversion=$upload_call_conversions_response->{results}[0];if(%$uploaded_call_conversion){printf"Uploaded call conversion that occurred at '%s' "."for caller ID '%s' to the conversion action with resource name '%s'.\n",$uploaded_call_conversion->{callStartDateTime},$uploaded_call_conversion->{callerId},$uploaded_call_conversion->{conversionAction};}return1;}
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-09-03 UTC."],[[["\u003cp\u003eTrack phone calls as conversions in Google Ads by uploading offline call conversion data using the Google Ads API.\u003c/p\u003e\n"],["\u003cp\u003eThis process involves creating a conversion action of type "UPLOAD_CALLS", gathering call details and conversion information, and sending this data to the Google Ads API.\u003c/p\u003e\n"],["\u003cp\u003eThe API request requires details like caller ID, conversion date and time, conversion action resource name, and optionally, conversion value and currency code.\u003c/p\u003e\n"],["\u003cp\u003eEnsure conversion tracking is enabled and properly configured in your Google Ads account before uploading call conversions.\u003c/p\u003e\n"],["\u003cp\u003eUploaded conversions may take up to 3 hours to appear in your Google Ads reporting interface.\u003c/p\u003e\n"]]],[],null,[]]