Upload Click Conversions

You can use the Google Ads API to upload offline click conversions into Google Ads in order to track ads that led to sales in the offline world, such as over the phone or through a sales rep.

Setup

There are a few prerequisites to a working offline conversions setup. Make sure all of the prerequisites are satisfied before proceeding to implementation:

  1. Enable conversion tracking in your Google Ads conversion customer.

  2. Configure tagging and store click IDs.

1. Enable conversion tracking in your Google Ads conversion customer

If you completed the conversions getting started guide and have conversion tracking enabled you can skip to step two: configure tagging .

Retrieve information about your conversion tracking setup

You can check your account's conversion tracking setup and confirm conversion tracking is enabled by querying the Customer resource for the ConversionTrackingSetting . Issue the following query with GoogleAdsService.SearchStream :

  SELECT 
  
 customer 
 . 
 conversion_tracking_setting 
 . 
  google_ads_conversion_customer 
 , 
  
 customer 
 . 
 conversion_tracking_setting 
 . 
  conversion_tracking_status 
 , 
  
 customer 
 . 
 conversion_tracking_setting 
 . 
 conversion_tracking_id 
 , 
  
 customer 
 . 
 conversion_tracking_setting 
 . 
 cross_account_conversion_tracking_id 
 FROM 
  
 customer 
 

The google_ads_conversion_customer field indicates the Google Ads account that creates and manages conversions for this customer. For customers using cross-account conversion tracking , this is the ID of a manager account. The Google Ads conversion customer ID should be given as the customer_id in Google Ads API requests to create and manage conversions. Note that this field is populated even if conversion tracking is not enabled.

The conversion_tracking_status field indicates whether conversion tracking is enabled and whether the account is using cross-account conversion tracking.

Create a conversion action under the Google Ads conversion customer

If the conversion_tracking_status value is NOT_CONVERSION_TRACKED , conversion tracking is not enabled for the account. Enable conversion tracking by creating at least one ConversionAction in the Google Ads conversion account, like in the following example. Alternatively, you can create a conversion action in the UI by following the instructions in the Help Center for the conversion type you want to enable.

Note that enhanced conversions are enabled automatically when sent through the Google Ads API, but they can be disabled through the Google Ads UI.

Code example

Java

 private 
  
 void 
  
 runExample 
 ( 
 GoogleAdsClient 
  
 googleAdsClient 
 , 
  
 long 
  
 customerId 
 ) 
  
 { 
  
 // Creates a ConversionAction. 
  
 ConversionAction 
  
 conversionAction 
  
 = 
  
 ConversionAction 
 . 
 newBuilder 
 () 
  
 // Note that conversion action names must be unique. If a conversion action already 
  
 // exists with the specified conversion_action_name the create operation will fail with 
  
 // a ConversionActionError.DUPLICATE_NAME error. 
  
 . 
 setName 
 ( 
 "Earth to Mars Cruises Conversion #" 
  
 + 
  
 getPrintableDateTime 
 ()) 
  
 . 
 setCategory 
 ( 
 ConversionActionCategory 
 . 
 DEFAULT 
 ) 
  
 . 
 setType 
 ( 
 ConversionActionType 
 . 
 WEBPAGE 
 ) 
  
 . 
 setStatus 
 ( 
 ConversionActionStatus 
 . 
 ENABLED 
 ) 
  
 . 
 setViewThroughLookbackWindowDays 
 ( 
 15L 
 ) 
  
 . 
 setValueSettings 
 ( 
  
 ValueSettings 
 . 
 newBuilder 
 () 
  
 . 
 setDefaultValue 
 ( 
 23.41 
 ) 
  
 . 
 setAlwaysUseDefaultValue 
 ( 
 true 
 ) 
  
 . 
 build 
 ()) 
  
 . 
 build 
 (); 
  
 // Creates the operation. 
  
 ConversionActionOperation 
  
 operation 
  
 = 
  
 ConversionActionOperation 
 . 
 newBuilder 
 (). 
 setCreate 
 ( 
 conversionAction 
 ). 
 build 
 (); 
  
 try 
  
 ( 
 ConversionActionServiceClient 
  
 conversionActionServiceClient 
  
 = 
  
 googleAdsClient 
 . 
 getLatestVersion 
 (). 
 createConversionActionServiceClient 
 ()) 
  
 { 
  
 MutateConversionActionsResponse 
  
 response 
  
 = 
  
 conversionActionServiceClient 
 . 
 mutateConversionActions 
 ( 
  
 Long 
 . 
 toString 
 ( 
 customerId 
 ), 
  
 Collections 
 . 
 singletonList 
 ( 
 operation 
 )); 
  
 System 
 . 
 out 
 . 
 printf 
 ( 
 "Added %d conversion actions:%n" 
 , 
  
 response 
 . 
 getResultsCount 
 ()); 
  
 for 
  
 ( 
 MutateConversionActionResult 
  
 result 
  
 : 
  
 response 
 . 
 getResultsList 
 ()) 
  
 { 
  
 System 
 . 
 out 
 . 
 printf 
 ( 
  
 "New conversion action added with resource name: '%s'%n" 
 , 
  
 result 
 . 
 getResourceName 
 ()); 
  
 } 
  
 } 
 } 
  
  

C#

 public 
  
 void 
  
 Run 
 ( 
 GoogleAdsClient 
  
 client 
 , 
  
 long 
  
 customerId 
 ) 
 { 
  
 // Get the ConversionActionService. 
  
 ConversionActionServiceClient 
  
 conversionActionService 
  
 = 
  
 client 
 . 
 GetService 
 ( 
 Services 
 . 
 V21 
 . 
 ConversionActionService 
 ); 
  
 // Note that conversion action names must be unique. 
  
 // If a conversion action already exists with the specified name the create operation 
  
 // will fail with a ConversionAction.DUPLICATE_NAME error. 
  
 string 
  
 ConversionActionName 
  
 = 
  
 "Earth to Mars Cruises Conversion #" 
  
 + 
  
 ExampleUtilities 
 . 
 GetRandomString 
 (); 
  
 // Add a conversion action. 
  
 ConversionAction 
  
 conversionAction 
  
 = 
  
 new 
  
 ConversionAction 
 () 
  
 { 
  
 Name 
  
 = 
  
 ConversionActionName 
 , 
  
 Category 
  
 = 
  
 ConversionActionCategory 
 . 
 Default 
 , 
  
 Type 
  
 = 
  
 ConversionActionType 
 . 
 Webpage 
 , 
  
 Status 
  
 = 
  
 ConversionActionStatus 
 . 
 Enabled 
 , 
  
 ViewThroughLookbackWindowDays 
  
 = 
  
 15 
 , 
  
 ValueSettings 
  
 = 
  
 new 
  
 ConversionAction 
 . 
 Types 
 . 
 ValueSettings 
 () 
  
 { 
  
 DefaultValue 
  
 = 
  
 23.41 
 , 
  
 AlwaysUseDefaultValue 
  
 = 
  
 true 
  
 } 
  
 }; 
  
 // Create the operation. 
  
 ConversionActionOperation 
  
 operation 
  
 = 
  
 new 
  
 ConversionActionOperation 
 () 
  
 { 
  
 Create 
  
 = 
  
 conversionAction 
  
 }; 
  
 try 
  
 { 
  
 // Create the conversion action. 
  
 MutateConversionActionsResponse 
  
 response 
  
 = 
  
 conversionActionService 
 . 
 MutateConversionActions 
 ( 
 customerId 
 . 
 ToString 
 (), 
  
 new 
  
 ConversionActionOperation 
 [] 
  
 { 
  
 operation 
  
 }); 
  
 // Display the results. 
  
 foreach 
  
 ( 
 MutateConversionActionResult 
  
 newConversionAction 
  
 in 
  
 response 
 . 
 Results 
 ) 
  
 { 
  
 Console 
 . 
 WriteLine 
 ( 
 $"New conversion action with resource name = " 
  
 + 
  
 $"'{newConversionAction.ResourceName}' was added." 
 ); 
  
 } 
  
 } 
  
 catch 
  
 ( 
 GoogleAdsException 
  
 e 
 ) 
  
 { 
  
 Console 
 . 
 WriteLine 
 ( 
 "Failure:" 
 ); 
  
 Console 
 . 
 WriteLine 
 ( 
 $"Message: {e.Message}" 
 ); 
  
 Console 
 . 
 WriteLine 
 ( 
 $"Failure: {e.Failure}" 
 ); 
  
 Console 
 . 
 WriteLine 
 ( 
 $"Request ID: {e.RequestId}" 
 ); 
  
 throw 
 ; 
  
 } 
 } 
  
  

