Send file download event from server to Google Ana

2020-07-18 06:41发布

问题:

A download link is sent to a customer via email:

Hello,
Please find your product here: https://www.example.com/files/yourfile.zip

I'd like to track this download in Google Analytics, as a Goal conversion.

Unfortunately, when the user clicks on the link, the file is directly delivered by the web server, without going trough a .html page.

How to track such a direct file download inside Analytics?

  1. Should I add a dummy HTML page "in the middle", that would use the analytics.js tracking snippet and send a download event to GA with ga.send(...), and then redirect to the actual file after 500 milliseconds with setTimeout(redirect, 500)? Is it really a clean and safe solution? I see many little potential issues: is 500 ms ok? what kind of redirection should be used? Also a user with JS disabled will never get his file... or if using <noscript> no Goal conversion can be recorded.

  2. Is there a way to ask Apache (who serves the yourfile.zip to the client) or PHP to send a tracking event to GoogleAnalytics when this file is served?

  3. Another solution?

It seems that solution 2. would have the advantage of being 100% reliable, no matter the client has JS enabled or not.

But on the other hand, I don't want to use a very-few used hack. What is the usual solution for this very common situation?

回答1:

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