@codenerd på twitter Mit seneste tweet:

Google Analytics API med PHP – Del 3: Avancerede dataudtræk

Dette er 3. del af min blogserie om Google Analytics API, og jeg anbefaler du læser Del 1 og Del 2, før vi går i gang med denne. I dag ser vi på hvordan vi kan hive data ud fra mere end en dimension og en metric, hvordan vi kan sortere og filtrere dataudtræk samt selvfølgelig hvordan vi omdanner disse udtræk til arrays.

Dataudtræk på på flere “dimensions” – Besøg pr dag opdelt efter kilde

I Del 2“dimensions” eller “metrics” adskildes disse blot af , (komma). Derfor skal vi forespørge denne url:

https://www.google.com/analytics/feeds/data?ids=ga:5311824&dimensions=ga:date,ga:medium&metrics=ga:visits&start-date=2009-04-01&end-date=2009-04-07

Denne url (husk at udskifte id til dit eget profil id) sender vi igen igennem vores hent_data funktion som nu vil returnere et xml feed med følgende struktur (uddrag):

PHP
1
2
3
4
5
6
7
8
9
<entry>
    <id>http://www.google.com/analytics/feeds/data?ids=ga:5311824&ga:date=20090401&ga:medium=(none)&start-date=2009-04-01&end-date=2009-04-07</id>
    <updated>2009-04-06T17:00:00.001-07:00</updated>
    <title type='text'>ga:date=20090401 | ga:medium=(none)</title>
    <link rel='alternate' type='text/html' href='http://www.google.com/analytics'/>
    <dxp:dimension name='ga:date' value='20090401'/>
    <dxp:dimension name='ga:medium' value='(none)'/>
    <dxp:metric confidenceInterval='0.0' name='ga:visits' type='integer' value='3'/>
</entry>

Den eneste forskel der er her er at vi kan se vi har to dimensions, vi vil derfor lave et multidimensionelt array som opbygges sådan her:

PHP
1
2
3
4
5
6
7
8
9
Array
(
[dato] => Array
(
[kilde] => antal
[kilde] => antal
[kilde] => antal
)
)

For at få denne struktur bruger vi igen SimpleXML:

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
//forsøg at logge ind, giv fejl hvis ikke
if (login()) {
    //vi er nu logget ind
    echo 'logget ind';
    $xml = hent_data('https://www.google.com/analytics/feeds/data?ids=ga:5311824&dimensions=ga:date,ga:medium&metrics=ga:visits&start-date=2009-04-01&end-date=2009-04-07'); //hent data fra google
    if ($xml) { //er xml loadet?
        $xml = str_replace('dxp:','',$xml); //simple xml håndtere namespaces på en lidt besværlig måde, så for nemhedens skyld fjerner vi bare dxp: fra noder i xml dokumentet
        $xml = new SimpleXMLElement($xml); //start simple xml og load vores xml ind
        $data = array(); //array vi vil gemme vores data i
        foreach ($xml->entry as $entry) { //gennemløb entry da det er her vores dage er gemt
            $dag=date('Y-m-d',strtotime($entry->dimension[0]->attributes()->value)); //hent dato som er vores dimension - denne er ikke formateret så det må vi selv klare med date og strtotime
            $antal=(integer)$entry->metric->attributes()->value; //hent antal besøg for dagen - vi er nødt til at angive datatypen her da vi ellers vil gemme et simple xml objekt
            $kilde = (string)$entry->dimension[1]->attributes()->value; //hent dimension 2 - dvs kilden for vores besøg
            $data[$dag][$kilde]=$antal; //tilføj til vores data array
        }
    }
} else {
    //ikke logget ind
    echo 'Der opstod en fejl i login';    
}
?>

Da vi har brugt 2 dimensioner er der nu to noder der hedder “dimension”. Disse to kan vi i SimpleXML tilgå som et array, dvs første dimension er [0] (dato) og anden dimension er [1] (kilde) – udover disse ændringer er koden den samme som på dag 2.