PHP

 public static function runExample(GoogleAdsClient $googleAdsClient, int $customerId) 
 { 
 // Creates a conversion action. 
 $conversionAction = new ConversionAction([ 
 // Note that conversion action names must be unique. 
 // If a conversion action already exists with the specified conversion_action_name 
 // the create operation will fail with a ConversionActionError.DUPLICATE_NAME error. 
 'name' => 'Earth to Mars Cruises Conversion #' . Helper::getPrintableDatetime(), 
 'category' => ConversionActionCategory::PBDEFAULT, 
 'type' => ConversionActionType::WEBPAGE, 
 'status' => ConversionActionStatus::ENABLED, 
 'view_through_lookback_window_days' => 15, 
 'value_settings' => new ValueSettings([ 
 'default_value' => 23.41, 
 'always_use_default_value' => true 
 ]) 
 ]); 
 // Creates a conversion action operation. 
 $conversionActionOperation = new ConversionActionOperation(); 
 $conversionActionOperation->setCreate($conversionAction); 
 // Issues a mutate request to add the conversion action. 
 $conversionActionServiceClient = $googleAdsClient->getConversionActionServiceClient(); 
 $response = $conversionActionServiceClient->mutateConversionActions( 
 MutateConversionActionsRequest::build($customerId, [$conversionActionOperation]) 
 ); 
 printf("Added %d conversion actions:%s", $response->getResults()->count(), PHP_EOL); 
 foreach ($response->getResults() as $addedConversionAction) { 
 /** @var ConversionAction $addedConversionAction */ 
 printf( 
 "New conversion action added with resource name: '%s'%s", 
 $addedConversionAction->getResourceName(), 
 PHP_EOL 
 ); 
 } 
 }  
 

Python

 def 
  
 main 
 ( 
 client 
 : 
 GoogleAdsClient 
 , 
 customer_id 
 : 
 str 
 ) 
 - 
> None 
 : 
 conversion_action_service 
 : 
 ConversionActionServiceClient 
 = 
 ( 
 client 
 . 
 get_service 
 ( 
 "ConversionActionService" 
 ) 
 ) 
 # Create the operation. 
 conversion_action_operation 
 : 
 ConversionActionOperation 
 = 
 client 
 . 
 get_type 
 ( 
 "ConversionActionOperation" 
 ) 
 # Create conversion action. 
 conversion_action 
 : 
 ConversionAction 
 = 
 conversion_action_operation 
 . 
 create 
 # Note that conversion action names must be unique. If a conversion action 
 # already exists with the specified conversion_action_name, the create 
 # operation will fail with a ConversionActionError.DUPLICATE_NAME error. 
 conversion_action 
 . 
 name 
 = 
 f 
 "Earth to Mars Cruises Conversion 
 { 
 uuid 
 . 
 uuid4 
 () 
 } 
 " 
 conversion_action 
 . 
 type_ 
 = 
 ( 
 client 
 . 
 enums 
 . 
 ConversionActionTypeEnum 
 . 
 UPLOAD_CLICKS 
 ) 
 conversion_action 
 . 
 category 
 = 
 ( 
 client 
 . 
 enums 
 . 
 ConversionActionCategoryEnum 
 . 
 DEFAULT 
 ) 
 conversion_action 
 . 
 status 
 = 
 client 
 . 
 enums 
 . 
 ConversionActionStatusEnum 
 . 
 ENABLED 
 conversion_action 
 . 
 view_through_lookback_window_days 
 = 
 15 
 # Create a value settings object. 
 value_settings 
 : 
 ConversionAction 
 . 
 ValueSettings 
 = 
 ( 
 conversion_action 
 . 
 value_settings 
 ) 
 value_settings 
 . 
 default_value 
 = 
 15.0 
 value_settings 
 . 
 always_use_default_value 
 = 
 True 
 # Add the conversion action. 
 conversion_action_response 
 : 
 MutateConversionActionsResponse 
 = 
 ( 
 conversion_action_service 
 . 
 mutate_conversion_actions 
 ( 
 customer_id 
 = 
 customer_id 
 , 
 operations 
 = 
 [ 
 conversion_action_operation 
 ], 
 ) 
 ) 
 print 
 ( 
 "Created conversion action " 
 f 
 '" 
 { 
 conversion_action_response 
 . 
 results 
 [ 
 0 
 ] 
 . 
 resource_name 
 } 
 ".' 
 ) 
  

Ruby

 def 
  
 add_conversion_action 
 ( 
 customer_id 
 ) 
  
 # GoogleAdsClient will read a config file from 
  
 # ENV['HOME']/google_ads_config.rb when called without parameters 
  
 client 
  
 = 
  
 Google 
 :: 
 Ads 
 :: 
 GoogleAds 
 :: 
 GoogleAdsClient 
 . 
 new 
  
 # Add a conversion action. 
  
 conversion_action 
  
 = 
  
 client 
 . 
 resource 
 . 
 conversion_action 
  
 do 
  
 | 
 ca 
 | 
  
 ca 
 . 
 name 
  
 = 
  
 "Earth to Mars Cruises Conversion 
 #{ 
 ( 
 Time 
 . 
 new 
 . 
 to_f 
  
 * 
  
 100 
 ) 
 . 
 to_i 
 } 
 " 
  
 ca 
 . 
 type 
  
 = 
  
 :UPLOAD_CLICKS 
  
 ca 
 . 
 category 
  
 = 
  
 :DEFAULT 
  
 ca 
 . 
 status 
  
 = 
  
 :ENABLED 
  
 ca 
 . 
 view_through_lookback_window_days 
  
 = 
  
 15 
  
 # Create a value settings object. 
  
 ca 
 . 
 value_settings 
  
 = 
  
 client 
 . 
 resource 
 . 
 value_settings 
  
 do 
  
 | 
 vs 
 | 
  
 vs 
 . 
 default_value 
  
 = 
  
 15 
  
 vs 
 . 
 always_use_default_value 
  
 = 
  
 true 
  
 end 
  
 end 
  
 # Create the operation. 
  
 conversion_action_operation 
  
 = 
  
 client 
 . 
 operation 
 . 
 create_resource 
 . 
 conversion_action 
 ( 
 conversion_action 
 ) 
  
 # Add the ad group ad. 
  
 response 
  
 = 
  
 client 
 . 
 service 
 . 
 conversion_action 
 . 
 mutate_conversion_actions 
 ( 
  
 customer_id 
 : 
  
 customer_id 
 , 
  
 operations 
 : 
  
 [ 
 conversion_action_operation 
 ] 
 , 
  
 ) 
  
 puts 
  
 "New conversion action with resource name = 
 #{ 
 response 
 . 
 results 
 . 
 first 
 . 
 resource_name 
 } 
 ." 
 end  
 
 . 
 rb 
  

Perl

 sub 
  
 add_conversion_action 
  
 { 
  
 my 
  
 ( 
 $api_client 
 , 
  
 $customer_id 
 ) 
  
 = 
  
 @_ 
 ; 
  
 # Note that conversion action names must be unique. 
  
 # If a conversion action already exists with the specified conversion_action_name, 
  
 # the create operation fails with error ConversionActionError.DUPLICATE_NAME. 
  
 my 
  
 $conversion_action_name 
  
 = 
  
 "Earth to Mars Cruises Conversion #" 
  
 . 
  
 uniqid 
 (); 
  
 # Create a conversion action. 
  
 my 
  
 $conversion_action 
  
 = 
  
 Google::Ads::GoogleAds::V21::Resources:: 
 ConversionAction 
 - 
> new 
 ({ 
  
 name 
  
 = 
>  
 $conversion_action_name 
 , 
  
 category 
  
 = 
>  
 DEFAULT 
 , 
  
 type 
  
 = 
>  
 WEBPAGE 
 , 
  
 status 
  
 = 
>  
 ENABLED 
 , 
  
 viewThroughLookbackWindowDays 
  
 = 
>  
 15 
 , 
  
 valueSettings 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Resources:: 
 ValueSettings 
 - 
> new 
 ({ 
  
 defaultValue 
  
 = 
>  
 23.41 
 , 
  
 alwaysUseDefaultValue 
  
 = 
>  
 "true" 
  
 })}); 
  
 # Create a conversion action operation. 
  
 my 
  
 $conversion_action_operation 
  
 = 
  
 Google::Ads::GoogleAds::V21::Services::ConversionActionService:: 
 ConversionActionOperation 
  
 - 
> new 
 ({ 
 create 
  
 = 
>  
 $conversion_action 
 }); 
  
 # Add the conversion action. 
  
 my 
  
 $conversion_actions_response 
  
 = 
  
 $api_client 
 - 
> ConversionActionService 
 () 
 - 
> mutate 
 ({ 
  
 customerId 
  
 = 
>  
 $customer_id 
 , 
  
 operations 
  
 = 
>  
 [ 
 $conversion_action_operation 
 ]}); 
  
 printf 
  
 "New conversion action added with resource name: '%s'.\n" 
 , 
  
 $conversion_actions_response 
 - 
> { 
 results 
 }[ 
 0 
 ]{ 
 resourceName 
 }; 
  
 return 
  
 1 
 ; 
 } 
  
  

Make sure the conversion_action_type is set to the correct ConversionActionType value. For more guidance on creating conversion actions in the Google Ads API, see Create Conversion Actions .

Retrieve an existing conversion action

You can retrieve details for an existing conversion action by issuing the following query. Make sure the customer ID in the request is set to the Google Ads conversion customer you identified above, and the conversion action type is set to the correct ConversionActionType value.

  SELECT 
  
 conversion_action 
 . 
 resource_name 
 , 
  
 conversion_action 
 . 
 name 
 , 
  
 conversion_action 
 . 
 status 
 FROM 
  
 conversion_action 
 WHERE 
  
 conversion_action 
 . 
 type 
  
 = 
  
 ' INSERT_CONVERSION_ACTION_TYPE 
' 
 

2. Configure tagging and store click IDs

Follow the instructions to confirm autotagging is enabled. Set up your Google Ads account, website, and lead-tracking system to capture and store the GCLID, GBRAID, or WBRAID of each impression and click for your ads. Autotagging is turned on by default for new accounts.

Construct the request

Follow this guidance to construct your UploadClickConversionsRequest and set its fields to appropriate values.

customer_id

Identifies the Google Ads account of your upload. Set this to the Google Ads conversion customer of the account that is the source of the clicks.

job_id

Provides a mechanism for associating your upload requests with the per-job information in offline data diagnostics .

If you don't set this field, the Google Ads API assigns each request a unique value in the range of [2^31, 2^63) . If you would prefer to group multiple requests into a single logical job, set this field to the same value in the range [0, 2^31) on every request in your job.

The job_id in the response contains the job ID for the request, regardless of whether you specified a value or let the Google Ads API assign a value.

partial_failure_enabled

Determines how the Google Ads API handles errors from operations.

This field must be set to true . Follow the partial failures guidelines when processing the response.

debug_enabled

Determines error-reporting behavior for enhanced conversions for leads uploads. The Google Ads API ignores this field when handling uploads for click conversions using gclid , gbraid , or wbraid .

Create click conversion operations

The collection of ClickConversion objects in your UploadClickConversionRequest defines the set of conversions you want to upload. Follow this guidance to construct each ClickConversion and set its fields to appropriate values.

Set the required fields of each conversion operation

Follow these instructions to set the required fields of ClickConversion to appropriate values.

gclid , gbraid , wbraid
The identifier you captured at the time of the click for the conversion's click or impression. Only set one of these fields.
conversion_date_time

The date and time of the conversion.

The value must have a timezone specified, and the format must be yyyy-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 does not have to match the account's timezone. However, if you plan on comparing your uploaded 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. You can find more details and examples in the Help Center and check the Codes and formats for a list of valid timezone IDs.

user_identifiers

Don't set this field when uploading conversions using only click IDs. If this field is set, Google Ads treats the upload operation as an upload for enhanced conversions for leads .

conversion_action

The resource name of the ConversionAction for the click conversion.

The conversion action must have a type of UPLOAD_CLICKS , and must exist in the Google Ads conversion customer of the Google Ads account associated with the click.

conversion_value

The value of the conversion.

currency_code

The currency code of the conversion_value .

Set optional fields of each conversion operation

Review the following list of optional fields and set them on your ClickConversion as needed.

order_id
The transaction ID for the conversion. This field is optional but strongly recommended. If you set it during the upload, you must use it for any adjustments made to the conversion. To learn more about how to use a transaction ID to minimize duplicate conversions, see this Help Center article .
external_attribution_data

If you use third-party tools or homegrown solutions to track conversions, then you may want to give Google Ads only part of the credit for the conversion, or you may want to distribute the credit for a conversion across multiple clicks. Externally attributed conversion imports allow you to upload conversions with fractional credit assigned to each click.

To upload fractional credits, set this field to an ExternalAttributionData object with values for external_attribution_model and external_attribution_credit .

custom_variables

The values for custom conversion variables .

Google Ads does not support custom conversion variables in combination with wbraid or gbraid .

cart_data

You can include shopping cart data for a ClickConversion in the cart_data field, which consists of the following attributes:

  • merchant_id : The ID of the associated Merchant Center account.
  • feed_country_code : The ISO 3166 two-character region code of the Merchant Center feed.
  • feed_language_code : The ISO 639-1 language code of the Merchant Center feed.
  • local_transaction_cost : The sum of all transaction-level discounts, in the currency_code of the ClickConversion .
  • items : The items in the shopping cart.

    Each item in items consists of the following attributes:

  • product_id : The ID of the product, sometimes referred to as the offer ID or item ID.

  • quantity : The quantity of the item.

  • unit_price : The unit price of the item.

conversion_environment

Indicates the environment where this conversion was recorded. For example, App or Web.

Code example

