Google Analytics 4 API into R

Author
Affiliation

LB

TPS

Published

March 26, 2025

Autenticazione

Inserisco la mail collegata ad analytics.

ga_auth(email = "..." )

Proseguo l’autenticazione su Browser flaggando tutti i campi.

ga_account_list(type = "ga4")
metadati <- ga_meta(propertyId = "...")

Vedo la lista degli account a cui ho accesso e poi posso vedere metadati associati, tra cui il nome delle dimensioni/metriche presenti in una data property.

Set Up

Definisco alcune variabili per l’estrazione: property_id, from_date, to_date, ga4_dimensions, ga4_metrics.

Property ID

Scelgo la property da cui estrarre i dati.

property_id = "property_id" #recuperato da ga_account_list()

Date

Definisco range temporale che mi interessa.

from_date <- "2023-09-12"
to_date <- "2023-09-19"

Dimensioni

Seleziono le dimensioni che mi servono, scritte tra virgolette. Il nome API lo recupero o dai metadati oppure dalla pagina: https://developers.google.com/analytics/devguides/reporting/data/v1/api-schema?hl=it, contenente la lista delle dimensioni/metriche con descrizione.

ga4_dimensions <- c(
  "date", 
  "month", 
  "sessionDefaultChannelGroup", 
  "eventName"
)

Metriche

Seleziono le dimensioni che mi servono, scritte tra virgolette. Il nome API lo recupero o dai metadati oppure dalla pagina: https://developers.google.com/analytics/devguides/reporting/data/v1/api-schema?hl=it, contenente la lista delle dimensioni/metriche con descrizione.

ga4_metrics <- c(
  "sessions", 
  "eventCount", 
  "engagedSessions", 
  "bounceRate", 
  "averageSessionDuration", 
  "totalUsers"
)

Estrazione

La funzione ga_data() prende in input property_id, date_range, dimensions, metrics e gli passiamo le variabili definite prima e assegna all’oggetto df_ga4 il database estratto.

df_ga4 <- ga_data(
  propertyId = property_id, 
  date_range = c(from_date, to_date), 
  dimensions = ga4_dimensions, 
  metrics = ga4_metrics
)

Filtri

Per creare un filtro si usa l’argomento dim_filter con la funzione ga_data_filter(). Per esempi su definizione di filtri vedere https://rdrr.io/cran/googleAnalyticsR/man/ga_data_filter.html.

df_ga4 <- ga_data(
  propertyId = property_id, 
  date_range = c(from_date, to_date), 
  dimensions = ga4_dimensions, 
  metrics = ga4_metrics, 
  dim_filter = ga_data_filter(x)
)

map_dfr()

Nel caso in cui si volesse fare la stessa identica estrazione da più property e poi fare un append in un unico database si può usare la funzione map_dfr della libreria purrr dell’universo tidyverse.

df_accounts_ga4 <- ga_account_list(type = "ga4") %>%
    janitor::clean_names() %>%
    dplyr::select(-account_id, -property_name) 

df_ga4 <- map_dfr(df_accounts_ga4$property_id,
                    function(property){
                        df_ga4 <- ga_data(property,
                                          date_range = date_range,
                                          metrics = ga4_metrics_ss,
                                          dimensions = ga4_dimensions_ss,
                                          limit = -1) %>%
                            janitor::clean_names() %>%
                            as_tibble()
                            
                        return(df_ga4)

                    }) 

Prima creo il df contenente tutte le property da cui voglio estrarre con i rispettivi property_id, dopo assegno come argomento della funzione map_dfr il vettore delle property in modo da ciclare su ognuna di esse. In questo modo però non ho indicazione di come distinguere i dati delle property. Quindi posso aggiungere una colonna uguale al nome della property.

df_accounts_ga4 <- ga_account_list(type = "ga4") %>%
    janitor::clean_names() %>%
    dplyr::select(-account_id, -property_name) 

