(Auto) Document your Google Tag Manager implementation

3 minute read


You might already noticed that I am a huge fan of documentation. The sweat spot I am a fool for is automation, and this is what I covered in the Create a Google Analytics implementation doc using R post. Today, we will generalize this into pulling the Google Tag Manager configuration and feeding it into a Google Sheet.


We will use the googleAuthR package to access the Google Tag Manager API and get the info we need. The pattern of URL(s) to point our GET requests are :

  • https://www.googleapis.com/tagmanager/v1/accounts
  • https://www.googleapis.com/tagmanager/v1/accounts/ACCOUNT_ID/containers/
  • https://www.googleapis.com/tagmanager/v1/accounts/ACCOUNT_ID/containers/CONTAINER_ID/tags
  • https://www.googleapis.com/tagmanager/v1/accounts/ACCOUNT_ID/containers/CONTAINER_ID/triggers
  • https://www.googleapis.com/tagmanager/v1/accounts/ACCOUNT_ID/containers/CONTAINER_ID/variables

Obviously, this is only a subset of the things we can do with the Google Tag Manager API since practically we only work on a read.only mode. However, we can update, delete and create Google Tag Manager objects in a similar fashion.


library(googlesheets) ## In order to push it to a Google Sheet

## Set the desired scopes for our problem(s)
options(googleAuthR.scopes.selected = c('https://www.googleapis.com/auth/tagmanager.delete.containers',

## Now authenticate to Google
gar_auth(new_user = T)
## Auth with `googlesheets` as well (since this can be a different account)

Next, let’s define the functions that will perform the requests to the Google Tag Manager API. Note, that you can use the autoGoogleAPI to create an R package but it is fairly simple to just define the functions using the generic template provided in googleAuthR.

## Define functions for the `googletagmanagerv1` package
## but let's use them directly here
accounts.list <- function() {
    url <- "https://www.googleapis.com/tagmanager/v1/accounts"
    # tagmanager.accounts.list
    f <- gar_api_generator(url, "GET", data_parse_function = function(x) x)


containers.list <- function(accountId) {
  url <- paste0("https://www.googleapis.com/tagmanager/v1/accounts/",accountId,"/containers/")
  # tagmanager.tags.list
  f <- gar_api_generator(url, "GET", data_parse_function = function(x) x)

tags.list <- function(accountId,containerId) {
  url <- paste0("https://www.googleapis.com/tagmanager/v1/accounts/",accountId,"/containers/",containerId,"/tags")
  # tagmanager.tags.list
  f <- gar_api_generator(url, "GET", data_parse_function = function(x) x)

triggers.list <- function(accountId,containerId) {
  url <- paste0("https://www.googleapis.com/tagmanager/v1/accounts/",accountId,"/containers/",containerId,"/triggers")
  # tagmanager.triggers.list
  f <- gar_api_generator(url, "GET", data_parse_function = function(x) x)

variables.list <- function(accountId,containerId) {
  url <- paste0("https://www.googleapis.com/tagmanager/v1/accounts/",accountId,"/containers/",containerId,"/variables")
  # tagmanager.variables.list
  f <- gar_api_generator(url, "GET", data_parse_function = function(x) x)

DISCLAIMER : I am a bit lazy to define a more elegant parsing of the f() in order to get more stuff out of the parameter, so we’ll have a list() within this column and we will process it when needed.


Now, we can use a for() loop to get all containers under an account into a separate Google Sheet. Since the example runs for the GTM of this blog the loop reduces to a single pass.

## We can get the accounts using the `accounts.list()`
## Sample Ids (originating from this blog)
accountId <- 65691
containerId <- 71466

time <- 3;
## A loop for generic use
for (acc_Id in accountId){
  for (con_Id in containerId) {
    container.tags <- tags.list(acc_Id,con_Id)
    container.triggers <- triggers.list(acc_Id,con_Id)
    container.variables <- variables.list(acc_Id,con_Id)

    ## Parameter is a `JSON` (so in `R` this is a `list`), that we will not use for now
    # str(container.tags$tags$parameter)

    ## Objects of interest
    tags <- container.tags$tags
    triggers <- container.triggers$triggers
    variables <- container.variables$variables

    ## Register a new Google Sheet to pass the data
    gs_new(paste("(Auto) GTM Implementation - ",acc_Id,"_",con_Id), verbose = TRUE)
    s_id <- gs_title(paste("(Auto) GTM Implementation - ",acc_Id,"_", con_Id), verbose = TRUE)
    yo.tags <- gs_ws_new(ss=s_id, ws_title="Tags" , input = tags[,1:10], trim = TRUE)
    yo.triggers <- gs_ws_new(ss=s_id, ws_title="Triggers", input = triggers, trim = TRUE)
    yo.variables <- gs_ws_new(ss=s_id, ws_title="Variables", input = variables, trim = TRUE)

    ## Get Google Sheet URL
    # s_id$browser_url
    # > https://docs.google.com/spreadsheets/d/1qibV3BSOtzSlI0vG6JC8xnzqnu6TnpFuxabaYN2vXeI/

  ## This is used to cool off the Google Drive API calls...
  ## Since we only write to one Google Sheet we don't need it in this run.
  # Sys.sleep(time)

End result

Now, we have a Google Sheet populated with the basics of the implementation that we can munge further to make it more presentable.

(Auto) GTM Implementation - 65691_71466


Hope this helps you!

Leave a Comment