Java

 private 
  
 void 
  
 runExample 
 ( 
  
 GoogleAdsClient 
  
 googleAdsClient 
 , 
  
 long 
  
 customerId 
 , 
  
 long 
  
 conversionActionId 
 , 
  
 String 
  
 gclid 
 , 
  
 String 
  
 gbraid 
 , 
  
 String 
  
 wbraid 
 , 
  
 String 
  
 conversionDateTime 
 , 
  
 Double 
  
 conversionValue 
 , 
  
 Long 
  
 conversionCustomVariableId 
 , 
  
 String 
  
 conversionCustomVariableValue 
 , 
  
 String 
  
 orderId 
 , 
  
 ConsentStatus 
  
 adUserDataConsent 
 ) 
  
 throws 
  
 InvalidProtocolBufferException 
  
 { 
  
 // Verifies that exactly one of gclid, gbraid, and wbraid is specified, as required. 
  
 // See https://developers.google.com/google-ads/api/docs/conversions/upload-clicks for details. 
  
 long 
  
 numberOfIdsSpecified 
  
 = 
  
 Arrays 
 . 
 asList 
 ( 
 gclid 
 , 
  
 gbraid 
 , 
  
 wbraid 
 ). 
 stream 
 (). 
 filter 
 ( 
 idField 
  
 - 
>  
 idField 
  
 != 
  
 null 
 ). 
 count 
 (); 
  
 if 
  
 ( 
 numberOfIdsSpecified 
  
 != 
  
 1 
 ) 
  
 { 
  
 throw 
  
 new 
  
 IllegalArgumentException 
 ( 
  
 "Exactly 1 of gclid, gbraid, or wbraid is required, but " 
  
 + 
  
 numberOfIdsSpecified 
  
 + 
  
 " ID values were provided" 
 ); 
  
 } 
  
 // Constructs the conversion action resource name from the customer and conversion action IDs. 
  
 String 
  
 conversionActionResourceName 
  
 = 
  
 ResourceNames 
 . 
 conversionAction 
 ( 
 customerId 
 , 
  
 conversionActionId 
 ); 
  
 // Creates the click conversion. 
  
 ClickConversion 
 . 
 Builder 
  
 clickConversionBuilder 
  
 = 
  
 ClickConversion 
 . 
 newBuilder 
 () 
  
 . 
 setConversionAction 
 ( 
 conversionActionResourceName 
 ) 
  
 . 
 setConversionDateTime 
 ( 
 conversionDateTime 
 ) 
  
 . 
 setConversionValue 
 ( 
 conversionValue 
 ) 
  
 . 
 setCurrencyCode 
 ( 
 "USD" 
 ); 
  
 // Sets the single specified ID field. 
  
 if 
  
 ( 
 gclid 
  
 != 
  
 null 
 ) 
  
 { 
  
 clickConversionBuilder 
 . 
 setGclid 
 ( 
 gclid 
 ); 
  
 } 
  
 else 
  
 if 
  
 ( 
 gbraid 
  
 != 
  
 null 
 ) 
  
 { 
  
 clickConversionBuilder 
 . 
 setGbraid 
 ( 
 gbraid 
 ); 
  
 } 
  
 else 
  
 { 
  
 clickConversionBuilder 
 . 
 setWbraid 
 ( 
 wbraid 
 ); 
  
 } 
  
 if 
  
 ( 
 conversionCustomVariableId 
  
 != 
  
 null 
 && 
 conversionCustomVariableValue 
  
 != 
  
 null 
 ) 
  
 { 
  
 // Sets the custom variable and value, if provided. 
  
 clickConversionBuilder 
 . 
 addCustomVariables 
 ( 
  
 CustomVariable 
 . 
 newBuilder 
 () 
  
 . 
 setConversionCustomVariable 
 ( 
  
 ResourceNames 
 . 
 conversionCustomVariable 
 ( 
 customerId 
 , 
  
 conversionCustomVariableId 
 )) 
  
 . 
 setValue 
 ( 
 conversionCustomVariableValue 
 )); 
  
 } 
  
 if 
  
 ( 
 orderId 
  
 != 
  
 null 
 ) 
  
 { 
  
 // Sets the order ID (unique transaction ID), if provided. 
  
 clickConversionBuilder 
 . 
 setOrderId 
 ( 
 orderId 
 ); 
  
 } 
  
 // Sets the consent information, if provided. 
  
 if 
  
 ( 
 adUserDataConsent 
  
 != 
  
 null 
 ) 
  
 { 
  
 // Specifies whether user consent was obtained for the data you are uploading. See 
  
 // https://www.google.com/about/company/user-consent-policy for details. 
  
 clickConversionBuilder 
 . 
 setConsent 
 ( 
 Consent 
 . 
 newBuilder 
 (). 
 setAdUserData 
 ( 
 adUserDataConsent 
 )); 
  
 } 
  
 ClickConversion 
  
 clickConversion 
  
 = 
  
 clickConversionBuilder 
 . 
 build 
 (); 
  
 // Creates the conversion upload service client. 
  
 try 
  
 ( 
 ConversionUploadServiceClient 
  
 conversionUploadServiceClient 
  
 = 
  
 googleAdsClient 
 . 
 getLatestVersion 
 (). 
 createConversionUploadServiceClient 
 ()) 
  
 { 
  
 // Uploads the click conversion. Partial failure should always be set to true. 
  
 // 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_service 
  
 UploadClickConversionsResponse 
  
 response 
  
 = 
  
 conversionUploadServiceClient 
 . 
 uploadClickConversions 
 ( 
  
 UploadClickConversionsRequest 
 . 
 newBuilder 
 () 
  
 . 
 setCustomerId 
 ( 
 Long 
 . 
 toString 
 ( 
 customerId 
 )) 
  
 . 
 addConversions 
 ( 
 clickConversion 
 ) 
  
 // Enables partial failure (must be true). 
  
 . 
 setPartialFailure 
 ( 
 true 
 ) 
  
 . 
 build 
 ()); 
  
 // Prints any partial errors returned. 
  
 if 
  
 ( 
 response 
 . 
 hasPartialFailureError 
 ()) 
  
 { 
  
 GoogleAdsFailure 
  
 googleAdsFailure 
  
 = 
  
 ErrorUtils 
 . 
 getInstance 
 (). 
 getGoogleAdsFailure 
 ( 
 response 
 . 
 getPartialFailureError 
 ()); 
  
 // Constructs a protocol buffer printer that will print error details in a concise format. 
  
 Printer 
  
 errorPrinter 
  
 = 
  
 JsonFormat 
 . 
 printer 
 (). 
 omittingInsignificantWhitespace 
 (); 
  
 for 
  
 ( 
 int 
  
 operationIndex 
  
 = 
  
 0 
 ; 
  
 operationIndex 
 < 
 response 
 . 
 getResultsCount 
 (); 
  
 operationIndex 
 ++ 
 ) 
  
 { 
  
 ClickConversionResult 
  
 conversionResult 
  
 = 
  
 response 
 . 
 getResults 
 ( 
 operationIndex 
 ); 
  
 if 
  
 ( 
 ErrorUtils 
 . 
 getInstance 
 (). 
 isPartialFailureResult 
 ( 
 conversionResult 
 )) 
  
 { 
  
 // Prints the errors for the failed operation. 
  
 System 
 . 
 out 
 . 
 printf 
 ( 
 "Operation %d failed with the following errors:%n" 
 , 
  
 operationIndex 
 ); 
  
 for 
  
 ( 
 GoogleAdsError 
  
 resultError 
  
 : 
  
 ErrorUtils 
 . 
 getInstance 
 (). 
 getGoogleAdsErrors 
 ( 
 operationIndex 
 , 
  
 googleAdsFailure 
 )) 
  
 { 
  
 // Prints the error with newlines and extra spaces removed. 
  
 System 
 . 
 out 
 . 
 printf 
 ( 
 "  %s%n" 
 , 
  
 errorPrinter 
 . 
 print 
 ( 
 resultError 
 )); 
  
 } 
  
 } 
  
 else 
  
 { 
  
 // Prints the information about the successful operation. 
  
 StringBuilder 
  
 clickInfoBuilder 
  
 = 
  
 new 
  
 StringBuilder 
 ( 
 "conversion that occurred at " 
 ) 
  
 . 
 append 
 ( 
 String 
 . 
 format 
 ( 
 "'%s' " 
 , 
  
 conversionResult 
 . 
 getConversionDateTime 
 ())) 
  
 . 
 append 
 ( 
 "with " 
 ); 
  
 if 
  
 ( 
 conversionResult 
 . 
 hasGclid 
 ()) 
  
 { 
  
 clickInfoBuilder 
 . 
 append 
 ( 
 String 
 . 
 format 
 ( 
 "gclid '%s'" 
 , 
  
 conversionResult 
 . 
 getGclid 
 ())); 
  
 } 
  
 else 
  
 if 
  
 ( 
 ! 
 conversionResult 
 . 
 getGbraid 
 (). 
 isEmpty 
 ()) 
  
 { 
  
 clickInfoBuilder 
 . 
 append 
 ( 
 String 
 . 
 format 
 ( 
 "gbraid '%s'" 
 , 
  
 conversionResult 
 . 
 getGbraid 
 ())); 
  
 } 
  
 else 
  
 if 
  
 ( 
 ! 
 conversionResult 
 . 
 getWbraid 
 (). 
 isEmpty 
 ()) 
  
 { 
  
 clickInfoBuilder 
 . 
 append 
 ( 
 String 
 . 
 format 
 ( 
 "wbraid '%s'" 
 , 
  
 conversionResult 
 . 
 getWbraid 
 ())); 
  
 } 
  
 else 
  
 { 
  
 clickInfoBuilder 
 . 
 append 
 ( 
 "no click ID" 
 ); 
  
 } 
  
 System 
 . 
 out 
 . 
 printf 
 ( 
 "Operation %d for %s succeeded.%n" 
 , 
  
 operationIndex 
 , 
  
 clickInfoBuilder 
 ); 
  
 } 
  
 } 
  
 } 
  
 } 
 } 
  
  