Kilder

APIen bruger følgende navne på kilder:

  • (none) = direkte besøg
  • organic = Organisk trafik (ikke betalt trafik fra søgemaskinerne)
  • cpc = Betalt trafik (adwords)
  • referral = Henvisninger

Dataudtræk på flere “metrics” – Bouncerate

Der er ingen metric der hedder bouncerate i Google Analytics API, men det er ganske nemt at regne denne ud, da vi kan forespørge på flere metrics. Bouncerate udregnes ved følgende formel: (antal afvisninger/antal indkomne visninger)*100. I API sprog bliver dette til (ga:bounces/ga:entrances)*100 – For at kunne lave denne udregning sender vi følgende url til hent_data():

https://www.google.com/analytics/feeds/data?ids=ga:5311824&dimensions=ga:date&metrics=ga:bounces,ga:entrances&start-date=2009-04-01&end-date=2009-04-07

Vores data udtræk ser nu sådan her ud:

PHP
1
2
3
4
5
6
7
8
9
10
<entry>
    <id>http://www.google.com/analytics/feeds/data?ids=ga:5311824&ga:date=20090401&ga:medium=(none)&start-date=2009-04-01&end-date=2009-04-07</id>
    <updated>2009-04-06T17:00:00.001-07:00</updated>
    <title type='text'>ga:date=20090401 | ga:medium=(none)</title>
    <link rel='alternate' type='text/html' href='http://www.google.com/analytics'/>
    <dxp:dimension name='ga:date' value='20090401'/>
    <dxp:dimension name='ga:medium' value='(none)'/>
    <dxp:metric confidenceInterval='0.0' name='ga:bounces' type='integer' value='27'/>
    <dxp:metric confidenceInterval='0.0' name='ga:entrances' type='integer' value='73'/>
</entry>

Som ved flere “dimensions”, ser vi nu, at der er to metrics noder i hvert disse kan vi igen hive ud som et array, udregne bouncerate og gemme i vores data array:

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
//forsøg at logge ind, giv fejl hvis ikke
if (login()) {
    //vi er nu logget ind
    echo 'logget ind';
    $xml = hent_data('https://www.google.com/analytics/feeds/data?ids=ga:5311824&dimensions=ga:date&metrics=ga:bounces,ga:entrances&start-date=2009-04-01&end-date=2009-04-07'); //hent data fra google
    if ($xml) { //er xml loadet?
        $xml = str_replace('dxp:','',$xml); //simple xml håndtere namespaces på en lidt besværlig måde, så for nemhedens skyld fjerner vi bare dxp: fra noder i xml dokumentet
        $xml = new SimpleXMLElement($xml); //start simple xml og load vores xml ind
        $data = array(); //array vi vil gemme vores data i
        foreach ($xml->entry as $entry) { //gennemløb entry da det er her vores dage er gemt
            $dag=date('Y-m-d',strtotime($entry->dimension->attributes()->value)); //hent dato som er vores dimension - denne er ikke formateret så det må vi selv klare med date og strtotime
            $bounces=(integer)$entry->metric[0]->attributes()->value; //hent antal bounces - metric 1
            $entrances = (string)$entry->metric[1]->attributes()->value; //hent antal entrances metric 2
            $bouncerate = ($bounces/$entrances)*100; //udregn bouncerate
            $data[$dag]=$bouncerate; //tilføj til vores data array
        }
    }
} else {
    //ikke logget ind
    echo 'Der opstod en fejl i login';    
}
?>

Flere “metrics” samt flere “dimensions” – Bouncerate opdelt på dag og kilde

Det er selvfølgelig også muligt at kombinere flere dimensions og flere metrics. Vi kan fx sagtens opdele bouncerate på kilde dvs, hvor høj er vores bouncerate på dem der kommer fra organisk trafik/cpc/henvisninger/direkte trafik, på en given dag eller periode. Her bruger vi ga:date,ga:medium som “dimensions” og ga:bounces,ga:entrances som metrics:

