Building your own Google R library

Mark Edmondson

2020-06-15

Build a Google API library for R

Generating your function

Creating your own API should be a matter of consulting the Google API documentation, and filling in the required details.

gar_api_generator() has these components:

Example below for generating a function:

Using your generated function

The function generated uses path_args and pars_args to create a template, but when the function is called you will want to pass dynamic data to them. This is done via the path_arguments and pars_arguments parameters.

path_args and pars_args and path_arguments and pars_arguments all accept named lists.

If a name in path_args is present in path_arguments, then it is substituted in. This way you can pass dynamic parameters to the constructed function. Likewise for pars_args and pars_arguments.

Body data

A lot of Google APIs look for you to send data in the Body of the request. This is done after you construct the function. googleAuthR uses httr’s JSON parsing via jsonlite to construct JSON from R lists.

Construct your list, then use jsonlite::toJSON to check if its in the correct format as specified by the Google documentation. This is often the hardest part using the API.

To aid debugging use the options(googleAuthR.verbose = 0) to see all the sent and recieved HTTP requests, and also write what was sent as JSON in the body is written to a file called request_debug.rds in the working directory.

Example:

library(googleAuthR)
library(googleAnalyticsR)
options(googleAuthR.verbose = 0)

ga_auth()
blah <- google_analytics_4(1212121, date_range = c(Sys.Date() - 7, Sys.Date()), metrics = "sessions")
Calling APIv4....
Single v4 batch
Token exists.
Valid local token
Request: https://analyticsreporting.googleapis.com/v4/reports:batchGet/
Body JSON parsed to: {"reportRequests":[{"viewId":"ga:121211","dateRanges":[{"startDate":"2017-01-06","endDate":"2017-01-13"}],"samplingLevel":"DEFAULT","metrics":[{"expression":"ga:sessions","alias":"sessions","formattingType":"METRIC_TYPE_UNSPECIFIED"}],"pageToken":"0","pageSize":1000,"includeEmptyRows":true}]}
-> POST /v4/reports:batchGet/ HTTP/1.1
-> Host: analyticsreporting.googleapis.com
-> User-Agent: googleAuthR/0.4.0.9000 (gzip)
-> Accept: application/json, text/xml, application/xml, */*
-> Content-Type: application/json
-> Accept-Encoding: gzip
-> Authorization: Bearer ya29XXXXX_EhpEot1ZPNP28MUmSz5EyQ7lY3kgNCFEefYv-Zof3a1RSwezgMJ5llCO44TA9iHi51c
-> Content-Length: 295
-> 
>> {"reportRequests":[{"viewId":"ga:1212121","dateRanges":[{"startDate":"2017-01-06","endDate":"2017-01-13"}],"samplingLevel":"DEFAULT","metrics":[{"expression":"ga:sessions","alias":"sessions","formattingType":"METRIC_TYPE_UNSPECIFIED"}],"pageToken":"0","pageSize":1000,"includeEmptyRows":true}]}

<- HTTP/1.1 200 OK
<- Content-Type: application/json; charset=UTF-8
<- Vary: Origin
<- Vary: X-Origin
<- Vary: Referer
<- Content-Encoding: gzip
<- Date: Fri, 13 Jan 2017 10:45:38 GMT
<- Server: ESF
<- Cache-Control: private
<- X-XSS-Protection: 1; mode=block
<- X-Frame-Options: SAMEORIGIN
<- X-Content-Type-Options: nosniff
<- Alt-Svc: quic=":443"; ma=2592000; v="35,34"
<- Transfer-Encoding: chunked
<- 
Downloaded [1] rows from a total of [1].

> readRDS("request_debug.rds")
$url
[1] "https://analyticsreporting.googleapis.com/v4/reports:batchGet/"

$request_type
[1] "POST"

$body_json
{"reportRequests":[{"viewId":"ga:1212121","dateRanges":[{"startDate":"2017-01-06","endDate":"2017-01-13"}],"samplingLevel":"DEFAULT","metrics":[{"expression":"ga:sessions","alias":"sessions","formattingType":"METRIC_TYPE_UNSPECIFIED"}],"pageToken":"0","pageSize":1000,"includeEmptyRows":true}]}

Auto-build libraries

From 0.4 is helper functions that use Google’s API Discovery service.

This is a meta-API which holds all the necessary details to build a supported Google API, which is all modern Google APIs. At the time of writing this is 152 libraries.

These libraries aren’t intended to be submitted to CRAN or used straight away, but should take away a lot of documentation and function building work so you can concentrate on tests, examples and helper functions for your users.

Get a list of the current APIs via gar_discovery_apis_list()

To get details of a particular API, use its name and version in the gar_discovery_api() function:

You can then pass this list to gar_create_package() along with a folder path to create all the files necessary for an R library. There are arguments to set it up with RStudio project files, do a CRAN CMD check and upload it to Github.

Creating an API library from scratch - Example with goo.gl

Below is an example building a link shortner R package using googleAuthR. It was done referring to the documentation for Google URL shortener. Note the help docs specifies the steps outlined above. These are in general the steps for every Google API.

  1. Creating a project
  2. Activate API
  3. Provide scope
  4. Specify the base URL (in this case it was https://www.googleapis.com/urlshortener/v1/url)
  5. Specify the httr request type e.g. POST
  6. Constructing a body request
  7. Giving the response format

Example goo.gl R library

library(googleAuthR)
## change the native googleAuthR scopes to the one needed.
options("googleAuthR.scopes.selected" = 
        c("https://www.googleapis.com/auth/urlshortener"))
#' Shortens a url using goo.gl
#'
#' @param url URl to shorten with goo.gl
#' 
#' @return a string of the short URL
shorten_url <- function(url){
  
  body = list(
    longUrl = url
  )
  
  f <- gar_api_generator("https://www.googleapis.com/urlshortener/v1/url",
                         "POST",
                         data_parse_function = function(x) x$id)
  
  f(the_body = body)
  
}
#' Expands a url that has used goo.gl
#'
#' @param shortUrl Url that was shortened with goo.gl
#' 
#' @return a string of the expanded URL
expand_url <- function(shortUrl){
  
  f <- gar_api_generator("https://www.googleapis.com/urlshortener/v1/url",
                         "GET",
                         pars_args = list(shortUrl = "shortUrl"),
                         data_parse_function = function(x) x)
                         
  f(pars_arguments = list(shortUrl = shortUrl))
  
}
#' Get analytics of a url that has used goo.gl
#'
#' @param shortUrl Url that was shortened with goo.gl
#' @param timespan The time period for the analytics data
#' 
#' @return a dataframe of the goo.gl Url analytics
analytics_url <- function(shortUrl, 
                          timespan = c("allTime", "month", "week","day","twoHours")){
  
  timespan <- match.arg(timespan)
    
  f <- gar_api_generator("https://www.googleapis.com/urlshortener/v1/url",
                         "GET",
                         pars_args = list(shortUrl = "shortUrl",
                                          projection = "FULL"),
                         data_parse_function = function(x) { 
                                    a <- x$analytics 
                                    return(a[timespan][[1]])
                                    })
  
  f(pars_arguments = list(shortUrl = shortUrl))
}
#' Get the history of the authenticated user
#' 
#' @return a dataframe of the goo.gl user's history
user_history <- function(){
  f <- gar_api_generator("https://www.googleapis.com/urlshortener/v1/url/history",
                         "GET",
                         data_parse_function = function(x) x$items)
  
  f()
}

To use the above functions:

Creating a Google Calendar list

Another example is shown below to fetch your Google calendar entries. The below uses the API skeletons functions that are auto generated via the gar_discovery_api functions.

Make sure the calendar API is activated for your Google Project at below URL: https://console.cloud.google.com/apis/api/calendar-json.googleapis.com/overview

To use your function: