Search code examples
google-apigoogle-ads-apigoogle-api-python-client

Google Ads API: How to Send Batch Requests?


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)



Solution

  • 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...]