django-analytical icon indicating copy to clipboard operation
django-analytical copied to clipboard

Support for GA Universal Analytics?

Open benregn opened this issue 12 years ago • 19 comments

benregn avatar May 17 '13 15:05 benregn

Hi Thomas,

Are you using or going to use Universal Analytics? I am currently not using it, and I found it best if people who use a service also implement an integration. Would you be able to contribute code?

I guess it would not be much more than using the JavaScript from [1] instead of the current code.

Regards, Joost

[1] https://developers.google.com/analytics/devguides/collection/analyticsjs/

jcassee avatar May 17 '13 21:05 jcassee

It would be nice to have the new Universal Analytics for Google implemented.

nknganda avatar Jul 28 '13 21:07 nknganda

Hi Newton,

I agree, that would be great. What would it take to implement Universal Analytics, just use a different JavaScript snippet? Would you be able to contribute it?

Regards, Joost

jcassee avatar Jul 28 '13 21:07 jcassee

I'm able to contribute it, but I need your opinion on how to do it. I can extend existing google_analytics.py (this will probably lead to more logic in template tag), or create separate plugin. They will need to coexist for some time until classic analytics will be deprecated by Google. What do you think is more appropriate?

max-arnold avatar Nov 18 '13 13:11 max-arnold

Hi Max,

Thanks for your offer to develop this feature! I think a separate plugin is better if every call is different. I think more features will be added to the new Analytics.js script.

Joost

jcassee avatar Nov 19 '13 14:11 jcassee

@max-arnold It's been a while, but are you still interested in contributing Google Universal Analytics?

jcassee avatar May 19 '15 20:05 jcassee

I'm sorry, but I haven't managed to allocate enough time for this plugin and solved my need by integrating analytics.js directly into my projects. I did some hacking in a separate branch, but there is not enough useful code to contribute. Feel free to reassign this issue to someone else.

max-arnold avatar May 20 '15 01:05 max-arnold

@jcassee I could do it the next weekend. should we deprecate the current analytic support, replace it or support both versions?

mgaitan avatar May 20 '15 02:05 mgaitan

@max-arnold No problem, it's been almost two years.

@mgaitan Thanks! The two analytics systems are still advertised so I think it should be a separate module that we support alongside the classic version.

jcassee avatar May 20 '15 11:05 jcassee

Anyone still interested in GA Universal Analytics? - Pull request anyone?

bittner avatar Aug 24 '15 12:08 bittner

+1 still interested

rocktavious avatar Apr 18 '16 16:04 rocktavious

@rocktavious Are you willing to contribute the implementation? This is an easy thing: Just take one of the existing implementations in templatetags, and roll your modified version.

If you need help with coding you can post your questions in our Gitter room (see the README).

bittner avatar May 26 '16 16:05 bittner

Migration guide: https://developers.google.com/analytics/devguides/collection/upgrade/reference/gajs-analyticsjs

Here's a start to google_universal.py. If someone looks it over, tries it out, and writes some tests, they can create the pull request:

"""
Google Analytics (Universal) template tags and filters.
"""

from __future__ import absolute_import

import decimal
import re
import json

from django.conf import settings
from django.template import Library, Node, TemplateSyntaxError

from analytical.utils import (
    AnalyticalException,
    disable_html,
    get_domain,
    get_required_setting,
    is_internal_ip,
)

TRACK_SINGLE_DOMAIN = 1
TRACK_MULTIPLE_SUBDOMAINS = 2
TRACK_MULTIPLE_DOMAINS = 3

SCOPE_VISITOR = 1
SCOPE_SESSION = 2
SCOPE_PAGE = 3

PROPERTY_ID_RE = re.compile(r'^UA-\d+-\d+$')
SETUP_CODE = """
<script>
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
ga('create', '%(property_id)s', 'auto', %(options)s);
%(commands)s
ga('send', 'pageview');
</script>
<script async src='%(source)s'></script>
"""
REQUIRE_LINKER_CODE = "ga('require', 'linker');"
DOMAIN_CODE = "ga.set('linker:autoLink', %s]);"
CUSTOM_DIMENSION_CODE = "ga('set', 'dimension%(index)s', '%(value)s');"
DEFAULT_SOURCE = "https://www.google-analytics.com/analytics.js"
DISPLAY_ADVERTISING_CODE = "ga('require', 'displayfeatures');"

ZEROPLACES = decimal.Decimal('0')
TWOPLACES = decimal.Decimal('0.01')

register = Library()


@register.tag
def google_universal(parser, token):
    """
    Google Analytics tracking template tag.

    Renders Javascript code to track page visits.  You must supply
    your website property ID (as a string) in the
    ``GOOGLE_ANALYTICS_PROPERTY_ID`` setting.
    """
    bits = token.split_contents()
    if len(bits) > 1:
        raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
    return GoogleUniversalNode()


