Skip to content

Passing Fields as arguments in gads_keyword_plan_historical_metrics function #20

Open
@Fluke95

Description

@Fluke95

Hi!
There are 2 additional Fields (aggregateMetrics, historicalMetricsOptions) in Ads API HistoricalMetrics Documentation which may be added in request body in order to adjust the response.
In your gads_keyword_plan_historical_metrics function, which uses this endpoint, there's no option to specify them, so I've decided to try this on my own :)

Default results look like this:

INPUT_KEYWORDS <- c("pizza", "coca-cola", "coca cola", "nike", "car", "cars","seo", "search engine optimisation", "search engine optimization")
KEYWORD_PLAN_ID <- 543641455
default_result <- gads_keyword_plan_historical_metrics(
  keyword_plan_id = KEYWORD_PLAN_ID,
  verbose = TRUE
)
default_result$historical_data |> dplyr::filter(search_query == "pizza")

A tibble: 12 × 4
search_query month year monthly_searches

1 pizza OCTOBER 2021 9140000
2 pizza NOVEMBER 2021 6120000
3 pizza DECEMBER 2021 6120000
4 pizza JANUARY 2022 6120000
5 pizza FEBRUARY 2022 7480000
6 pizza MARCH 2022 11100000
7 pizza APRIL 2022 16600000
8 pizza MAY 2022 13600000
9 pizza JUNE 2022 16600000
10 pizza JULY 2022 20400000
11 pizza AUGUST 2022 20400000
12 pizza SEPTEMBER 2022 16600000

It returns data list with 2 dataframes: main_data and historical_data (with search volumes for last 12 months).

However, when I've modified your function a bit, I've managed to adjust the response. Now it returns device aggregated data and historical metrics for 3 months only:

library(gargle)
library(stringr)
library(httr)
library(jsonlite)
library(dplyr)
library(tidyr)
library(purrr)

CUSTOMER_ID <- getOption("gads.customer.id")
LOGIN_CUSTOMER_ID <- getOption("gads.login.customer.id")

# prepare request body
request_body <- list(
  aggregateMetrics = list(
    aggregateMetricTypes = "DEVICE"
  ),
  historicalMetricsOptions = list(
    yearMonthRange = list(
      start = list(
        year = "2022",
        month = "JANUARY"
      ),
      end = list(
        year = "2022",
        month = "MARCH"
      )
    )
  )
)
### IMPORTANT
# body request list has to be converted to json, otherwise `request_retry` function will throw an error:
# Error in curl::handle_setform(handle, .list = req$fields) :
#   Unsupported value type for form field 'aggregateMetrics'.
request_body_json <- jsonlite::toJSON(
  request_body,
  pretty = TRUE,
  auto_unbox = TRUE)

# build query
out <- request_build(
  method   = "POST",
  path     = str_glue('{options("gads.api.version")}/customers/{CUSTOMER_ID}/keywordPlans/{KEYWORD_PLAN_ID}:generateHistoricalMetrics'),
  token    = gads_token(),
  base_url = getOption('gads.base.url'),
  body = request_body_json # code changed here
)

# send request
ans <- request_retry(
  out,
  encode = "multipart",
  add_headers(
    `developer-token`= gads_developer_token(),
    `login-customer-id` = LOGIN_CUSTOMER_ID)
)

# ... <other code>

# pars result
data <- response_process(ans, error_message = gads_check_errors2, remember = FALSE)

Now, when you unpack the data list, it returns 3 dataframes: main_data and historical_data (with search volumes for selected months, 3 months in this case) and aggregateMetricResults with sum of search count broken down by device type.

historical <- tibble(data = data$metrics) %>% unnest_wider("data") %>%
  unnest_wider("keywordMetrics") %>% select("searchQuery",
                                            "monthlySearchVolumes") %>% unnest_longer("monthlySearchVolumes") %>%
  unnest_wider("monthlySearchVolumes") %>% rename_with(getOption("gads.column.name.case.fun"))
historical |> dplyr::filter(search_query == "pizza")

A tibble: 3 × 4
search_query month year monthly_searches

1 pizza JANUARY 2022 6120000
2 pizza FEBRUARY 2022 7480000
3 pizza MARCH 2022 11100000

Sample unpacked device data:

purrr::flatten_df(data$aggregateMetricResults)

A tibble: 3 × 2
device searchCount

1 DESKTOP 2693749
2 MOBILE 12669313
3 TABLET 239938

What do you think about enhancing your function with such option and adding it to your package? I may try figuring out how to implement creating and managing keywordplans or requesting ideas endpoint.
Let me know what do you think about it. Great work on the package.
Cheers!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions