Nick Mihailovski, Team API di Google Analytics – Ottobre 2009
Questo articolo illustra come rilevare e eseguire il backfill dei valori delle serie temporali mancanti nei dati restituiti dall' API di esportazione dei dati di Google Analytics.
Prima di iniziare
L'articolo presuppone che tu sappia come funziona l'API di esportazione dei dati di Google Analytics. Il codice campione è in Java, ma puoi utilizzare i concetti nel linguaggio che preferisci. Il codice di questo articolo è fornito in formato open source e può essere scaricato dall'hosting del progetto.
Dopo aver letto questo articolo, imparerai a:
- Il trattamento delle dimensioni di data da parte dell'API Data Export di Google Analytics.
- Come strutturare le query in modo da raggruppare i risultati e rilevare le date mancanti.
- Come inserire i valori mancanti utilizzando Java.
Introduzione
Il confronto dei dati in un periodo di tempo fornisce un contesto.
Ad esempio, affermare che un sito web ha generato entrate da 1 milione di dollari
non significa molto. Tuttavia, dichiarare che le entrate di un sito web sono aumentate di 10 volte su base trimestrale o su base annua è davvero impressionante. Con l'API Google
Analytics, è facile tracciare i dati nel tempo utilizzando le
dimensioni ga:date
, ga:day
e ga:month
.
Se la query utilizza solo una dimensione di data, se qualche giorno dell'intervallo di date non ha raccolto dati, l'API Google Analytics eseguirà il backfill delle date e dei valori 0
per le metriche.
ga:date | ga:sessions |
---|---|
2010-03-01 | 101 |
2010-03-02 | 0 |
2010-03-03 | 69 |
Tuttavia, diventa difficile se esegui query sulla data insieme ad altre dimensioni. Se una delle date non contiene dati, l'API NON restituirà una voce per quella data. Passerà semplicemente alla data successiva disponibile contenente i dati.
ga:keyword | ga:date | ga:sessions |
---|---|---|
sedia | 2010-03-01 | 55 |
sedia | 2010-03-03 | 48 |
Idealmente, gli analisti vorrebbero che le date mancanti di una determinata parola chiave vengano compilate come nel primo esempio sopra
Questo articolo descrive alcune best practice per il backfill pragmatico dei dati.
Contesto
Vediamo innanzitutto perché esiste questo problema. I motivi sono due.
- Google Analytics elabora solo i dati raccolti. Se nessuno ha visitato un sito in un determinato giorno, non ci sono dati da elaborare e non vengono restituiti.
- È molto difficile determinare quante dimensioni aggiuntive e quali valori devono essere utilizzati per le date senza dati.
Quindi, invece di cercare di definire un processo per regolarle tutte, l'API Google Analytics lascia l'esercizio di inserire i dati per le query che hanno più dimensioni fino allo sviluppatore. Che fortunata :)
Panoramica del programma
Ecco i passaggi per eseguire il backfill dei dati nel grafico riportato sopra.
- Modifica la query per assicurarti che le dimensioni siano ordinate in modo opportuno.
- Determinare le date previste a partire dall'intervallo di date.
- Ripeti l'iterazione ed esegui il backfill delle date mancanti.
- Inserisci i valori mancanti rimanenti.
Modifica la query
Per eseguire il backfill delle date, dobbiamo assicurarci che i dati restituiti dall'API siano in un formato che consenta di rilevare facilmente quando manca una data.
Ecco una query di esempio per recuperare sia ga:keyword
sia ga:date
per i primi 5 giorni di marzo:
DataQuery dataQuery = new DataQuery(new URL(BASE_URL)); dataQuery.setIds(TABLE_ID); dataQuery.setStartDate("2010-03-01"); dataQuery.setEndDate("2010-03-05"); dataQuery.setDimensions("ga:keyword,ga:date"); dataQuery.setMetrics("ga:entrances");
Una volta inviata la query all'API, i risultati conterranno un elenco di oggetti DataEntry
. Ogni oggetto voce rappresenta una riga di dati e include nomi e valori di dimensioni/metriche. Poiché non è stato utilizzato alcun parametro di ordinamento, i risultati vengono restituiti in ordine arbitrario.
ga:keyword | ga:date | ga:entrances |
---|---|---|
sedia | 2010-03-04 | 14 |
sedia | 2010-03-01 | 23 |
tavolo | 2010-03-04 | 18 |
tavolo | 2010-03-02 | 24 |
sedia | 2010-03-03 | 13 |
Per identificare facilmente le date mancanti, dobbiamo prima raggruppare tutte le dimensioni. A questo scopo, imposta il parametro di ordinamento della query sulle dimensioni utilizzate nella query originale.
dataQuery.setSort("ga:keyword,ga:date");
Se aggiungi il parametro di ordinamento, l'API restituirà i risultati nell'ordine desiderato.
ga:keyword | ga:date | ga:entrances |
---|---|---|
sedia | 2010-03-01 | 23 |
sedia | 2010-03-03 | 13 |
sedia | 2010-03-04 | 14 |
tavolo | 2010-03-02 | 24 |
tavolo | 2010-03-04 | 18 |
Il secondo passaggio consiste nell'assicurarti che, per ogni dimensione, tutte le date vengano restituite
in ordine crescente. Sebbene l'API Google Analytics fornisca una serie di dimensioni
relative alla data, solo ga:date
può essere ordinato con precisione oltre i limiti
di date (ad esempio giorni, mesi, anni). Pertanto, se vuoi eseguire il backfill delle date, assicurati che la query utilizzi la dimensione ga:date
sia nelle dimensioni sia nei parametri di query di ordinamento.
Dopo l'esecuzione della query ordinata, tutte le stesse pagine di destinazione verranno restituite una accanto all'altra e le date saranno in ordine sequenziale. L'elenco di date di una singola pagina di destinazione può essere considerato come una serie temporale e, poiché sono in ordine, è molto più facile identificare le date mancanti.
Determinare le date previste
Per rilevare date mancanti, dobbiamo confrontare le date effettive restituite dall'API con le date previste in ogni serie temporale. Per capire cosa ci si aspetta:
- Determinare la data di inizio prevista dalla query API.
- Conteggio del numero di giorni previsti nell'intervallo di date della query.
Entrambi i valori possono essere utilizzati insieme per determinare ogni data prevista incrementando la data di inizio di 1 per ogni giorno nell'intervallo di date.
Determinazione della data di inizio prevista
Possiamo utilizzare il parametro di query start-date
come data di inizio prevista della serie. Poiché il formato della data restituito nella risposta dell'API yyyyMMdd
è diverso da quello del parametro di query yyyy-MM-dd
,
dobbiamo convertire il formato della data per poterlo utilizzare.
Il metodo setExpectedStartDate
converte i formati delle date.
private static SimpleDateFormat queryDateFormat = new SimpleDateFormat("yyyy-MM-dd"); private static SimpleDateFormat resultDateFormat = new SimpleDateFormat("yyyyMMdd"); public void setExpectedStartDate(String startDate) { try { calendar.setTime(queryDateFormat.parse(startDate)); expectedStartDate = resultDateFormat.format(calendar.getTime()); } catch (ParseException e) { handleException(e); } }
Conteggio del numero di giorni previsti
Per ottenere il numero di giorni nell'intervallo di date, il programma analizza le date di inizio e di fine negli oggetti Java Date
. Quindi utilizza un oggetto Calendar
per calcolare il tempo tra entrambe le date. Viene aggiunto un giorno alla differenza tra le date per includere il conteggio.
private static final long millisInDay = 24 * 60 * 60 * 1000; public void setNumberOfDays(DataQuery dataQuery) { long startDay = 0; long endDay = 0; try { calendar.setTime(queryDateFormat.parse(dataQuery.getStartDate())); startDay = calendar.getTimeInMillis() / millisInDay; calendar.setTime(queryDateFormat.parse(dataQuery.getEndDate())); endDay = calendar.getTimeInMillis() / millisInDay; } catch (ParseException e) { handleException(e); } numberOfDays = (int) (endDay - startDay + 1); }
Ora abbiamo tutti i dati necessari per capire quali date mancano.
Identificare ogni serie temporale nei risultati
Una volta eseguita la query, il programma passa attraverso ogni oggetto DataEntry
nella risposta dell'API. Poiché la query è stata inizialmente ordinata, la risposta avrà una serie temporale parziale per ogni parola chiave. Dobbiamo quindi trovare l'inizio di ogni serie temporale, esaminare ogni data e inserire i dati mancanti non restituiti dall'API.
Questo programma utilizza le variabili dimensionValue
e tmpDimensionValue
per rilevare l'inizio di ogni serie.
Ecco l'intero codice per gestire la risposta. L'inserimento dei dati mancanti è discusso di seguito.
public void printBackfilledResults(DataFeed dataFeed) { String expectedDate = ""; String dimensionValue = ""; List<Integer> row = null; for (DataEntry entry : dataFeed.getEntries()) { String tmpDimValue = entry.getDimensions().get(0).getValue(); // Detect beginning of a series. if (!tmpDimValue.equals(dimensionValue)) { if (row != null) { forwardFillRow(row); printRow(dimensionValue, row); } // Create a new row. row = new ArrayList<Integer>(numberOfDays); dimensionValue = tmpDimValue; expectedDate = expectedStartDate; } // Backfill row. String foundDate = entry.getDimension("ga:date").getValue(); if (!foundDate.equals(expectedDate)) { backFillRow(expectedDate, foundDate, row); } // Handle the data. Metric metric = entry.getMetrics().get(0); row.add(new Integer(metric.getValue())); expectedDate = getNextDate(foundDate); } // Handle the last row. if (row != null) { forwardFillRow(row); printRow(dimensionValue, row); } }
Backfill eventuali date mancanti
Per ogni voce di una serie, il programma memorizza i valori delle metriche (entrate) in un
ArrayList
denominato row
. Quando viene rilevata una nuova serie temporale, viene creata una nuova riga e
la data prevista viene impostata sulla data di inizio prevista.
Quindi, per ogni voce, il programma controlla se il valore della data nella voce corrisponde alla data prevista. Se sono uguali, la metrica nella voce viene aggiunta alla riga. In caso contrario, il programma ha rilevato date mancanti che devono essere sottoposte a backfill.
Il metodo backfillRow
gestisce il backfill dei dati. Accetta come parametri le date previste e trovate, nonché la riga corrente.
Quindi, determina il numero di giorni tra le due date (non incluse) e aggiunge molti 0 alla riga.
public void backFillRow(String startDate, String endDate, List<Integer> row) { long d1 = 0; long d2 = 0; try { calendar.setTime(resultDateFormat.parse(startDate)); d1 = calendar.getTimeInMillis() / millisInDay; calendar.setTime(resultDateFormat.parse(endDate)); d2 = calendar.getTimeInMillis() / millisInDay; } catch (ParseException e) { handleException(e); } long differenceInDays = d2 - d1; if (differenceInDays > 0) { for (int i = 0; i < differenceInDays; i++) { row.add(0); } } }
Al termine del metodo, è stato eseguito il backfill della riga con i dati ed è possibile aggiungere i dati attuali. La data prevista viene quindi incrementata a un giorno dopo la data rilevata utilizzando il metodo getNextDate
.
public String getNextDate(String initialDate) { try { calendar.setTime(resultDateFormat.parse(initialDate)); calendar.add(Calendar.DATE, 1); return resultDateFormat.format(calendar.getTime()); } catch (ParseException e) { handleException(e); } return ""; }
Inserisci i valori rimanenti
Dopo che i dati della serie sono stati elaborati in un row
,
dobbiamo verificare che alla fine della serie non manchino altre date.
Il metodo forwardFillRow
calcola semplicemente la differenza tra il
numero di giorni nella query originale e la dimensione corrente della riga, aggiungendo
molti 0 alla fine della riga.
public void forwardFillRow(List<Integer> row) { int remainingElements = numberOfDays - row.size(); if (remainingElements > 0) { for (int i = 0; i < remainingElements; i++) { row.add(0); } } }
A questo punto, il programma ha compilato gli eventuali valori mancanti nelle serie temporali. Ora che tutti i dati sono disponibili, il programma stampa i valori delle dimensioni e delle metriche come elenco separato da virgole.
Conclusione
Con questo esempio, puoi eseguire facilmente il backfill dei dati per date non restituite dall'API. Come accennato in precedenza, questa soluzione può essere adattata a qualsiasi linguaggio di programmazione. Gli sviluppatori possono anche adattare queste tecniche e applicarle per gestire più dimensioni e metriche. Ora è ancora più facile iniziare a eseguire analisi avanzate sulle serie temporali restituite dall'API Google Analytics.