C#

 public 
  
 void 
  
 Run 
 ( 
 GoogleAdsClient 
  
 client 
 , 
  
 long 
  
 customerId 
 , 
  
 long 
  
 conversionActionId 
 , 
  
 string 
  
 gclid 
 , 
  
 string 
  
 gbraid 
 , 
  
 string 
  
 wbraid 
 , 
  
 string 
  
 conversionTime 
 , 
  
 double 
  
 conversionValue 
 , 
  
 ConsentStatus 
 ? 
  
 adUserDataConsent 
 ) 
 { 
  
 // Get the ConversionActionService. 
  
 ConversionUploadServiceClient 
  
 conversionUploadService 
  
 = 
  
 client 
 . 
 GetService 
 ( 
 Services 
 . 
 V21 
 . 
 ConversionUploadService 
 ); 
  
 // Creates a click conversion by specifying currency as USD. 
  
 ClickConversion 
  
 clickConversion 
  
 = 
  
 new 
  
 ClickConversion 
 () 
  
 { 
  
 ConversionAction 
  
 = 
  
 ResourceNames 
 . 
 ConversionAction 
 ( 
 customerId 
 , 
  
 conversionActionId 
 ), 
  
 ConversionValue 
  
 = 
  
 conversionValue 
 , 
  
 ConversionDateTime 
  
 = 
  
 conversionTime 
 , 
  
 CurrencyCode 
  
 = 
  
 "USD" 
 , 
  
 }; 
  
 // Sets the consent information, if provided. 
  
 if 
  
 ( 
 adUserDataConsent 
  
 != 
  
 null 
 ) 
  
 { 
  
 // Specifies whether user consent was obtained for the data you are uploading. See 
  
 // https://www.google.com/about/company/user-consent-policy 
  
 // for details. 
  
 clickConversion 
 . 
 Consent 
  
 = 
  
 new 
  
 Consent 
 () 
  
 { 
  
 AdUserData 
  
 = 
  
 ( 
 ConsentStatus 
 ) 
 adUserDataConsent 
  
 }; 
  
 } 
  
 // Verifies that exactly one of gclid, gbraid, and wbraid is specified, as required. 
  
 // See https://developers.google.com/google-ads/api/docs/conversions/upload-clicks 
  
 // for details. 
  
 string 
 [] 
  
 ids 
  
 = 
  
 { 
  
 gclid 
 , 
  
 gbraid 
 , 
  
 wbraid 
  
 }; 
  
 int 
  
 idCount 
  
 = 
  
 ids 
 . 
 Where 
 ( 
 id 
  
 = 
>  
 ! 
 string 
 . 
 IsNullOrEmpty 
 ( 
 id 
 )). 
 Count 
 (); 
  
 if 
  
 ( 
 idCount 
  
 != 
  
 1 
 ) 
  
 { 
  
 throw 
  
 new 
  
 ArgumentException 
 ( 
 $"Exactly 1 of gclid, gbraid, or wbraid is " 
  
 + 
  
 $"required, but {idCount} ID values were provided" 
 ); 
  
 } 
  
 // Sets the single specified ID field. 
  
 if 
  
 ( 
 ! 
 string 
 . 
 IsNullOrEmpty 
 ( 
 gclid 
 )) 
  
 { 
  
 clickConversion 
 . 
 Gclid 
  
 = 
  
 gclid 
 ; 
  
 } 
  
 else 
  
 if 
  
 ( 
 ! 
 string 
 . 
 IsNullOrEmpty 
 ( 
 wbraid 
 )) 
  
 { 
  
 clickConversion 
 . 
 Wbraid 
  
 = 
  
 wbraid 
 ; 
  
 } 
  
 else 
  
 if 
  
 ( 
 ! 
 string 
 . 
 IsNullOrEmpty 
 ( 
 gbraid 
 )) 
  
 { 
  
 clickConversion 
 . 
 Gbraid 
  
 = 
  
 gbraid 
 ; 
  
 } 
  
 try 
  
 { 
  
 // Issues a request to upload the click conversion. 
  
 UploadClickConversionsResponse 
  
 response 
  
 = 
  
 conversionUploadService 
 . 
 UploadClickConversions 
 ( 
  
 new 
  
 UploadClickConversionsRequest 
 () 
  
 { 
  
 CustomerId 
  
 = 
  
 customerId 
 . 
 ToString 
 (), 
  
 Conversions 
  
 = 
  
 { 
  
 clickConversion 
  
 }, 
  
 PartialFailure 
  
 = 
  
 true 
 , 
  
 ValidateOnly 
  
 = 
  
 false 
  
 }); 
  
 // Prints the result. 
  
 ClickConversionResult 
  
 uploadedClickConversion 
  
 = 
  
 response 
 . 
 Results 
 [ 
 0 
 ]; 
  
 Console 
 . 
 WriteLine 
 ( 
 $"Uploaded conversion that occurred at " 
  
 + 
  
 $"'{uploadedClickConversion.ConversionDateTime}' from Google " 
  
 + 
  
 $"Click ID '{uploadedClickConversion.Gclid}' to " 
  
 + 
  
 $"'{uploadedClickConversion.ConversionAction}'." 
 ); 
  
 } 
  
 catch 
  
 ( 
 GoogleAdsException 
  
 e 
 ) 
  
 { 
  
 Console 
 . 
 WriteLine 
 ( 
 "Failure:" 
 ); 
  
 Console 
 . 
 WriteLine 
 ( 
 $"Message: {e.Message}" 
 ); 
  
 Console 
 . 
 WriteLine 
 ( 
 $"Failure: {e.Failure}" 
 ); 
  
 Console 
 . 
 WriteLine 
 ( 
 $"Request ID: {e.RequestId}" 
 ); 
  
 throw 
 ; 
  
 } 
 } 
  
  

PHP

 public static function runExample( 
 GoogleAdsClient $googleAdsClient, 
 int $customerId, 
 int $conversionActionId, 
 ?string $gclid, 
 ?string $gbraid, 
 ?string $wbraid, 
 ?string $orderId, 
 string $conversionDateTime, 
 float $conversionValue, 
 ?string $conversionCustomVariableId, 
 ?string $conversionCustomVariableValue, 
 ?int $adUserDataConsent 
 ) { 
 // Verifies that exactly one of gclid, gbraid, and wbraid is specified, as required. 
 // See https://developers.google.com/google-ads/api/docs/conversions/upload-clicks for details. 
 $nonNullFields = array_filter( 
 [$gclid, $gbraid, $wbraid], 
 function ($field) { 
 return !is_null($field); 
 } 
 ); 
 if (count($nonNullFields) !== 1) { 
 throw new \UnexpectedValueException( 
 sprintf( 
 "Exactly 1 of gclid, gbraid or wbraid is required, but %d ID values were " 
 . "provided", 
 count($nonNullFields) 
 ) 
 ); 
 } 
 // Creates a click conversion by specifying currency as USD. 
 $clickConversion = new ClickConversion([ 
 'conversion_action' = 
> ResourceNames::forConversionAction($customerId, $conversionActionId), 
 'conversion_value' => $conversionValue, 
 'conversion_date_time' => $conversionDateTime, 
 'currency_code' => 'USD' 
 ]); 
 // Sets the single specified ID field. 
 if (!is_null($gclid)) { 
 $clickConversion->setGclid($gclid); 
 } elseif (!is_null($gbraid)) { 
 $clickConversion->setGbraid($gbraid); 
 } else { 
 $clickConversion->setWbraid($wbraid); 
 } 
 if (!is_null($conversionCustomVariableId) && !is_null($conversionCustomVariableValue)) { 
 $clickConversion->setCustomVariables([new CustomVariable([ 
 'conversion_custom_variable' => ResourceNames::forConversionCustomVariable( 
 $customerId, 
 $conversionCustomVariableId 
 ), 
 'value' => $conversionCustomVariableValue 
 ])]); 
 } 
 // Sets the consent information, if provided. 
 if (!empty($adUserDataConsent)) { 
 // Specifies whether user consent was obtained for the data you are uploading. See 
 // https://www.google.com/about/company/user-consent-policy for details. 
 $clickConversion->setConsent(new Consent(['ad_user_data' => $adUserDataConsent])); 
 } 
 if (!empty($orderId)) { 
 // Sets the order ID (unique transaction ID), if provided. 
 $clickConversion->setOrderId($orderId); 
 } 
 // Issues a request to upload the click conversion. 
 $conversionUploadServiceClient = $googleAdsClient->getConversionUploadServiceClient(); 
 /** @var UploadClickConversionsResponse $response */ 
 // 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_service 
 $response = $conversionUploadServiceClient->uploadClickConversions( 
 // Uploads the click conversion. Partial failure should always be set to true. 
 UploadClickConversionsRequest::build($customerId, [$clickConversion], true) 
 ); 
 // Prints the status message if any partial failure error is returned. 
 // Note: The details of each partial failure error are not printed here, you can refer to 
 // the example HandlePartialFailure.php to learn more. 
 if ($response->hasPartialFailureError()) { 
 printf( 
 "Partial failures occurred: '%s'.%s", 
 $response->getPartialFailureError()->getMessage(), 
 PHP_EOL 
 ); 
 } else { 
 // Prints the result if exists. 
 /** @var ClickConversionResult $uploadedClickConversion */ 
 $uploadedClickConversion = $response->getResults()[0]; 
 printf( 
 "Uploaded click conversion that occurred at '%s' from Google Click ID '%s' " . 
 "to '%s'.%s", 
 $uploadedClickConversion->getConversionDateTime(), 
 $uploadedClickConversion->getGclid(), 
 $uploadedClickConversion->getConversionAction(), 
 PHP_EOL 
 ); 
 } 
 }  
 