df_ga4 <- map_dfr(df_accounts_ga4$property_id,
                    function(property){
                        df_ga4 <- ga_data(property,
                                          date_range = date_range,
                                          metrics = ga4_metrics_ss,
                                          dimensions = ga4_dimensions_ss,
                                          limit = -1) %>%
                            janitor::clean_names() %>%
                            as_tibble() %>% 
                            mutate(account_name = df_accounts_ga4 %>%
                              filter(property_id == property) %>%
                              pull(account_name) %>%
                              first())

In questo caso creo una variabile di flag chiamata account_name che è uguale al nome della property GA4 da cui provengono i dati, utile a raggruppamenti o segmentazione dei dati.

DDP

Nel caso del DDP abbiamo una property unica per la combinazione brand-mercato. Quindi il numero di estrazioni è molto elevato, ma la struttura delle estrazioni è sempre la stessa.

set up

Definisco prima due vettori con la lista dei mercati e dei brand.

ga_auth(email = "l.bongiorno@reply.it" )
ga_account_list(type = "ga4")

# property dei brand
df_accounts_STLA <- ga_account_list(type = "ga4") %>%
    janitor::clean_names() %>%
    dplyr::select(-account_id, -property_name) %>%
    filter(str_detect(account_name, "Fiat|Jeep|Alfa|Abarth|Lancia")) %>%
    separate(col = "account_name",
             into = c("brand", "market"),
             sep = "\\|") %>%
    mutate(brand = str_trim(brand),
           market = str_trim(market)) %>%
    # le properties di LU e BE per i mercati sotto danno errore
    filter(!((market == "LU"|market == "BE") &
             (brand == "Jeep" | brand == "Lancia"))
        
# property della Splashpage     
df_accounts_PSA <- ga_account_list(type = "ga4") %>%
    janitor::clean_names() %>%
    dplyr::select(-account_id, -property_name) %>%
    filter(str_detect(account_name, "PSA")) %>%
    separate(col = "account_name",
             into = c("brand", "market"),
             sep = "\\|") %>%
    mutate(brand = str_trim(brand),
           market = str_trim(market))

Il df_accounts_STLA contiene le property dei brand, mentre il df_accounts_PSA contiene la property specifica della Splashpage (unica per tutti i brand e tutti i mercati). Entrambi i df contengono la colonna brand, la colonna market (ricavate dal nome dell’account) e la property_id.

esempio singolo mercato

Per estrarre i dati di un singolo mercato, per tutti i brand si può usare questo codice.

# Seleziono il mercato che mi interessa, definendo variabile var_market
var_market = "IT"

# creo df set up del mercato
df_account_IT <- df_accounts_STLA %>% 
    filter(market == var_market)

# estraggo dati
df_ga4_IT <- map_dfr(df_account_IT,
                    function(property){
                        df_ga4 <- ga_data(property,
                                          date_range = date_range,
                                          metrics = ga4_metrics,
                                          dimensions = ga4_dimensions,
                                          dim_filters = ga_data_filter("customEvent:site_type" == "dealer website" ),
                                          limit = -1) %>%
                            janitor::clean_names() %>%
                            as_tibble() %>% 
                        mutate(market = df_account_IT %>%
                                 filter(property_id == property) %>%
                                 pull(market) %>%
                                 first())
                            mutate(market = df_account_IT %>%
                                       filter(property_id == property) %>%
                                       pull(market) %>%
                                       first(),
                                   brand = df_account_IT %>%
                                       filter(property_id == property) %>%
                                       pull(brand) %>%
                                       first()
                            )

                        return(df_ga4)

                    }) 

Uso la funzione ga_data_filter per assicurarci di estrarre solo i dati dei DWS e non dei siti di brand.

esempio calcolo KPI per mese

Normalizzo la data, raggruppo per mese e sommo i KPI di interesse.

df_ga4_IT %>%
    mutate(dt = floor_date(date, unit = "months")) %>%
    group_by(dt) %>%
    summarise(sessions = sum(sessions),
              engaged = sum(engaged_sessions),
              bounce_rate = mean(bounce_rate),
              duration = mean(average_session_duration))

esempio calcolo site sections

Voglio avere il traffico per sezione del sito, quindi estraggo come metrica le sessions e la dimensione custom customEvent:site_typelevel2.

ga4_metrics_ss <- c("sessions")
ga4_dimensions_ss <- c("date", "customEvent:site_type", "customEvent:site_typelevel2")

Replico la stessa estrazione aggiornando dimensioni e metriche di interesse.

df_ss_IT <- map_dfr(df_account_IT$property_id,
                    function(property){
                        df_ga4 <- ga_data(property,
                                          date_range = date_range,
                                          metrics = ga4_metrics_ss,
                                          dimensions = ga4_dimensions_ss,
                                          dim_filters = ga_data_filter("customEvent:site_type" == "dealer website" ),
                                          limit = -1) %>%
                            janitor::clean_names() %>%
                            as_tibble() %>% 
                        mutate(market = df_account_IT %>%
                                 filter(property_id == property) %>%
                                 pull(market) %>%
                                 first())
                            mutate(market = df_account_IT %>%
                                       filter(property_id == property) %>%
                                       pull(market) %>%
                                       first(),
                                   brand = df_account_IT %>%
                                       filter(property_id == property) %>%
                                       pull(brand) %>%
                                       first()
                            )

                        return(df_ga4)
                    }) %>% 
        mutate(site_section = case_when(
          str_detect(custom_event_site_typelevel2, "ownership:") ~ "aftersales",
          str_detect(custom_event_site_typelevel2, "about-us|offices") ~ "about us",
          str_detect(custom_event_site_typelevel2, "showroom$") ~ "showroom_hub",
          str_detect(custom_event_site_typelevel2, "showroom:") ~ "showroom_detail",
          str_detect(custom_event_site_typelevel2, "used-inventory$") ~ "used_inventory_hub",
          str_detect(custom_event_site_typelevel2, "promotions$") ~ "promo_hub",
          str_detect(custom_event_site_typelevel2, "homepage") ~ "homepage",
          str_detect(custom_event_site_typelevel2, "promotions:") ~ "promo_detail",
          TRUE ~ "other"
        ))

Dopo calcolo la somma di sessions per site sections.

df_ss_AT %>%
    mutate(dt = floor_date(date, unit = "months")) %>%
    group_by(dt, site_section) %>%
    summarise(sessions = sum(sessions))

append

Creo una funzione per replicare l’estrazione e applicarla a mercati e report suite diverse. Come argomenti devo passargli il df della report suite, il vettore di metriche e il vettore di dimensioni.

fn_ga4_extraction <- function(df_account, ga4_metrics, ga4_dimensions){
  map_dfr(df_account,
                    function(property){
                        df_ga4 <- ga_data(property,
                                          date_range = date_range,
                                          metrics = ga4_metrics,
                                          dimensions = ga4_dimensions,
                                          dim_filters = ga_data_filter("customEvent:site_type" == "dealer website" ),
                                          limit = -1) %>%
                            janitor::clean_names() %>%
                            as_tibble() %>% 
                        mutate(market = df_account %>%
                                 filter(property_id == property) %>%
                                 pull(market) %>%
                                 first())
                            mutate(market = df_account %>%
                                       filter(property_id == property) %>%
                                       pull(market) %>%
                                       first(),
                                   brand = df_account %>%
                                       filter(property_id == property) %>%
                                       pull(brand) %>%
                                       first()
                            )

                        return(df_ga4)

                    }) 
}

Dopo eseguo la funzione per i mercati in scope.

df_ga4_IT <- fn_ga4_extraction(df_account_IT, ga4_metrics_IT, ga4_dimensions_IT) 
df_ga4_DE <- fn_ga4_extraction(df_account_DE, ga4_metrics_DE, ga4_dimensions_DE) 
df_ga4_BE <- fn_ga4_extraction(df_account_BE, ga4_metrics_BE, ga4_dimensions_BE) 
df_ga4_LU <- fn_ga4_extraction(df_account_LU, ga4_metrics_LU, ga4_dimensions_LU) 
df_ga4_AT <- fn_ga4_extraction(df_account_AT, ga4_metrics_AT, ga4_dimensions_AT) 
df_ga4_PT <- fn_ga4_extraction(df_account_PT, ga4_metrics_PT, ga4_dimensions_PT) 

A questo punto creo un unico dataframe contenente tutti i dati.

splashpage

Per i dati della splashpage devo estrarre dalla property specifica PSA, filtrando sempre il site type ed eventualmente il mercato.

ga4_dimensions_splash <- c("date", "customEvent:site_type", "customEvent:site_country")

df_splash <- ga_data(df_accounts_PSA$property_id,
                     date_range = date_range,
                     metrics = ga4_metrics,
                     dimensions = ga4_dimensions_splash,
                     limit = -1) %>%
    janitor::clean_names() %>%
    as_tibble()
    
df_splash %>%
    filter(custom_event_site_type == "dealer website",
           custom_event_site_country == "it") %>%
    mutate(dt = floor_date(date, unit = "months")) %>%
    group_by(dt) %>%
    summarise(sessions = sum(sessions),
              engaged = sum(engaged_sessions),
              bounce_rate = mean(bounce_rate))

In questo modo estraggo i KPI relativi al traffico, raggruppo per mese e sommo.

df_splash_events <- ga_data(df_accounts_PSA$property_id,
                            date_range = date_range,
                            metrics = "eventCount",
                            dimensions = c("date", 
                                           "customEvent:site_country", 
                                           "customEvent:asset_owner", 
                                           "eventName"),
                            limit = -1) %>%
    janitor::clean_names() %>%
    as_tibble()
    
df_splash_events %>%
    filter(custom_event_asset_owner == "dealer",
           custom_event_site_country == "it",
           str_detect(event_name, "form")) %>%
    mutate(dt = floor_date(date, unit = "months")) %>%
    group_by(dt) %>%
    summarise(count = sum(event_count))

In questo modo estraggo il conteggio di eventi, raggruppo per mese e sommo. Filtro il nome dell’evento di interesse dalla dimensione event_name.

Salvo dati estratti in Excel

Mi assicuro di aver definito la working directory in cui vado a salvare il file Excel con i dati estratti.

install.packages("openxlsx")
library("openxlsx")

# Crea un nuovo libro di lavoro
wb <- createWorkbook()
# Aggiunge un foglio di lavoro al libro
addWorksheet(wb, "nome_del_foglio_excel")
# Scrive i dati nei fogli di lavoro
writeData(wb, "nome_del_foglio_excel", df_ga4)
# Salva il libro di lavoro
saveWorkbook(wb, "nome_del_file_excel.xlsx")

Codice DDP PRONTO DA USARE

# Librerie utili
library("tidyverse") 
library("lubridate") 
library("scales")    
library("janitor")   
library("here")      
library("ggrepel")
library("readxl")
library("tidytext")

# Libreria specifica per GA4
library("googleAnalyticsR")

# Working directory
setwd(here::here())

# Authentication
ga_auth(email = "l.bongiorno@reply.it" )

# property dei brand
df_accounts_STLA <- ga_account_list(type = "ga4") %>%
    janitor::clean_names() %>%
    dplyr::select(-account_id, -property_name) %>%
    filter(str_detect(account_name, "Fiat|Jeep|Alfa|Abarth|Lancia")) %>%
    separate(col = "account_name",
             into = c("brand", "market"),
             sep = "\\|") %>%
    mutate(brand = str_trim(brand),
           market = str_trim(market)) %>%
    # le properties di LU e BE per i mercati sotto danno errore
    filter(!((market == "LU"|market == "BE") &
             (brand == "Jeep" | brand == "Lancia"))
        
# property della Splashpage     
df_accounts_PSA <- ga_account_list(type = "ga4") %>%
    janitor::clean_names() %>%
    dplyr::select(-account_id, -property_name) %>%
    filter(str_detect(account_name, "PSA")) %>%
    separate(col = "account_name",
             into = c("brand", "market"),
             sep = "\\|") %>%
    mutate(brand = str_trim(brand),
           market = str_trim(market))

# creo df set up del mercato
df_account_IT <- df_accounts_STLA %>% filter(market == "IT")
df_account_DE <- df_accounts_STLA %>% filter(market == "DE")
df_account_BE <- df_accounts_STLA %>% filter(market == "BE")
df_account_LU <- df_accounts_STLA %>% filter(market == "LU")
df_account_AT <- df_accounts_STLA %>% filter(market == "AT")
df_account_PT <- df_accounts_STLA %>% filter(market == "PT")

# funzione estrazione
fn_ga4_extraction <- function(df_account, ga4_metrics, ga4_dimensions){
  map_dfr(df_account,
                    function(property){
                        df_ga4 <- ga_data(property,
                                          date_range = date_range,
                                          metrics = ga4_metrics,
                                          dimensions = ga4_dimensions,
                                          dim_filters = ga_data_filter("customEvent:site_type" == "dealer website" ),
                                          limit = -1) %>%
                            janitor::clean_names() %>%
                            as_tibble() %>% 
                        mutate(market = df_account %>%
                                 filter(property_id == property) %>%
                                 pull(market) %>%
                                 first())
                            mutate(market = df_account %>%
                                       filter(property_id == property) %>%
                                       pull(market) %>%
                                       first(),
                                   brand = df_account %>%
                                       filter(property_id == property) %>%
                                       pull(brand) %>%
                                       first()
                            )

                        return(df_ga4)

                    }) 
}

date_range <- c("2024-10-31", "2025-02-28")
ga4_metrics <- "sessions"
ga4_dimensions <- c("date", "month")

df_ga4_IT <- fn_ga4_extraction(df_account_IT, ga4_metrics, ga4_dimensions) 
df_ga4_DE <- fn_ga4_extraction(df_account_DE, ga4_metrics, ga4_dimensions) 
df_ga4_BE <- fn_ga4_extraction(df_account_BE, ga4_metrics, ga4_dimensions) 
df_ga4_LU <- fn_ga4_extraction(df_account_LU, ga4_metrics, ga4_dimensions) 
df_ga4_AT <- fn_ga4_extraction(df_account_AT, ga4_metrics, ga4_dimensions) 
df_ga4_PT <- fn_ga4_extraction(df_account_PT, ga4_metrics, ga4_dimensions) 

df_ga4_finale <- rbind(df_ga4_IT, df_ga4_DE, df_ga4_BE, df_ga4_LU, df_ga4_AT, df_ga4_PT)

wb <- createWorkbook()
addWorksheet(wb, "GA4 data")
writeData(wb, "GA4 data", df_ga4_finale)
saveWorkbook(wb, "GA4_DATA_BRAND.xlsx")

Poi estraggo i dati della Splashpage.

ga4_dimensions_splash <- c("date", "customEvent:site_country"))

df_splash <- ga_data(df_accounts_PSA$property_id,
                     date_range = date_range,
                     metrics = ga4_metrics,
                     dimensions = ga4_dimensions_splash,
                     dim_filters = ga_data_filter("customEvent:site_type" == "dealer website" ),
                     limit = -1) %>%
    janitor::clean_names() %>%
    as_tibble()
    
wb2 <- createWorkbook()
addWorksheet(wb2, "GA4 data Splash")
writeData(wb2, "GA4 data Splash", df_splash)
saveWorkbook(wb2, "GA4_DATA_SPLASH.xlsx")