I'm using Google Ads API v11 to upload conversions and adjust conversions. I send hundreds of conversions each day and want to start sending batch requests instead.

I've followed Google's documentation and I upload/ adjust conversions exactly the way they stated. https://developers.google.com/google-ads/api/docs/conversions/upload-clicks https://developers.google.com/google-ads/api/docs/conversions/upload-adjustments

I could not find any good explanation or example on how to send batch requests: https://developers.google.com/google-ads/api/reference/rpc/v11/BatchJobService

Below is my code, an example of how I adjust hundreds of conversions. An explanation of how to do so with batch requests would be very appreciated.

# Adjust the conversion value of an existing conversion, via Google Ads API def adjust_offline_conversion(client,     customer_id,     conversion_action_id,     gclid,     conversion_date_time,     adjustment_date_time,     restatement_value,     adjustment_type='RESTATEMENT'):     # Check that gclid is valid string else exit the function     if type(gclid) is not str:         return None     # Check if datetime or string, if string make as datetime     if type(conversion_date_time) is str:         conversion_date_time = datetime.strptime(conversion_date_time, '%Y-%m-%d %H:%M:%S')     # Add 1 day forward to conversion time to avoid this error (as explained by Google: "The Offline Conversion cannot happen before the ad click. Add 1-2 days to your conversion time in your upload, or check that the time zone is properly set.")     to_datetime_plus_one = conversion_date_time + timedelta(days=1)     # If time is bigger than now, set as now (it will be enough to avoid the original google error, but to avoid a new error since google does not support future dates that are bigger than now)     to_datetime_plus_one = to_datetime_plus_one if to_datetime_plus_one < datetime.utcnow() else datetime.utcnow()     # We must convert datetime back to string + add time zone suffix (+00:00 or -00:00 this is utc) **in order to work with google ads api**     adjusted_string_date = to_datetime_plus_one.strftime('%Y-%m-%d %H:%M:%S') + "+00:00"     conversion_adjustment_type_enum = client.enums.ConversionAdjustmentTypeEnum     # Determine the adjustment type.     conversion_adjustment_type = conversion_adjustment_type_enum[adjustment_type].value     # Associates conversion adjustments with the existing conversion action.     # The GCLID should have been uploaded before with a conversion     conversion_adjustment = client.get_type("ConversionAdjustment")     conversion_action_service = client.get_service("ConversionActionService")     conversion_adjustment.conversion_action = (         conversion_action_service.conversion_action_path(             customer_id, conversion_action_id         )     )     conversion_adjustment.adjustment_type = conversion_adjustment_type     conversion_adjustment.adjustment_date_time = adjustment_date_time.strftime('%Y-%m-%d %H:%M:%S') + "+00:00"     # Set the Gclid Date     conversion_adjustment.gclid_date_time_pair.gclid = gclid     conversion_adjustment.gclid_date_time_pair.conversion_date_time = adjusted_string_date     # Sets adjusted value for adjustment type RESTATEMENT.     if conversion_adjustment_type == conversion_adjustment_type_enum.RESTATEMENT.value:         conversion_adjustment.restatement_value.adjusted_value = float(restatement_value)     conversion_adjustment_upload_service = client.get_service("ConversionAdjustmentUploadService")     request = client.get_type("UploadConversionAdjustmentsRequest")     request.customer_id = customer_id     request.conversion_adjustments = [conversion_adjustment]     request.partial_failure = True     response = (         conversion_adjustment_upload_service.upload_conversion_adjustments(             request=request,         )     )     conversion_adjustment_result = response.results[0]     print(         f"Uploaded conversion that occurred at "         f'"{conversion_adjustment_result.adjustment_date_time}" '         f"from Gclid "         f'"{conversion_adjustment_result.gclid_date_time_pair.gclid}"'         f' to "{conversion_adjustment_result.conversion_action}"'     ) # Iterate every row (subscriber) and call the "adjust conversion" function for it df.apply(lambda row: adjust_offline_conversion(client=client                                                    , customer_id=customer_id                                                    , conversion_action_id='xxxxxxx'                                                    , gclid=row['click_id']                                                    , conversion_date_time=row['subscription_time']                                                    , adjustment_date_time=datetime.utcnow()                                                    , restatement_value=row['revenue'])                                                    , axis=1) 

Tag:google-ads-api, google-api, google-api-python-client

2 comments.

  1. stitz

    I managed to solve it in the following way:

    The conversion upload and adjustment are not supported in the Batch Processing, as they are not listed here.

    However, it is possible to upload multiple conversions in one request since the conversions[] field (list) could be populated with several conversions, not only a single conversion as I mistakenly thought.

    So if you're uploading conversions/ adjusting conversions you can simply upload them in batch this way:

    Instead of uploading one conversion:

    request.conversions = [conversion]

    Upload several:

    request.conversions = [conversion_1, conversion_2, conversion_3...]

    Going the same way for conversions adjustment upload:

    request.conversion_adjustments = [conversion_adjustment_1, conversion_adjustment_2, conversion_adjustment_3...]
    1. stitz

      As you mentioned, you can send a list of ClickConversion objects through and "bulk upload" multiple conversions at a time. I do recommend using the Partial Failure feature to allow successful conversions to upload and not block the ones that fail to upload.

Add a new comment.