yadirGetReportFun <-
function(ReportType = "CUSTOM_REPORT",
DateRangeType = "CUSTOM_DATE",
DateFrom = Sys.Date() - 31,
DateTo = Sys.Date() - 1,
FieldNames = c("CampaignName","Impressions","Clicks","Cost"),
FilterList = NULL,
Goals = NULL,
AttributionModels = NULL,
IncludeVAT = "YES",
IncludeDiscount = "NO",
Login = getOption("ryandexdirect.user"),
AgencyAccount = getOption("ryandexdirect.agency_account"),
Token = NULL,
TokenPath = yadirTokenPath(),
SkipErrors = TRUE){
# start time
proc_start <- Sys.time()
# field names
Fields <- paste0("<FieldNames>",FieldNames, "</FieldNames>", collapse = "")
# for limited accounts
limit_reached <- c()
# filters
if(!is.null(FilterList)){
fil_list <- NA
filt <- FilterList
for(fil in filt){
val <- strsplit(paste0(strsplit(fil ," ")[[1]][3:length(strsplit(fil ," ")[[1]])], collapse = ""), split = ",| |;")[[1]]
fil_list <- paste0(fil_list[!is.na(fil_list)],
paste0("<Filter>",
paste0("<Field>",strsplit(fil ," ")[[1]][1], "</Field>"),
paste0("<Operator>",strsplit(fil ," ")[[1]][2], "</Operator>"),
paste0(paste0("<Values>",val, "</Values>"), collapse = ""),"</Filter>"))
}}
# Goals and attributtion
Goals <- ifelse(is.null(Goals), "", paste0("<Goals>",Goals, "</Goals>", collapse = ""))
AttributionModels <- ifelse(is.null(AttributionModels), "", paste0("<AttributionModels>",AttributionModels, "</AttributionModels>", collapse = ""))
# compose request body
queryBody <- paste0('
<ReportDefinition xmlns="http://api.direct.yandex.com/v5/reports">
<SelectionCriteria>',
ifelse(DateRangeType == "CUSTOM_DATE",paste0("<DateFrom>",DateFrom,"</DateFrom>","<DateTo>",DateTo,"</DateTo>") ,"" ),
ifelse(is.null(FilterList),"",fil_list),
'
</SelectionCriteria>',
Goals,AttributionModels,Fields,'
<ReportName>',paste0("MyReport ", Sys.time()),'</ReportName>
<ReportType>',ReportType,'</ReportType>
<DateRangeType>',DateRangeType ,'</DateRangeType>
<Format>TSV</Format>
<IncludeVAT>',IncludeVAT,'</IncludeVAT>
<IncludeDiscount>',IncludeDiscount,'</IncludeDiscount>
</ReportDefinition>')
# result frame
result <- data.frame()
for(current_login in Login){
# auth
curToken <- tech_auth(login = current_login, token = Token, AgencyAccount = AgencyAccount, TokenPath = TokenPath)
# time counter
parsing_time <- 0
server_time <- 0
# start message
packageStartupMessage("-----------------------------------------------------------")
packageStartupMessage(paste0("Loading data by ",current_login))
# send request to API
serv_start_time <- Sys.time()
answer <- POST("https://api.direct.yandex.com/v5/reports",
body = queryBody,
add_headers( Authorization = paste0("Bearer ",curToken),
'Accept-Language' = "ru",
skipReportHeader = "true" ,
skipReportSummary = "true" ,
'Client-Login' = current_login,
returnMoneyInMicros = "false",
processingMode = "auto"))
if(substr(answer$status_code,1,1) == 4){
packageStartupMessage("Error in request parameters or limit on the number of requests or reports in the queue is exceeded. In this case, analyze the error message, correct the request and send it again.")
# parse error
content(answer, "parsed","text/xml",encoding = "UTF-8") %>%
xml_find_all(xpath = ".//reports:ApiError//reports:requestId") %>%
xml_text() %>%
message(" > Request Id")
content(answer, "parsed","text/xml",encoding = "UTF-8") %>%
xml_find_all(xpath = ".//reports:ApiError//reports:errorCode") %>%
xml_text() %>%
message(" > Error Code")
content(answer, "parsed","text/xml",encoding = "UTF-8") %>%
xml_find_all(xpath = ".//reports:ApiError//reports:errorMessage") %>%
xml_text() %>%
message(" > Error Message")
content(answer, "parsed","text/xml",encoding = "UTF-8") %>%
xml_find_all(xpath = ".//reports:ApiError//reports:errorDetail") %>%
xml_text() %>%
message(" > Error Detail")
if ( SkipErrors == FALSE ) {
err_detail <- content(answer, "parsed","text/xml",encoding = "UTF-8") %>%
xml_find_all(xpath = ".//reports:ApiError//reports:errorDetail") %>%
xml_text()
stop(err_detail)
} else {
next
}
}
if(answer$status_code == 500){
packageStartupMessage(paste0(current_login," - ",xml_text(content(answer, "parsed","text/xml",encoding = "UTF-8"))))
packageStartupMessage("While generating the report an error occurred on the server. If for this report the error on the server occurred for the first time, try to generate a report again. If the error persists, contact support.")
if ( SkipErrors == FALSE ) {
err_detail <- content(answer, "parsed","text/xml",encoding = "UTF-8") %>%
xml_find_all(xpath = ".//reports:ApiError//reports:errorDetail") %>%
xml_text()
stop(err_detail)
} else {
next
}
}
if(answer$status_code == 201){
packageStartupMessage("The report has been successfully queued for offline generation.", appendLF = T)
packageStartupMessage("Proccesing", appendLF = F)
packageStartupMessage("|", appendLF = F)
}
if(answer$status_code == 202){
packageStartupMessage("Report generation is not completed yet.", appendLF = F)
}
while(answer$status_code != 200){
answer <- POST("https://api.direct.yandex.com/v5/reports",
body = queryBody,
add_headers( Authorization = paste0("Bearer ",curToken),
'Accept-Language' = "ru",
skipReportHeader = "true" ,
skipReportSummary = "true" ,
'Client-Login' = current_login,
returnMoneyInMicros = "false",
processingMode = "auto"))
packageStartupMessage("=", appendLF = F)
if(answer$status_code == 500){
stop("While generating the report an error occurred on the server. If for this report the error on the server occurred for the first time, try to generate a report again. If the error persists, contact support.")
}
if(answer$status_code == 502){
stop("Request processing time exceeded server limit.")
}
Sys.sleep(5)
}
packageStartupMessage("|", appendLF = T)
# succes message
server_time <- round(difftime(Sys.time(), serv_start_time , units ="secs"),0)
packageStartupMessage("Report successfully generated and transmitted in response body.", appendLF = T)
packageStartupMessage(paste0("Server time: ",server_time , " sec."), appendLF = T)
# pars start time
pasr_start_time <- Sys.time()
if(answer$status_code == 200){
df_new <- suppressMessages(content(answer, "parsed", "text/tab-separated-values", encoding = "UTF-8"))
# check data
if(nrow(df_new) == 0){
packageStartupMessage("Your request did not return any data, carefully check the specified filter and report period, and then try again.")
next
}
# check if there are APi limits
if (nrow(df_new) >= 1000000) {
warning(current_login,': You have reached the limits of Yandex.Direct API. Try to use "FetchBy" parameter with DateRangeType = "CUSTOM_DATE", "DateFrom" and "DateTo". If you are already using it, try to choose a smaller value.')
limit_reached <- append(limit_reached, current_login)
}
# timing message
parsing_time <- round(difftime(Sys.time(), pasr_start_time , units ="secs"),0)
packageStartupMessage(paste0("Parsing time: ", parsing_time, " sec."), appendLF = T)
# request id
packageStartupMessage(paste0("RequestID: ",answer$headers$requestid), appendLF = T)
# add login
if(length(Login) > 1){
df_new$Login <- current_login}
# add to result
result <- rbind(result, df_new)
# end of cycle
}
}
# check limits
if ( length(limit_reached) > 0 ) {
attr(result, "limit_reached") <- limit_reached
packageStartupMessage("Limit of 1 000 000 rows reached by next accounts: ", paste(limit_reached, collapse = ", "))
}
# tech messages
total_work_time <- round(difftime(Sys.time(), proc_start , units ="secs"),0)
packageStartupMessage(paste0("Total time: ",total_work_time, " sec."))
packageStartupMessage(paste0(round(as.integer(server_time) / as.integer(total_work_time) * 100, 0), "% server time rate."))
packageStartupMessage(paste0(round(as.integer(parsing_time) / as.integer(total_work_time) * 100, 0), "% parsing time rate."))
packageStartupMessage("Number of rows is ", nrow(df_new))
packageStartupMessage(paste0("RequestID: ",answer$headers$requestid))
packageStartupMessage("-----------------------------------------------------------")
# return result
return(result)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.