Google Ads API: How to Send Batch Requests? - google-api

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)

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

Related

Can GA4-API fetch the data from requests made with a combination of minute and region and sessions?

Problem
With UA, I was able to get the number of sessions per region per minute (a combination of minute, region, and sessions), but is this not possible with GA4?
If not, is there any plan to support this in the future?
Detail
I ran GA4 Query Explorer with date, hour, minute, region in Dimensions and sessions in Metrics.
But I got an incompatibility error.
What I tried
I have checked with GA4 Dimensions & Metrics Explorer and confirmed that the combination of minute and region is not possible. (see image below).
(updated 2022/05/16 15:35)Checked by Code Execution
I ran it with ruby.
require "google/analytics/data/v1beta/analytics_data"
require 'pp'
require 'json'
ENV['GOOGLE_APPLICATION_CREDENTIALS'] = '' # service acount file path
client = ::Google::Analytics::Data::V1beta::AnalyticsData::Client.new
LIMIT_SIZE = 1000
offset = 0
loop do
request = Google::Analytics::Data::V1beta::RunReportRequest.new(
property: "properties/xxxxxxxxx",
date_ranges: [
{ start_date: '2022-04-01', end_date: '2022-04-30'}
],
dimensions: %w(date hour minute region).map { |d| { name: d } },
metrics: %w(sessions).map { |m| { name: m } },
keep_empty_rows: false,
offset: offset,
limit: LIMIT_SIZE
)
ret = client.run_report(request)
dimension_headers = ret.dimension_headers.map(&:name)
metric_headers = ret.metric_headers.map(&:name)
puts (dimension_headers + metric_headers).join(',')
ret.rows.each do |row|
puts (row.dimension_values.map(&:value) + row.metric_values.map(&:value)).join(',')
end
offset += LIMIT_SIZE
break if ret.row_count <= offset
end
The result was an error.
3:The dimensions and metrics are incompatible.. debug_error_string:{"created":"#1652681913.393028000","description":"Error received from peer ipv4:172.217.175.234:443","file":"src/core/lib/surface/call.cc","file_line":953,"grpc_message":"The dimensions and metrics are incompatible.","grpc_status":3}
Error in your code, Make sure you use the actual dimension name and not the UI name. The correct name of that dimension is dateHourMinute not Date hour and minute
dimensions: %w(dateHourMinute).map { |d| { name: d } },
The query explore returns this request just fine
results
Limited use for region dimension
The as for region. As the error message states the dimensions and metrics are incompatible. The issue being that dateHourMinute can not be used with region. Switch to date or datehour
at the time of writing this is a beta api. I have sent a message off to google to find out if this is working as intended or if it may be changed.

Time Delta problem in Hackerrank not taking good answer / Python 3

The hackerrank challenge is in the following url: https://www.hackerrank.com/challenges/python-time-delta/problem
I got testcase 0 correct, but the website is saying that I have wrong answers for testcase 1 and 2, but in my pycharm, I copied the website expected output and compared with my output and they were exactly the same.
Please have a look at my code.
#!/bin/pyth
# Complete the time_delta function below.
from datetime import datetime
def time_delta(tmp1, tmp2):
dicto = {'Jan':1, 'Feb':2, 'Mar':3,
'Apr':4, 'May':5, 'Jun':6,
'Jul':7, 'Aug':8, 'Sep':9,
'Oct':10, 'Nov':11, 'Dec':12}
# extracting t1 from first timestamp without -xxxx
t1 = datetime(int(tmp1[2]), dicto[tmp1[1]], int(tmp1[0]), int(tmp1[3][:2]),int(tmp1[3][3:5]), int(tmp1[3][6:]))
# extracting t1 from second timestamp without -xxxx
t2 = datetime(int(tmp2[2]), dicto[tmp2[1]], int(tmp2[0]), int(tmp2[3][:2]), int(tmp2[3][3:5]), int(tmp2[3][6:]))
# converting -xxxx of timestamp 1
t1_utc = int(tmp1[4][:3])*3600 + int(tmp1[4][3:])*60
# converting -xxxx of timestamp 2
t2_utc = int(tmp2[4][:3])*3600 + int(tmp2[4][3:])*60
# absolute difference
return abs(int((t1-t2).total_seconds()-(t1_utc-t2_utc)))
if __name__ == '__main__':
# fptr = open(os.environ['OUTPUT_PATH'], 'w')
t = int(input())
for t_itr in range(t):
tmp1 = list(input().split(' '))[1:]
tmp2 = list(input().split(' '))[1:]
delta = time_delta(tmp1, tmp2)
print(delta)
t1_utc = int(tmp1[4][:3])*3600 + int(tmp1[4][3:])*60
For a time zone like +0715, you correctly add “7 hours of seconds” and “15 minutes of seconds”
For a timezone like -0715, you are adding “-7 hours of seconds” and “+15 minutes of seconds”, resulting in -6h45m, instead of -7h15m.
You need to either use the same “sign” for both parts, or apply the sign afterwards.

Got Error "Command Get label of interval: not available for current selection" when trying to edit selections with certain labels

I was trying to replace certain selections of sounds with silences, but before I could get into the essential part, the "Get label from interval" command failed before I was able to check whether I'd obtained the correct output.
Error Message I've Got on Praat
I'd thought it was some problems with the toy audio I played with, so I switched to another one but strangely enough, every time I always got stuck with the third interval in the sequence. Screenshot available here:
The Third Interval was Strangely not Available
The code I'm using right now is quite simple as below:
There could be problems with how I process the intervals labelled as "sounding", but it should not be relevant to the error I got here.
----------------------------------------------------------------------------
soundname$ = chooseReadFile$: "Open a sound file"
sound = Read from file: soundname$
gridname$ = chooseReadFile$: "Select the corresponding TextGrid file."
grid = Read from file: gridname$
tier = 1
soundEnd = Get total duration
numOfIntervals = Get number of intervals: tier
writeInfoLine: "Number of Intervals:", numOfIntervals
appendInfoLine: "**** Starting to Replace Selected Sounds... ****"
for interval from 1 to numOfIntervals
appendInfoLine: "Interval#", interval
label$ = Get label of interval: tier, interval
appendInfoLine: "Interval#", interval, ": ", label$
if label$ == "sounding"
startTime = Get starting point: tier, interval
endTime = Get end point: tier, interval
newSilence = Create Sound from formula: "new_silence", 1, startTime, endTime, 44100, ~ 0
before = Extract part: 0, startTime, "rectangular", 1, "no"
after = Extract part: endTime, soundEnd, "rectangular", 1, "no"
selectObject: before, newSilence, after
new = Concatenate
Write to WAV file... "new".wav
removeObject: before, newSilence, after
endif
endfor
appendInfoLine: "Finish!"
----------------------------------------------------------------------------
I'd suspected that it was because of my editing that some shifts occurred in the TextGrid-- however, since I only supplanted the sounds with silences that were of the same length, there should not be impacts on sounds or TextGrids afterwards. However, since I never had the chance to output some playable audio results, all I inferred above could not be corroborated by solid truth.
Thank you all so much for your kind attention and help in advance!

Getting curent time of specific time zone in classical asp

Here goes the problem:
I have a requirement that an (classical)asp application should display different content at specific EST(Eastern Time) duration. The clients can arrive from any timezone, but the server should take only EST time into consideration.
I am sorry for my ignorance, but I am from ASP.Net background and have no idea of doing this in classical asp.
This SO Link guided me to get UTC, but I still don't know how to convert it to EST.
Any help will be greatly appreciated.
If your server is in EST then not an issue, otherwise you'll need to compensate for it.
mytime = now()
myadjtime = DateAdd("h", 3, mytime)
will add 3 hours to the current time
<%
mytime = now()
response.write hour(mytime)
if hour(mytime) >=12 then
response.write "It's noon or later"
end if
%>
you can check http://worldclockapi.com web site. You can take current time as timezone..
example: http://worldclockapi.com/api/json/est/now
if you go to above address you can see EST current date, time and other data..
example: http://worldclockapi.com/api/json/pst/now
if you go to above address, you can see PST current date, time and other data...
and you can use XMLHTTP for getting data from external site.
`
private Function GETHTTP(adres)
Set StrHTTP = Server.CreateObject("Microsoft.XMLHTTP" )
StrHTTP.Open "GET" , adres, false
StrHTTP.sEnd
GETHTTP = StrHTTP.Responsetext
Set StrHTTP = Nothing
End Function
full_data= GETHTTP("http://worldclockapi.com/api/json/est/now")
`
after you use split code by comma:
parts=split(full_data,",")
response.write parts(1)

In KRL How can I get the current year, month, and day?

I am working on an application in which I need to get the current year, month, and day. Is there a way to get this information in the pre block of a rule?
Can I get this data as a string or a number or both?
There are currently time functions documented on http://docs.kynetx.com/docs/Time but none of them seem to work for what I am trying to do.
Is there a way to set the timezone when getting this data?
I was able to do it using strftime which appears to be an undocumented feature so use with caution.
ruleset a60x518 {
meta {
name "date-test"
description <<
date-test
>>
author "Mike Grace"
logging on
}
rule testing {
select when pageview ".*"
pre {
retTime = time:strftime(time:now({"tz":"America/Denver"}), "%c");
month = time:strftime(time:now({"tz":"America/Denver"}), "%B");
year = time:strftime(time:now({"tz":"America/Denver"}), "%Y");
day = time:strftime(time:now({"tz":"America/Denver"}), "%d");
}
{
notify("time",retTime) with sticky = true;
notify("month",month) with sticky = true;
notify("year",year) with sticky = true;
notify("day",day) with sticky = true;
}
}
}
App run on example.com twice. Once with the timezone set to New York and onother time set to Denver
I used this site http://www.statoids.com/tus.html to get the correct strings to use for the timezone. I have no idea if they all work. I just found this site and tried a few and they worked so use with caution.
Perhaps the docs got reverted. For convenience, here is the documentation for strftime:
time:strftime()
Convert a datetime string to a different format
Usage
time:strftime(`<string>`,`<format>`)
Valid format arguments to strftime follow the POSIX strftime conventions.
Samples
time:strftime(xTime,”%F %T”) # 2010-10-06 18:15:24
time:strftime(xTime,”%F”) # 2010-10-06
time:strftime(xTime,”%T”) # 18:19:29
time:strftime(xTime,”%A %d %b %Y”) # Wednesday 06 Oct 2010
time:strftime(xTime,”%c”) # Oct 6, 2010 6:25:55 PM
The other time functions:
time:now()
Current datetime based upon user’s location data
Usage
time:now()
time:now({“tz” : <timezone>)
time:new()
Create a new RFC 3339 datetime string from a string (allows some flexibility in how the source string is formatted)
Usage
time:new() # Equivalent to time:now()
time:new(<string>)
Valid formats for the datetime source string can be found in ISO8601 (v2000).
time:add()
Add (or subtract) a specific number of time units to a source string
Usage
time:add(<string>,{<unit> : n})

Resources