https://www.google.com/analytics/feeds/data?ids=ga:5311824&dimensions=ga:date,ga:medium&metrics=ga:bounces,ga:entrances&start-date=2009-04-01&end-date=2009-04-07

Igen sender vi urlen igennem hent_data() og behandler retursvar vha. SimpleXML. Strukturen er den samme som før, bort set fra der er kommet en ekstra dimension, derfor behandler vi næsten også data på samme måde som før:

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
//forsøg at logge ind, giv fejl hvis ikke
if (login()) {
    //vi er nu logget ind
    echo 'logget ind';
    $xml = hent_data('https://www.google.com/analytics/feeds/data?ids=ga:5311824&dimensions=ga:date,ga:medium&metrics=ga:bounces,ga:entrances&start-date=2009-04-01&end-date=2009-04-07'); //hent data fra google
    if ($xml) { //er xml loadet?
        $xml = str_replace('dxp:','',$xml); //simple xml håndtere namespaces på en lidt besværlig måde, så for nemhedens skyld fjerner vi bare dxp: fra noder i xml dokumentet
        $xml = new SimpleXMLElement($xml); //start simple xml og load vores xml ind
        $data = array(); //array vi vil gemme vores data i
        foreach ($xml->entry as $entry) { //gennemløb entry da det er her vores dage er gemt
            $dag=date('Y-m-d',strtotime($entry->dimension->attributes()->value)); //hent dato som er vores dimension - denne er ikke formateret så det må vi selv klare med date og strtotime
            $kilde = (string)$entry->dimension[1]->attributes()->value; //hent dimension 2 - dvs kilden for vores besøg        
            $bounces=(integer)$entry->metric[0]->attributes()->value; //hent antal bounces - metric 1
            $entrances = (string)$entry->metric[1]->attributes()->value; //hent antal entrances metric 2
            $bouncerate = ($bounces/$entrances)*100; //udregn bouncerate
            $data[$dag][$kilde]=$bouncerate; //tilføj til vores data array
        }
    }
} else {
    //ikke logget ind
    echo 'Der opstod en fejl i login';    
}
?>

Sortering og filtrer

Efter som vi gemmer vores data i et array, ville det være nemt at sortere i PHP, men vi kan også bede APIen om at gøre det for os ved at bruge sort parametren. Ligeledes kan vi inkludere eller ekskludere bestemte data ved at bruge filter. Hvis vi tager udgangspunkt i vores data kald fra Del 2 kan vi fx nemt sortere dagene, efter hvilken dag der har flest besøgende:

https://www.google.com/analytics/feeds/data?ids=ga:5311824&dimensions=ga:date&metrics=ga:visits&start-date=2009-04-01&end-date=2009-04-07&sort=-ga:visits

Vi sorterer her vores resultater efter ga:visits (ga:visits) og med foranstillet – (minus) fortæller vi google, at vi vil sortere i faldende orden. Stigende orden er standard og kræver derfor ikke noget fortegn. Du kan sortere efter alle metrics og dimensions.

Filtrer

Filtrering af data er en anelse mere kompliceret end sortering. Filtrering betyder at vi fortæller Google Analytics API, at vi kun ønsker data som opfylder bestemte krav. Hvis vi kun ville udtrække dage, hvor der var flere besøg end 50, kan vi gøre det sådan her: ga:visits>=50 – operatorene i filtrer skal i visse tilfælde urlencodes, så ga:visits>=50 bliver til: ga:visits%3E%3D50 – den fulde url er nu:

https://www.google.com/analytics/feeds/data?ids=ga:5311824&dimensions=ga:date&metrics=ga:visits&start-date=2009-04-01&end-date=2009-04-07&filters=ga:visits%3E%3D50

Sender vi urlen igennem vores funktion fra dag 2 får vi følgende array:

