nystudio107 / craft-instantanalytics

DEPRECATED: Instant Analytics brings full Google Analytics support to your Twig templates and automatic Craft Commerce integration with Google Enhanced Ecommerce.
https://nystudio107.com/
Other
20 stars 9 forks source link

In contrary to what manuals says: Backend and Frontend analytics cannot be used together: they create 2 user sessions #42

Closed bencresty closed 4 years ago

bencresty commented 4 years ago

Describe the bug

According to the manual of the plugin the plugin we should be able to use the backend analytics via the plugin parallel with the gtag frontend lib for sending google analytics. But to my dissapointment this doesn't seem to work as we might expect. See steps to reproduce

To reproduce

Steps to reproduce the behaviour:

  1. Include the following in the main template:
    
    {# add gtag javascript code here #}

{% block analytics %} {% set pv_analytics = pageViewAnalytics(craft.app.request.url, 'title here') %} {% do pv_analytics.sendPageView() %} {% endblock %}

      {{ dump(pv_analytics.getClientId()) }}

(2. Clear all cookies for the domain in the browser)
3. Open the page in the browser
4. Look at the printed clientID of the plugin. This has a format like `bc3bc2f7-e923-4ea0-9410-7facd4f89cb8`. 
5. Now refresh the page in the browser
6. Look at the printed clientID of the plugin now. When using a browser which is blocking google analytics code frontend the clientID is the same as before, but on a browser calling the frontend analytics code suddenly this has changed to something with a format like `238036582.1618153421`, so is a completely new and different clientID now and therefor logs a new 'usersession' in analytics. From now on this clientID is used for this session, so the new page loads will be bound to the same (second) session. But for this usersession now 2 sessions exist in our analytics data and that's obviously not what we want as now we have double the amount of users and cannot track the first page they came onto the site to this user.

Sorry, but this way using the plugin is pretty much useless when combined with frontend analytics as the created data is a mess.

Would be great if we could get at least a response to these bugs and hopefully a fix soon.

### Expected behaviour
All google analytics for this session should be using the exact same clientID.

### Versions
- Plugin version: 1.1.7
- Craft version: 3.4.30
khalwat commented 4 years ago

@bencresty While the format of the _ga cookie is undocumented, and Google can and will change it, we to try to parse it:

    /**
     * gaParseCookie handles the parsing of the _ga cookie or setting it to a
     * unique identifier
     *
     * @return string the cid
     */
    private function gaParseCookie(): string
    {
        $cid = '';
        if (isset($_COOKIE['_ga'])) {
            $parts = preg_split('[\.]', $_COOKIE['_ga'], 4);
            if ($parts !== false) {
                $cid = implode('.', \array_slice($parts, 2));
            }
        } elseif (isset($_COOKIE['_ia']) && $_COOKIE['_ia'] !== '') {
            $cid = $_COOKIE['_ia'];
        } else {
            $cid = $this->gaGenUUID();
        }
        if (InstantAnalytics::$settings->createGclidCookie && !empty($cid)) {
            setcookie('_ia', $cid, strtotime('+2 years'), '/'); // Two years
        }

        return $cid;
    }

The issue is that if no _ga cookie is set, IA will create its own unique identifier for the clientId. It also will optionally create an _ia cookie to store that value.

In situations where there is no _ga cookie set yet (potentially because JavaScript hasn't been loaded and parsed by the time that IA is loading on the backend), we have a situation where IA doesn't know that you're loading Google Analytics on the frontend, and maybe it should instead just not set this value at all (letting it acquire the clientId later when the _ga cookie is set).

Here's what Google has to say about it: https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#cid

This field is required if User ID (uid) is not specified in the request. This anonymously identifies a particular user, device, or browser instance. For the web, this is generally stored as a first-party cookie with a two-year expiration. For mobile apps, this is randomly generated for each particular instance of an application install. The value of this field should be a random UUID (version 4) as described in http://www.ietf.org/rfc/rfc4122.txt.

khalwat commented 4 years ago

Google's official documentation states to get the cookie using their official JS libriaries: https://developers.google.com/analytics/devguides/collection/analyticsjs/cookies-user-id#getting_the_client_id_from_the_cookie

I'm not seeing a great way to do this automatically, as IA can't know whether you will or will not be using GA on the frontend.

My only thought is that there could be a setting in IA that essentially tells it to not do any tracking at all until or unless it can pull out a clientId from the _ga cookie. You're expressing your intention that IA should piggyback off of the GA data always, rather than ever creating its own unique clientId

khalwat commented 4 years ago

Addressed in: https://github.com/nystudio107/craft-instantanalytics/commit/5370b41f56f53ef588de0d9df6c44c879eff65b6

Released as: https://github.com/nystudio107/craft-instantanalytics/releases/tag/1.1.8

lmk how you go @bencresty

karensg commented 4 years ago

I am not sure whether setting this as a new default is a good idea. The most payment providers use webhooks to process payments and there is no _ga cookie, which results in E-commerce PaymentComplete event not working.

Took me some time to realize that. At least not a good idea to have that change in a minor update, I think.

If there is a way to somehow get the clientId in the OrderComplete hook, that would of course be fantastic. Other advice is welcome as well.

khalwat commented 4 years ago

Thanks @karensg sorry about that, you're right, probably it should have been a more major version bump