Send file download event from server to Google Analytics [duplicate]

ぃ、小莉子 提交于 2019-12-04 11:03:15

Google analytics actually has a protocol for sending analytics data from arbitrary sources. See here: https://developers.google.com/analytics/devguides/collection/protocol/v1/

So having your webserver send an analytics event to Google is not as hacky as it might seem. I'm not sure if you can hook into Apache directly to generate these events. However, I do see at least two solutions.

1) Redirect all downloads to a server side script which sends the data and can generate the desired analytics event.
2) Parse the servers logs and generate analytics events from that.

EDIT Example for solution 1:
Do make sure there are no spaces before or after the tags because this would would be part of the actual response sent to the client.

download.php:

<?php
    // Read ?file=xxx URL parameter
    $requestedFile = $_GET["file"];

    // Read Google Analytics cookie
    $rawCookie = $_COOKIE["_ga"];
    $splitCookie = explode('.', $rawCookie);
    $trackingId = $splitCookie[2] . '.' . $splitCookie[3];

    // Create Google Analytics request data (see here https://developers.google.com/analytics/devguides/collection/protocol/v1/devguide)
    $data = array('v' => 1, 
                  'tid' => 'UA-XXXXX-Y', 
                  'cid' => $trackingId, 
                  't' => 'event', 
                  'ec' => 'download', 
                  'ea' => 'download', 
                  'el' => $requestedFile);

    // Create the request options
    $options = array(
        'http' => array(
            'method' => 'POST',
            'content' => http_build_query($data)
        )
    );

    $context = stream_context_create($options);

    // Send GA request
    $result = file_get_contents('https://www.google-analytics.com/collect', false, $context);

    // GA request failed
    if($result === FALSE) { /* Error */ }

    // Requested file does not exist
    if(!file_exists($requestedFile)) { /* Error */ }

    // Set response headers for binary data
    header('Content-Type: application/octet-stream');
    header('Content-Length: ' . filesize($requestedFile));

    // Open the requested file
    $fileHandle = fopen($requestedFile, 'r');

    // Write the requested file to stdout (which is what the client receives)
    print fread($fileHandle, filesize($requestedFile));
    flush();

    // Close the requested file again
    fclose($fileHandle);

    exit;
?>

.htaccess/mod_rewrite rules:

RewriteEngine on
RewriteUrl ^/download/(.*)$ download.php?file=$1 [L]

Not it's been ages since I wrote my last PHP code and I didn't test this. But it should give a pretty good gist on how to implement option 1)

EDIT 2: If you send your tracking request to www.google-analytics.com/debug/collect you will receive some validation information telling you whether your request is valid or not (it will not track the event, though).

EDIT 3: Okay, so I've checked with a page which uses analytics.js. The script sets the following cookies:

_ga=GA1.3.1788966449.1501761573
_gid=GA1.3.1010429060.1501761573

Later on in the collect requests it sets

cid:1788966449.1501761573
_gid:1010429060.1501761573

So it seems like you need to do a little string splitting with what you find in the _ga cookie. (I've updated the code above)

EDIT 4: In case anyone's wondering, this is the request the analytics.js script generates with the cookie values mentioned above.

GET https://www.google-analytics.com/collect?v=1&_v=j56&a=1178408574&t=pageview&_s=1&dl=https%3A%2F%2Fdevelopers.google.com%2Fanalytics%2Fdevguides%2Fcollection%2Fanalyticsjs%2Fcommand-queue-reference&ul=de&de=UTF-8&dt=The%20ga%20Command%20Queue%20Reference%20%C2%A0%7C%C2%A0%20Analytics%20for%20Web%20(analytics.js)%20%C2%A0%7C%C2%A0%20Google%20Developers&sd=24-bit&sr=1920x1200&vp=1899x1072&je=0&_u=QDCAAAIhI~&jid=&gjid=&cid=1788966449.1501761573&tid=UA-41425441-2&_gid=1010429060.1501761573&z=1116872044
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!