PHP
1
2
3
4
5
6
7
Array
(
[2009-04-01] => 71
[2009-04-02] => 76
[2009-04-04] => 79
[2009-04-05] => 70
)

Der er i alt 12 operatorer (6 metrics 6 dimensions) (direkte fra Googles dokumentation):

Metric Filters
Operator Beskrivelse Encoded
== Svarer til %3D%3D
!= Svarer ikke til !%3D
> Større end %3E
< Mindre end %3C
>= Større eller svarer til %3E%3D
<= Mindre eller svarer til %3C%3D
Dimension Filters
Operator Beskrivelse Encoded
== Svarer til %3D%3D
!= Svarer ikke til !%3D
=~ Regular expression indeholder %3D~
!~ Regular expresion indeholder ikke ingen
=@ Indeholder ord %3D@
!@ Indeholder ikke ord ingen

Vi kan selvfølgelig også kombinere sortering og filtrer uden problemer.

Fejlfinding og leg

Som med alt andet handler det om at lege lidt med APIen og prøve at hive forskellige datarapporter ud. Dette vil unægteligt resulterer i nogle fejl, og tvivl om hvordan data hives ud via SimpleXML. Som standard er det XML vi får ud fra APIen helt uden mellemrum, hvilket kan gøre det meget uoverskueligt hvis vi udskriver vores $xml variabel til skærmen. Dette kan dog ændres, simpelthen ved at tilføje &prettyprint=true til vores data url kald. Hvis denne parameter tilføjes får vi udskrevet XMLen opstillet pænt. (Nb. udskriv $xml før du kalder simplexml). Det er en rigtig god ide at fjerne prettyprint igen, da formateringen betyder ekstra data der skal sendes fra APIen.

Hvis du er i tvivl om hvordan du får fat på et element i SimpleXML kan du lave en var_dump($entry) i foreach løkken. Her vil du så få hele strukturen at se.

Og så er det bare at angive stien til noden.

Afslutning

Nu har vi fulgt hinanden nogle dage og dette er i første omgang den sidste planlagte del af serien. Dette betyder dog ikke at det er slut for dig, vi har kun lige rodet i overfladen af Google Analytics API, og nu handler det bare om at være nysgerrig og komme i gang med at grave dybere. Jeg kan næsten garantere at der kommer mere fra mig om APIen men hvornår det lige bliver ved jeg ikke

Endnu engang kan du hente min kildekode til dag 3

Håber du har fået noget ud af at følge denne blog serie – og som altid så er du velkommen til at skrive spørgsmål og kommentarer, og skal da heller ikke udelukke at specifikke spørgsmål omkring APIen kan resultere i endnu et blogindlæg i serien.

2 kommentarer

  1. Jeg simpelthen elsker dette Martin… Mange tak for din 3 trins raket. Denne guide vil absolut blive brugt og fulgt nøje når jeg vil lave min egne udtræk via deres API.

    Det må have været svært at få det hele beskrevet så godt, men tror vi er rigtig mange der er utrolig glade for du har taget dig denne tid.

    Og at vi får alle koderne er simpelthen bare perfekt. Ikke noget med at genopfinde den dybe tallerken.
    Tak tak og atter tak Martin!

    Svar på kommentaren
  2. Velbekommen. Det har jo stået stille så længe her, så tænkte jeg ville lægge hårdt ud med Analytics API – indrømmer gerne at disse 3 indlæg har trukket tænder ud – brugte det meste af min søndag på eksempler og omskrivninger.

    Det sværeste har faktisk næsten været at vidde hvor man skulle stoppe. Jeg er selv dybt fascineret af APIen og kunne vrøvle videre i alt evighed (og gjorde det flere steder) men håber på jeg har ramt et niveau hvor alle får noget ud af indlæggene.

    Svar på kommentaren

Leave a Reply to Martin Nielsen Cancel reply

Krævede felter er markeret med *.

*