Python

 def 
  
 main 
 ( 
 client 
 : 
 GoogleAdsClient 
 , 
 customer_id 
 : 
 str 
 , 
 conversion_action_id 
 : 
 str 
 , 
 gclid 
 : 
 Optional 
 [ 
 str 
 ], 
 conversion_date_time 
 : 
 str 
 , 
 conversion_value 
 : 
 str 
 , 
 conversion_custom_variable_id 
 : 
 Optional 
 [ 
 str 
 ], 
 conversion_custom_variable_value 
 : 
 Optional 
 [ 
 str 
 ], 
 gbraid 
 : 
 Optional 
 [ 
 str 
 ], 
 wbraid 
 : 
 Optional 
 [ 
 str 
 ], 
 order_id 
 : 
 Optional 
 [ 
 str 
 ], 
 ad_user_data_consent 
 : 
 Optional 
 [ 
 str 
 ], 
 ) 
 - 
> None 
 : 
  
 """Creates a click conversion with a default currency of USD. 
 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. 
 gclid: The Google Click Identifier ID. If set, the wbraid and gbraid 
 parameters must be None. 
 conversion_date_time: The the date and time of the conversion (should be 
 after 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 custom 
 variable to associate with the upload. 
 conversion_custom_variable_value: The str value of the conversion custom 
 variable to associate with the upload. 
 gbraid: The GBRAID for the iOS app conversion. If set, the gclid and 
 wbraid parameters must be None. 
 wbraid: The WBRAID for the iOS app conversion. If set, the gclid and 
 gbraid parameters must be None. 
 order_id: The order ID for the click conversion. 
 ad_user_data_consent: The ad user data consent for the click. 
 """ 
 click_conversion 
 : 
 ClickConversion 
 = 
 client 
 . 
 get_type 
 ( 
 "ClickConversion" 
 ) 
 conversion_upload_service 
 : 
 ConversionUploadServiceClient 
 = 
 ( 
 client 
 . 
 get_service 
 ( 
 "ConversionUploadService" 
 ) 
 ) 
 conversion_action_service 
 : 
 ConversionActionServiceClient 
 = 
 ( 
 client 
 . 
 get_service 
 ( 
 "ConversionActionService" 
 ) 
 ) 
 click_conversion 
 . 
 conversion_action 
 = 
 ( 
 conversion_action_service 
 . 
 conversion_action_path 
 ( 
 customer_id 
 , 
 conversion_action_id 
 ) 
 ) 
 # Sets the single specified ID field. 
 if 
 gclid 
 : 
 click_conversion 
 . 
 gclid 
 = 
 gclid 
 elif 
 gbraid 
 : 
 click_conversion 
 . 
 gbraid 
 = 
 gbraid 
 else 
 : 
 click_conversion 
 . 
 wbraid 
 = 
 wbraid 
 click_conversion 
 . 
 conversion_value 
 = 
 float 
 ( 
 conversion_value 
 ) 
 click_conversion 
 . 
 conversion_date_time 
 = 
 conversion_date_time 
 click_conversion 
 . 
 currency_code 
 = 
 "USD" 
 if 
 conversion_custom_variable_id 
 and 
 conversion_custom_variable_value 
 : 
 conversion_custom_variable 
 : 
 CustomVariable 
 = 
 client 
 . 
 get_type 
 ( 
 "CustomVariable" 
 ) 
 conversion_custom_variable 
 . 
 conversion_custom_variable 
 = 
 ( 
 conversion_upload_service 
 . 
 conversion_custom_variable_path 
 ( 
 customer_id 
 , 
 conversion_custom_variable_id 
 ) 
 ) 
 conversion_custom_variable 
 . 
 value 
 = 
 conversion_custom_variable_value 
 click_conversion 
 . 
 custom_variables 
 . 
 append 
 ( 
 conversion_custom_variable 
 ) 
 if 
 order_id 
 : 
 click_conversion 
 . 
 order_id 
 = 
 order_id 
 # Sets the consent information, if provided. 
 if 
 ad_user_data_consent 
 : 
 # Specifies whether user consent was obtained for the data you are 
 # uploading. For more details, see: 
 # https://www.google.com/about/company/user-consent-policy 
 click_conversion 
 . 
 consent 
 . 
 ad_user_data 
 = 
 client 
 . 
 enums 
 . 
 ConsentStatusEnum 
 [ 
 ad_user_data_consent 
 ] 
 # Uploads the click conversion. Partial failure must be set to True here. 
 # 
 # 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_service 
 request 
 : 
 UploadClickConversionsRequest 
 = 
 client 
 . 
 get_type 
 ( 
 "UploadClickConversionsRequest" 
 ) 
 request 
 . 
 customer_id 
 = 
 customer_id 
 request 
 . 
 conversions 
 . 
 append 
 ( 
 click_conversion 
 ) 
 request 
 . 
 partial_failure 
 = 
 True 
 conversion_upload_response 
 : 
 UploadClickConversionsResponse 
 = 
 ( 
 conversion_upload_service 
 . 
 upload_click_conversions 
 ( 
 request 
 = 
 request 
 , 
 ) 
 ) 
 uploaded_click_conversion 
 : 
 ClickConversionResult 
 = 
 ( 
 conversion_upload_response 
 . 
 results 
 [ 
 0 
 ] 
 ) 
 print 
 ( 
 f 
 "Uploaded conversion that occurred at " 
 f 
 '" 
 { 
 uploaded_click_conversion 
 . 
 conversion_date_time 
 } 
 " from ' 
 f 
 'Google Click ID " 
 { 
 uploaded_click_conversion 
 . 
 gclid 
 } 
 " ' 
 f 
 'to " 
 { 
 uploaded_click_conversion 
 . 
 conversion_action 
 } 
 "' 
 ) 
  