class GoogleUniversalNode(Node):
    def __init__(self):
        self.property_id = get_required_setting(
            'GOOGLE_ANALYTICS_PROPERTY_ID', PROPERTY_ID_RE,
            "must be a string looking like 'UA-XXXXXX-Y'")

    def render(self, context):
        options = {}
        commands = self._get_domain_commands(context)
        commands.extend(self._get_custom_dimension_commands(context))
        if getattr(settings, 'GOOGLE_ANALYTICS_DISPLAY_ADVERTISING', False):
            commands.append(DISPLAY_ADVERTISING_CODE)
        source = DEFAULT_SOURCE
        if tracking_type == TRACK_MULTIPLE_DOMAINS:
            options['allowLinker'] = True
            sampleRate = getattr(settings, 'GOOGLE_ANALYTICS_SAMPLE_RATE', False)
            if sampleRate is not False:
                value = decimal.Decimal(sampleRate)
                if not 0 <= value <= 100:
                    raise AnalyticalException("'GOOGLE_ANALYTICS_SAMPLE_RATE' must be >= 0 and <= 100")
                options['sampleRate'] = value.quantize(TWOPLACES)
        html = SETUP_CODE % {'property_id': self.property_id,
                             'commands': " ".join(commands),
                             'source': source,
                             'options': json.dumps(options)}
        if is_internal_ip(context, 'GOOGLE_ANALYTICS'):
            html = disable_html(html, 'Google Analytics')
        return html

    def _get_domain_commands(self, context):
        commands = []
        tracking_type = getattr(settings, 'GOOGLE_ANALYTICS_TRACKING_STYLE',
                                TRACK_SINGLE_DOMAIN)
        if tracking_type == TRACK_MULTIPLE_DOMAINS:
            getattr(settings, 'GOOGLE_ANALYTICS_OTHER_DOMAINS'
            if domain is None:
                raise AnalyticalException(
                    "tracking multiple domains with Google Analytics"
                    " requires other domain names")
            commands.append(REQUIRE_LINKER_CODE)
            commands.append(DOMAIN_CODE % json.dumps(domain))
        return commands

    def _get_custom_dimension_commands(self, context):
        values = (
            context.get('google_analytics_dim%s' % i) for i in range(1, 6)
        )
        params = [(i, v) for i, v in enumerate(values, 1) if v is not None]
        commands = []
        for index, var in params:
            name = var[0]
            value = var[1]
            try:
                scope = var[2]
            except IndexError:
                scope = SCOPE_PAGE
            commands.append(CUSTOM_DIMENSION_CODE % {
                'index': index,
                'value': value,
            })
        return commands

def contribute_to_analytical(add_node):
    GoogleUniversalNode()  # ensure properly configured
    add_node('head_bottom', GoogleUniversalNode)

kevinmickey avatar May 31 '16 04:05 kevinmickey

I will definitely take a look at integrating this next week, i'm currently at Pycon and won't beable to test integration this week.

rocktavious avatar May 31 '16 15:05 rocktavious

@jcassee, @kevinmickey, @rocktavious Hi, Joost Kevin and Kyle!

I just created an account on Google Analytics for the first time and installed django-analytical. I'm very excited to start using django-analytical. But I noticed the javascript code embedded into my base template using django-analytical doesn't quite look like the one I get from Google Analytics dashboard or the one you posted above, Kevin.

This is what it looks like straight from the Google Analytics Dashboard.

I'm very noob. So sorry if my question sounds very naive but can I still use django-analytical with Google Analytics? Since this thread has been around for a while and I wonder if GA Universal Analytics refers to what I can see today (as of Nov 2016) in my GA dashboard.

It seems to me that for noobs like me with very little to no budget Google Analytics seems to obvious choice when starting measuring what's happening in your website.

Thanks!

roperi avatar Nov 18 '16 14:11 roperi

+1

divick avatar Dec 07 '16 07:12 divick

Just checking, do we mean to support Google Tag Manager too by this implementation? (What is the difference?)

Disclaimer: I'm not using GA for years. So, my knowledge about it is fairly rusty.

bittner avatar Apr 05 '17 14:04 bittner

Just a heads-up: There are two PRs that are candidates for solving this issue: #140 and #154

Please, consider replacing the old module

As a side-note, I'd really appreciate if the currently deprecated google_analytics implementation would be replaced by an up-to-date version of google_analytics_js, which integrates also tag manager, probably as an option. Instead of adding just another module.

If I read this comparison and this explaination correctly then having just a single module should be possible. Feel free to correct me if I'm wrong.

bittner avatar Apr 02 '20 23:04 bittner

Anyone willing to consolidate the 3 google_analytics* modules into a single one? That would be a great contribution for an upcoming version 4.0.0 release. :rocket: :guitar:

bittner avatar Jul 06 '22 21:07 bittner