Ruby

 def 
  
 upload_offline_conversion 
 ( 
  
 customer_id 
 , 
  
 conversion_action_id 
 , 
  
 gclid 
 , 
  
 gbraid 
 , 
  
 wbraid 
 , 
  
 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 parameters 
  
 client 
  
 = 
  
 Google 
 :: 
 Ads 
 :: 
 GoogleAds 
 :: 
 GoogleAdsClient 
 . 
 new 
  
 # Verifies that exactly one of gclid, gbraid, and wbraid is specified, as required. 
  
 # See https://developers.google.com/google-ads/api/docs/conversions/upload-clicks for details. 
  
 identifiers_specified 
  
 = 
  
 [ 
 gclid 
 , 
  
 gbraid 
 , 
  
 wbraid 
 ]. 
 reject 
  
 { 
 | 
 v 
 | 
  
 v 
 . 
 nil? 
 } 
 . 
 count 
  
 if 
  
 identifiers_specified 
  
 != 
  
 1 
  
 raise 
  
 "Must specify exactly one of GCLID, GBRAID, and WBRAID. " 
  
 \ 
  
 " 
 #{ 
 identifiers_specified 
 } 
 values were provided." 
  
 end 
  
 click_conversion 
  
 = 
  
 client 
 . 
 resource 
 . 
 click_conversion 
  
 do 
  
 | 
 cc 
 | 
  
 cc 
 . 
 conversion_action 
  
 = 
  
 client 
 . 
 path 
 . 
 conversion_action 
 ( 
 customer_id 
 , 
  
 conversion_action_id 
 ) 
  
 # Sets the single specified ID field. 
  
 if 
  
 ! 
 gclid 
 . 
 nil? 
  
 cc 
 . 
 gclid 
  
 = 
  
 gclid 
  
 elsif 
  
 ! 
 gbraid 
 . 
 nil? 
  
 cc 
 . 
 gbraid 
  
 = 
  
 gbraid 
  
 else 
  
 cc 
 . 
 wbraid 
  
 = 
  
 wbraid 
  
 end 
  
 cc 
 . 
 conversion_value 
  
 = 
  
 conversion_value 
 . 
 to_f 
  
 cc 
 . 
 conversion_date_time 
  
 = 
  
 conversion_date_time 
  
 cc 
 . 
 currency_code 
  
 = 
  
 'USD' 
  
 if 
  
 conversion_custom_variable_id 
 && 
 conversion_custom_variable_value 
  
 cc 
 . 
 custom_variables 
 << 
 client 
 . 
 resource 
 . 
 custom_variable 
  
 do 
  
 | 
 cv 
 | 
  
 cv 
 . 
 conversion_custom_variable 
  
 = 
  
 client 
 . 
 path 
 . 
 conversion_custom_variable 
 ( 
  
 customer_id 
 , 
  
 conversion_custom_variable_id 
 ) 
  
 cv 
 . 
 value 
  
 = 
  
 conversion_custom_variable_value 
  
 end 
  
 end 
  
 # Sets the consent information, if provided. 
  
 unless 
  
 ad_user_data_consent 
 . 
 nil? 
  
 cc 
 . 
 consent 
  
 = 
  
 client 
 . 
 resource 
 . 
 consent 
  
 do 
  
 | 
 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-policy 
  
 c 
 . 
 ad_user_data 
  
 = 
  
 ad_user_data_consent 
  
 end 
  
 end 
  
 end 
  
 response 
  
 = 
  
 client 
 . 
 service 
 . 
 conversion_upload 
 . 
 upload_click_conversions 
 ( 
  
 customer_id 
 : 
  
 customer_id 
 , 
  
 # 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_service 
  
 conversions 
 : 
  
 [ 
 click_conversion 
 ] 
 , 
  
 partial_failure 
 : 
  
 true 
 , 
  
 ) 
  
 if 
  
 response 
 . 
 partial_failure_error 
 . 
 nil? 
  
 result 
  
 = 
  
 response 
 . 
 results 
 . 
 first 
  
 puts 
  
 "Uploaded conversion that occurred at 
 #{ 
 result 
 . 
 conversion_date_time 
 } 
 " 
  
 \ 
  
 "from Google Click ID 
 #{ 
 result 
 . 
 gclid 
 } 
 to 
 #{ 
 result 
 . 
 conversion_action 
 } 
 ." 
  
 else 
  
 failures 
  
 = 
  
 client 
 . 
 decode_partial_failure_error 
 ( 
 response 
 . 
 partial_failure_error 
 ) 
  
 puts 
  
 "Request failed. Failure details:" 
  
 failures 
 . 
 each 
  
 do 
  
 | 
 failure 
 | 
  
 failure 
 . 
 errors 
 . 
 each 
  
 do 
  
 | 
 error 
 | 
  
 puts 
  
 " 
 \t 
 #{ 
 error 
 . 
 error_code 
 . 
 error_code 
 } 
 : 
 #{ 
 error 
 . 
 message 
 } 
 " 
  
 end 
  
 end 
  
 end 
 end  
 
 . 
 rb 
  

Perl

 sub 
  
 upload_offline_conversion 
  
 { 
  
 my 
  
 ( 
  
 $api_client 
 , 
  
 $customer_id 
 , 
  
 $conversion_action_id 
 , 
  
 $gclid 
 , 
  
 $gbraid 
 , 
  
 $wbraid 
 , 
  
 $conversion_date_time 
 , 
  
 $conversion_value 
 , 
  
 $conversion_custom_variable_id 
 , 
  
 $conversion_custom_variable_value 
 , 
  
 $order_id 
 , 
  
 $ad_user_data_consent 
  
 ) 
  
 = 
  
 @_ 
 ; 
  
 # Verify that exactly one of gclid, gbraid, and wbraid is specified, as required. 
  
 # See https://developers.google.com/google-ads/api/docs/conversions/upload-clicks for details. 
  
 my 
  
 $number_of_ids_specified 
  
 = 
  
 grep 
  
 { 
  
 defined 
  
 $_ 
  
 } 
  
 ( 
 $gclid 
 , 
  
 $gbraid 
 , 
  
 $wbraid 
 ); 
  
 if 
  
 ( 
 $number_of_ids_specified 
  
 != 
  
 1 
 ) 
  
 { 
  
 die 
  
 sprintf 
  
 "Exactly 1 of gclid, gbraid, or wbraid is required, " 
  
 . 
  
 "but %d ID values were provided.\n" 
 , 
  
 $number_of_ids_specified 
 ; 
  
 } 
  
 # Create a click conversion by specifying currency as USD. 
  
 my 
  
 $click_conversion 
  
 = 
  
 Google::Ads::GoogleAds::V21::Services::ConversionUploadService:: 
 ClickConversion 
  
 - 
> new 
 ({ 
  
 conversionAction 
  
 = 
>  
 Google::Ads::GoogleAds::V21::Utils::ResourceNames:: 
 conversion_action 
 ( 
  
 $customer_id 
 , 
  
 $conversion_action_id 
  
 ), 
  
 conversionDateTime 
  
 = 
>  
 $conversion_date_time 
 , 
  
 conversionValue 
  
 = 
>  
 $conversion_value 
 , 
  
 currencyCode 
  
 = 
>  
 "USD" 
  
 }); 
  
 # Set the single specified ID field. 
  
 if 
  
 ( 
 defined 
  
 $gclid 
 ) 
  
 { 
  
 $click_conversion 
 - 
> { 
 gclid 
 } 
  
 = 
  
 $gclid 
 ; 
  
 } 
  
 elsif 
  
 ( 
 defined 
  
 $gbraid 
 ) 
  
 { 
  
 $click_conversion 
 - 
> { 
 gbraid 
 } 
  
 = 
  
 $gbraid 
 ; 
  
 } 
  
 else 
  
 { 
  
 $click_conversion 
 - 
> { 
 wbraid 
 } 
  
 = 
  
 $wbraid 
 ; 
  
 } 
  
 if 
  
 ( 
 $conversion_custom_variable_id 
 && 
 $conversion_custom_variable_value 
 ) 
  
 { 
  
 $click_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 
  
 })]; 
  
 } 
  
 if 
  
 ( 
 defined 
  
 $order_id 
 ) 
  
 { 
  
 # Set the order ID (unique transaction ID), if provided. 
  
 $click_conversion 
 - 
> { 
 orderId 
 } 
  
 = 
  
 $order_id 
 ; 
  
 } 
  
 # 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. 
  
 $click_conversion 
 - 
> { 
 consent 
 } 
  
 = 
  
 Google::Ads::GoogleAds::V21::Common:: 
 Consent 
 - 
> new 
 ({ 
  
 adUserData 
  
 = 
>  
 $ad_user_data_consent 
  
 }); 
  
 } 
  
 # Issue a request to upload the click conversion. Partial failure should 
  
 # always be set to true. 
  
 # 
  
 # 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_service 
  
 my 
  
 $upload_click_conversions_response 
  
 = 
  
 $api_client 
 - 
> ConversionUploadService 
 () 
 - 
> upload_click_conversions 
 ({ 
  
 customerId 
  
 = 
>  
 $customer_id 
 , 
  
 conversions 
  
 = 
>  
 [ 
 $click_conversion 
 ], 
  
 partialFailure 
  
 = 
>  
 "true" 
  
 }); 
  
 # Print any partial errors returned. 
  
 if 
  
 ( 
 $upload_click_conversions_response 
 - 
> { 
 partialFailureError 
 }) 
  
 { 
  
 printf 
  
 "Partial error encountered: '%s'.\n" 
 , 
  
 $upload_click_conversions_response 
 - 
> { 
 partialFailureError 
 }{ 
 message 
 }; 
  
 } 
  
 # Print the result if valid. 
  
 my 
  
 $uploaded_click_conversion 
  
 = 
  
 $upload_click_conversions_response 
 - 
> { 
 results 
 }[ 
 0 
 ]; 
  
 if 
  
 ( 
 %$uploaded_click_conversion 
 ) 
  
 { 
  
 printf 
  
 "Uploaded conversion that occurred at '%s' from Google Click ID '%s' " 
  
 . 
  
 "to the conversion action with resource name '%s'.\n" 
 , 
  
 $uploaded_click_conversion 
 - 
> { 
 conversionDateTime 
 }, 
  
 $uploaded_click_conversion 
 - 
> { 
 gclid 
 }, 
  
 $uploaded_click_conversion 
 - 
> { 
 conversionAction 
 }; 
  
 } 
  
 return 
  
 1 
 ; 
 } 
  
  

curl

 # 
This  
code  
example  
uploads  
a  
click  
conversion. # 
 # 
Variables: # 
API_VERSION, # 
CUSTOMER_ID, # 
DEVELOPER_TOKEN, # 
MANAGER_CUSTOMER_ID, # 
OAUTH2_ACCESS_TOKEN: # 
See  
https://developers.google.com/google-ads/api/rest/auth#request_headers # 
 for 
  
details. # 
 # 
CONVERSION_ACTION_RESOURCE_NAME:  
Resource  
name  
of  
the  
conversion  
action # 
associated  
with  
this  
conversion. # 
GCLID:  
The  
Google  
click  
ID  
 ( 
gclid ) 
  
associated  
with  
this  
conversion. # 
CONVERSION_VALUE:  
The  
value  
of  
the  
conversion  
 for 
  
the  
advertiser. # 
CONVERSION_DATE_TIME:  
The  
date  
 time 
  
at  
which  
the  
conversion  
occurred.  
The # 
format  
is  
 "yyyy-mm-dd hh:mm:ss+|-hh:mm" 
,  
 for 
  
example, # 
 "2019-01-01 12:32:45-08:00" 
. # 
CURRENCY_CODE:  
The  
currency  
code  
of  
the  
conversion  
value.  
This  
is  
the # 
ISO  
 4217 
  
 3 
-character  
currency  
code.  
For  
example:  
USD,  
EUR. # 
CONVERSION_CUSTOM_VARIABLE:  
The  
name  
of  
the  
conversion  
custom  
variable. # 
CONVERSION_CUSTOM_VARIABLE_VALUE:  
The  
value  
of  
the  
conversion  
custom # 
variable. # 
ORDER_ID:  
The  
order  
ID  
of  
the  
conversion. curl -f --request POST \ 
 "https://googleads.googleapis.com/v${API_VERSION}/customers/${CUSTOMER_ID}:uploadClickConversions" \ 
 --header "Content-Type: application/json" \ 
 --header "developer-token: ${DEVELOPER_TOKEN}" \ 
 --header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \ 
 --header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \ 
 --data @- <<EOF 
 { 
 "conversions": [ 
 { 
 "conversionAction": "${CONVERSION_ACTION_RESOURCE_NAME}", 
 "gclid": "${GCLID}", 
 "conversionValue": ${CONVERSION_VALUE}, 
 "conversionDateTime": "${CONVERSION_DATE_TIME}", 
 "currencyCode": "${CURRENCY_CODE}", 
 "customVariables": [ 
 { 
 "conversionCustomVariable": "${CONVERSION_CUSTOM_VARIABLE}", 
 "value": "${CONVERSION_CUSTOM_VARIABLE_VALUE}" 
 } 
 ], 
 "orderId": "${ORDER_ID}", 
 "consent": { 
 "adUserData": "GRANTED" 
 } 
 } 
 ], 
 "partialFailure": true 
 } 
 EOF  
 
  

Troubleshoot

Offline data diagnostics provide a single resource for reviewing the overall health of your uploads on an ongoing basis. However, during implementation you can use the information in this section to investigate any errors reported in the partial_failure_error field of the response.

Some of the most common errors when uploading conversion actions are authorization errors, such as USER_PERMISSION_DENIED . Double check that you have the customer ID in your request set to the Google Ads conversion customer which owns the conversion action. Visit our authorization guide for more details and see our common errors guide for tips on how to debug these different errors.

Debug common errors

Error
The specified conversion action has a type that is not valid for uploading click conversions. Make sure the ConversionAction specified in your upload request has type UPLOAD_CLICKS .
The specified conversion action is either not enabled or cannot be found within the uploading customer_id . Retrieve information about your conversion setup to make sure the conversion action in your upload is enabled and is owned by the customer_id of the upload request.
The conversion action is newly created. Wait at least 6 hours after the action is created before retrying the failed conversions.
The customer_id of the request is not the same customer ID that was the Google Ads API conversion account at the time of the click. Update the customer_id of the request to the correct customer.
Google Ads cannot find the combination of click ID and customer_id . Review the requirements for customer_id and confirm you are uploading using the correct Google Ads account.
Multiple conversions in the request have the same combination of click ID, conversion_date_time and conversion_action . Remove duplicate conversions from your request.
A conversion with the same combination of click ID, conversion_date_time , and conversion_action was previously uploaded. Ignore this error if you were retrying the upload and this conversion previously succeeded. If you want to add another conversion in addition to the previously uploaded conversion, adjust the conversion_date_time of the ClickConversion to avoid duplicating the previously uploaded conversion.
Google Ads cannot find the combination of click ID and customer_id . Review the requirements for customer_id and confirm you are uploading using the correct Google Ads account.
The imported click occurred before the timeframe specified in the click_through_lookback_window_days field. A change to the click_through_lookback_window_days only impacts clicks recorded after the change , so changing the lookback window wouldn't resolve this error for the particular click. If appropriate, change the conversion_action to another action with a longer lookback window.
The conversion_date_time is before the date and time of the click. Update the conversion_date_time to a later value.
The ClickConversion has a value set for both gbraid and wbraid . Update the conversion to use only one click ID, and make sure you are not combining multiple clicks into the same conversion. Each click has only one click ID.
Check the location of the GoogleAdsError to determine which of the following issues led to the error.
  • The ClickConversion has a value set for gclid as well as at least one of gbraid or wbraid . Update the conversion to use only one click ID, and make sure you are not combining multiple clicks into the same conversion. Each click has only one click ID.
  • The ClickConversion has a value set for either gbraid or wbraid and has a value for custom_variables . Google Ads does not support custom variables for a conversion with a gbraid or wbraid click ID. Unset the custom_variables field of the conversion.

Conversions in reports

Uploaded conversions are reflected in reports for the impressiondate of the original click , not the date of the upload request or the date of the conversion_date_time of the ClickConversion .

It takes up to 3 hours for imported conversion statistics to appear in your Google Ads account for last-click attribution. For other search attribution models, it can take longer than 3 hours. Consult the data freshness guide for more information.

Design a Mobile Site
View Site in Mobile | Classic
Share by: