mirror of
https://github.com/jazzband/django-analytical.git
synced 2026-03-16 22:20:25 +00:00
Merge branch 'master' of github.com:greenkahuna/django-analytical into greenkahuna-master
This commit is contained in:
commit
cef2956edb
21 changed files with 357 additions and 18 deletions
|
|
@ -11,6 +11,7 @@ The application was inspired by and uses ideas from Analytical_, Joshua
|
|||
Krall's all-purpose analytics front-end for Rails.
|
||||
|
||||
The work on Crazy Egg was made possible by `Bateau Knowledge`_.
|
||||
The work on Intercom was made possible by `GreenKahuna`_.
|
||||
|
||||
.. _`Joost Cassee`: mailto:joost@cassee.net
|
||||
.. _`Eric Davis`: https://github.com/edavis
|
||||
|
|
@ -24,5 +25,6 @@ The work on Crazy Egg was made possible by `Bateau Knowledge`_.
|
|||
.. _`Philippe O. Wagner`: mailto:admin@arteria.ch
|
||||
.. _`Max Arnold`: https://github.com/max-arnold
|
||||
.. _`Martín Gaitán`: https://github.com/mgaitan
|
||||
.. _Analytical: https://github.com/jkrall/analytical
|
||||
.. _`Analytical`: https://github.com/jkrall/analytical
|
||||
.. _`Bateau Knowledge`: http://www.bateauknowledge.nl/
|
||||
.. _`GreenKahuna`: http://www.greenkahuna.com/
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
Version 0.17.0
|
||||
--------------
|
||||
* Update UserVoice support (Martín Gaitán)
|
||||
* Add support for Intercom.io (Steven Skoczen)
|
||||
|
||||
Version 0.16.0
|
||||
--------------
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ Currently supported services:
|
|||
* `Google Analytics`_ traffic analysis
|
||||
* `GoSquared`_ traffic monitoring
|
||||
* `HubSpot`_ inbound marketing
|
||||
* `Intercom`_ live chat and support
|
||||
* `KISSinsights`_ feedback surveys
|
||||
* `KISSmetrics`_ funnel analysis
|
||||
* `Mixpanel`_ event tracking
|
||||
|
|
@ -59,6 +60,7 @@ an issue to discuss your plans.
|
|||
.. _`Google Analytics`: http://www.google.com/analytics/
|
||||
.. _`GoSquared`: http://www.gosquared.com/
|
||||
.. _`HubSpot`: http://www.hubspot.com/
|
||||
.. _`Intercom`: http://www.intercom.io/
|
||||
.. _`KISSinsights`: http://www.kissinsights.com/
|
||||
.. _`KISSmetrics`: http://www.kissmetrics.com/
|
||||
.. _`Mixpanel`: http://www.mixpanel.com/
|
||||
|
|
|
|||
|
|
@ -10,6 +10,6 @@ Django_ project. See the ``docs`` directory for more information.
|
|||
|
||||
__author__ = "Joost Cassee"
|
||||
__email__ = "joost@cassee.net"
|
||||
__version__ = "0.16.0"
|
||||
__version__ = "0.17.0"
|
||||
__copyright__ = "Copyright (C) 2011-2012 Joost Cassee and others"
|
||||
__license__ = "MIT License"
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ TAG_MODULES = [
|
|||
'analytical.google_analytics',
|
||||
'analytical.gosquared',
|
||||
'analytical.hubspot',
|
||||
'analytical.intercom',
|
||||
'analytical.kiss_insights',
|
||||
'analytical.kiss_metrics',
|
||||
'analytical.mixpanel',
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ class ChartbeatBottomNode(Node):
|
|||
domain = _get_domain(context)
|
||||
if domain is not None:
|
||||
config['domain'] = domain
|
||||
html = SETUP_CODE % {'config': json.dumps(config)}
|
||||
html = SETUP_CODE % {'config': json.dumps(config, sort_keys=True)}
|
||||
if is_internal_ip(context, 'CHARTBEAT'):
|
||||
html = disable_html(html, 'Chartbeat')
|
||||
return html
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ class ClickyNode(Node):
|
|||
custom.setdefault('session', {})['username'] = identity
|
||||
|
||||
html = TRACKING_CODE % {'site_id': self.site_id,
|
||||
'custom': json.dumps(custom)}
|
||||
'custom': json.dumps(custom, sort_keys=True)}
|
||||
if is_internal_ip(context, 'CLICKY'):
|
||||
html = disable_html(html, 'Clicky')
|
||||
return html
|
||||
|
|
|
|||
88
analytical/templatetags/intercom.py
Normal file
88
analytical/templatetags/intercom.py
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
"""
|
||||
intercom.io template tags and filters.
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import
|
||||
import json
|
||||
import time
|
||||
import re
|
||||
|
||||
from django.template import Library, Node, TemplateSyntaxError
|
||||
|
||||
from analytical.utils import disable_html, get_required_setting, is_internal_ip,\
|
||||
get_user_from_context, get_identity
|
||||
|
||||
APP_ID_RE = re.compile(r'[\da-f]+$')
|
||||
TRACKING_CODE = """
|
||||
<script id="IntercomSettingsScriptTag">
|
||||
window.intercomSettings = %(settings_json)s;
|
||||
</script>
|
||||
<script>(function(){var w=window;var ic=w.Intercom;if(typeof ic==="function"){ic('reattach_activator');ic('update',intercomSettings);}else{var d=document;var i=function(){i.c(arguments)};i.q=[];i.c=function(args){i.q.push(args)};w.Intercom=i;function l(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='https://static.intercomcdn.com/intercom.v1.js';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);}if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})()</script>
|
||||
"""
|
||||
|
||||
register = Library()
|
||||
|
||||
|
||||
@register.tag
|
||||
def intercom(parser, token):
|
||||
"""
|
||||
Intercom.io template tag.
|
||||
|
||||
Renders Javascript code to intercom.io testing. You must supply
|
||||
your APP ID account number in the ``INTERCOM_APP_ID``
|
||||
setting.
|
||||
"""
|
||||
bits = token.split_contents()
|
||||
if len(bits) > 1:
|
||||
raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
|
||||
return IntercomNode()
|
||||
|
||||
|
||||
class IntercomNode(Node):
|
||||
def __init__(self):
|
||||
self.app_id = get_required_setting(
|
||||
'INTERCOM_APP_ID', APP_ID_RE,
|
||||
"must be a string looking like 'XXXXXXX'")
|
||||
|
||||
def _identify(self, user):
|
||||
name = user.get_full_name()
|
||||
if not name:
|
||||
name = user.username
|
||||
return name
|
||||
|
||||
def _get_custom_attrs(self, context):
|
||||
vars = {}
|
||||
for dict_ in context:
|
||||
for var, val in dict_.items():
|
||||
if var.startswith('intercom_'):
|
||||
vars[var[9:]] = val
|
||||
|
||||
user = get_user_from_context(context)
|
||||
if user is not None and user.is_authenticated():
|
||||
if 'full_name' not in vars:
|
||||
vars['full_name'] = get_identity(context, 'intercom', self._identify, user)
|
||||
if 'email' not in vars and user.email:
|
||||
vars['email'] = user.email
|
||||
|
||||
vars['created_at'] = int(time.mktime(user.date_joined.timetuple()))
|
||||
else:
|
||||
vars['created_at'] = None
|
||||
|
||||
return vars
|
||||
|
||||
def render(self, context):
|
||||
html = ""
|
||||
user = get_user_from_context(context)
|
||||
vars = self._get_custom_attrs(context)
|
||||
vars["app_id"] = self.app_id
|
||||
html = TRACKING_CODE % {"settings_json": json.dumps(vars, sort_keys=True)}
|
||||
|
||||
if is_internal_ip(context, 'INTERCOM') or not user or not user.is_authenticated():
|
||||
# Intercom is disabled for non-logged in users.
|
||||
html = disable_html(html, 'Intercom')
|
||||
return html
|
||||
|
||||
|
||||
def contribute_to_analytical(add_node):
|
||||
IntercomNode()
|
||||
add_node('body_bottom', IntercomNode)
|
||||
|
|
@ -78,13 +78,13 @@ class KissMetricsNode(Node):
|
|||
try:
|
||||
name, properties = context[EVENT_CONTEXT_KEY]
|
||||
commands.append(EVENT_CODE % {'name': name,
|
||||
'properties': json.dumps(properties)})
|
||||
'properties': json.dumps(properties, sort_keys=True)})
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
properties = context[PROPERTY_CONTEXT_KEY]
|
||||
commands.append(PROPERTY_CODE % {
|
||||
'properties': json.dumps(properties)})
|
||||
'properties': json.dumps(properties, sort_keys=True)})
|
||||
except KeyError:
|
||||
pass
|
||||
html = TRACKING_CODE % {'api_key': self.api_key,
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ class MixpanelNode(Node):
|
|||
try:
|
||||
name, properties = context[EVENT_CONTEXT_KEY]
|
||||
commands.append(EVENT_CODE % {'name': name,
|
||||
'properties': json.dumps(properties)})
|
||||
'properties': json.dumps(properties, sort_keys=True)})
|
||||
except KeyError:
|
||||
pass
|
||||
html = TRACKING_CODE % {'token': self.token,
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ class OlarkNode(Node):
|
|||
extra_code.append(NICKNAME_CODE % identity)
|
||||
try:
|
||||
extra_code.append(STATUS_CODE %
|
||||
json.dumps(context[STATUS_CONTEXT_KEY]))
|
||||
json.dumps(context[STATUS_CONTEXT_KEY], sort_keys=True))
|
||||
except KeyError:
|
||||
pass
|
||||
extra_code.extend(self._get_configuration(context))
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ class ReinvigorateNode(Node):
|
|||
email = get_identity(context, 'reinvigorate', lambda u: u.email)
|
||||
if email is not None:
|
||||
re_vars['context'] = email
|
||||
tags = " ".join("var re_%s_tag = %s;" % (tag, json.dumps(value))
|
||||
tags = " ".join("var re_%s_tag = %s;" % (tag, json.dumps(value, sort_keys=True))
|
||||
for tag, value in re_vars.items())
|
||||
|
||||
html = TRACKING_CODE % {'tracking_id': self.tracking_id,
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ class UserVoiceNode(Node):
|
|||
getattr(settings, 'USERVOICE_ADD_TRIGGER', True))
|
||||
|
||||
html = TRACKING_CODE % {'widget_key': widget_key,
|
||||
'options': json.dumps(options),
|
||||
'options': json.dumps(options, sort_keys=True),
|
||||
'trigger': TRIGGER if trigger else ''}
|
||||
return html
|
||||
|
||||
|
|
|
|||
|
|
@ -57,8 +57,8 @@ class WoopraNode(Node):
|
|||
visitor = self._get_visitor(context)
|
||||
|
||||
html = TRACKING_CODE % {
|
||||
'settings': json.dumps(settings),
|
||||
'visitor': json.dumps(visitor),
|
||||
'settings': json.dumps(settings, sort_keys=True),
|
||||
'visitor': json.dumps(visitor, sort_keys=True),
|
||||
}
|
||||
if is_internal_ip(context, 'WOOPRA'):
|
||||
html = disable_html(html, 'Woopra')
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ from analytical.tests.test_tag_gauges import *
|
|||
from analytical.tests.test_tag_google_analytics import *
|
||||
from analytical.tests.test_tag_gosquared import *
|
||||
from analytical.tests.test_tag_hubspot import *
|
||||
from analytical.tests.test_tag_intercom import *
|
||||
from analytical.tests.test_tag_kiss_insights import *
|
||||
from analytical.tests.test_tag_kiss_metrics import *
|
||||
from analytical.tests.test_tag_mixpanel import *
|
||||
|
|
|
|||
94
analytical/tests/test_tag_intercom.py
Normal file
94
analytical/tests/test_tag_intercom.py
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
"""
|
||||
Tests for the intercom template tags and filters.
|
||||
"""
|
||||
|
||||
import datetime
|
||||
|
||||
from django.contrib.auth.models import User, AnonymousUser
|
||||
from django.http import HttpRequest
|
||||
from django.template import Context
|
||||
|
||||
from analytical.templatetags.intercom import IntercomNode
|
||||
from analytical.tests.utils import TagTestCase, override_settings, SETTING_DELETED
|
||||
from analytical.utils import AnalyticalException
|
||||
|
||||
|
||||
@override_settings(INTERCOM_APP_ID='1234567890abcdef0123456789')
|
||||
class IntercomTagTestCase(TagTestCase):
|
||||
"""
|
||||
Tests for the ``intercom`` template tag.
|
||||
"""
|
||||
|
||||
def test_tag(self):
|
||||
rendered_tag = self.render_tag('intercom', 'intercom')
|
||||
self.assertTrue(rendered_tag.startswith('<!-- Intercom disabled on internal IP address'))
|
||||
|
||||
def test_node(self):
|
||||
now = datetime.datetime(2014, 4, 9, 15, 15, 0)
|
||||
rendered_tag = IntercomNode().render(Context({
|
||||
'user': User(
|
||||
username='test',
|
||||
first_name='Firstname',
|
||||
last_name='Lastname',
|
||||
email="test@example.com",
|
||||
date_joined=now)
|
||||
}))
|
||||
# Because the json isn't predictably ordered, we can't just test the whole thing verbatim.
|
||||
self.assertEquals("""
|
||||
<script id="IntercomSettingsScriptTag">
|
||||
window.intercomSettings = {"app_id": "1234567890abcdef0123456789", "created_at": 1397074500, "email": "test@example.com", "full_name": "Firstname Lastname"};
|
||||
</script>
|
||||
<script>(function(){var w=window;var ic=w.Intercom;if(typeof ic==="function"){ic('reattach_activator');ic('update',intercomSettings);}else{var d=document;var i=function(){i.c(arguments)};i.q=[];i.c=function(args){i.q.push(args)};w.Intercom=i;function l(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='https://static.intercomcdn.com/intercom.v1.js';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);}if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})()</script>
|
||||
""", rendered_tag)
|
||||
|
||||
@override_settings(INTERCOM_APP_ID=SETTING_DELETED)
|
||||
def test_no_account_number(self):
|
||||
self.assertRaises(AnalyticalException, IntercomNode)
|
||||
|
||||
@override_settings(INTERCOM_APP_ID='123abQ')
|
||||
def test_wrong_account_number(self):
|
||||
self.assertRaises(AnalyticalException, IntercomNode)
|
||||
|
||||
def test_identify_name_email_and_created_at(self):
|
||||
now = datetime.datetime(2014, 4, 9, 15, 15, 0)
|
||||
r = IntercomNode().render(Context({'user': User(username='test',
|
||||
first_name='Firstname', last_name='Lastname',
|
||||
email="test@example.com", date_joined=now)}))
|
||||
self.assertTrue(
|
||||
"""window.intercomSettings = {"app_id": "1234567890abcdef0123456789", "created_at": 1397074500, "email": "test@example.com", "full_name": "Firstname Lastname"};"""\
|
||||
in r
|
||||
)
|
||||
|
||||
def test_custom(self):
|
||||
r = IntercomNode().render(Context({
|
||||
'intercom_var1': 'val1',
|
||||
'intercom_var2': 'val2'
|
||||
}))
|
||||
self.assertTrue('var1": "val1", "var2": "val2"' in r)
|
||||
|
||||
def test_identify_name_and_email(self):
|
||||
r = IntercomNode().render(Context({
|
||||
'user': User(username='test',
|
||||
first_name='Firstname',
|
||||
last_name='Lastname',
|
||||
email="test@example.com")
|
||||
}))
|
||||
self.assertTrue('"email": "test@example.com", "full_name": "Firstname Lastname"' in r)
|
||||
|
||||
def test_identify_username_no_email(self):
|
||||
r = IntercomNode().render(Context({'user': User(username='test')}))
|
||||
self.assertTrue('"full_name": "test"' in r, r)
|
||||
|
||||
def test_no_identify_when_explicit_name(self):
|
||||
r = IntercomNode().render(Context({'intercom_full_name': 'explicit',
|
||||
'user': User(username='implicit')}))
|
||||
self.assertTrue('"full_name": "explicit"' in r, r)
|
||||
|
||||
def test_no_identify_when_explicit_email(self):
|
||||
r = IntercomNode().render(Context({'intercom_email': 'explicit',
|
||||
'user': User(username='implicit')}))
|
||||
self.assertTrue('"email": "explicit"' in r, r)
|
||||
|
||||
def test_disable_for_anonymous_users(self):
|
||||
r = IntercomNode().render(Context({'user': AnonymousUser()}))
|
||||
self.assertTrue(r.startswith('<!-- Intercom disabled on internal IP address'), r)
|
||||
|
|
@ -61,7 +61,7 @@ class KissMetricsTagTestCase(TagTestCase):
|
|||
def test_property(self):
|
||||
r = KissMetricsNode().render(Context({'kiss_metrics_properties':
|
||||
{'prop1': 'val1', 'prop2': 'val2'}}))
|
||||
self.assertTrue("_kmq.push(['set', "
|
||||
self.assertTrue("_kmq.push([\'set\', "
|
||||
'{"prop1": "val1", "prop2": "val2"}]);' in r, r)
|
||||
|
||||
def test_alias(self):
|
||||
|
|
|
|||
|
|
@ -79,5 +79,4 @@ class UserVoiceTagTestCase(TagTestCase):
|
|||
@override_settings(USERVOICE_ADD_TRIGGER=False)
|
||||
def test_auto_trigger_custom_win(self):
|
||||
r = UserVoiceNode().render(Context({'uservoice_add_trigger': True}))
|
||||
self.assertTrue("UserVoice.push(['addTrigger', {}]);" in r, r)
|
||||
|
||||
self.assertTrue("UserVoice.push(['addTrigger', {}]);" in r, r)
|
||||
|
|
@ -44,15 +44,15 @@ class WoopraTagTestCase(TagTestCase):
|
|||
r = WoopraNode().render(Context({'woopra_var1': 'val1',
|
||||
'woopra_var2': 'val2'}))
|
||||
self.assertTrue('var woo_visitor = {"var1": "val1", "var2": "val2"};'
|
||||
in r, r)
|
||||
in r, r)
|
||||
|
||||
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
|
||||
def test_identify_name_and_email(self):
|
||||
r = WoopraNode().render(Context({'user': User(username='test',
|
||||
first_name='Firstname', last_name='Lastname',
|
||||
email="test@example.com")}))
|
||||
self.assertTrue('var woo_visitor = {"name": "Firstname Lastname", '
|
||||
'"email": "test@example.com"};' in r, r)
|
||||
self.assertTrue('var woo_visitor = {"email": "test@example.com", '
|
||||
'"name": "Firstname Lastname"};' in r, r)
|
||||
|
||||
@override_settings(ANALYTICAL_AUTO_IDENTIFY=True)
|
||||
def test_identify_username_no_email(self):
|
||||
|
|
|
|||
|
|
@ -128,6 +128,10 @@ settings required to enable each service are listed here:
|
|||
HUBSPOT_PORTAL_ID = '1234'
|
||||
HUBSPOT_DOMAIN = 'somedomain.web101.hubspot.com'
|
||||
|
||||
* :doc:`Intercom <services/intercom>`::
|
||||
|
||||
INTERCOM_APP_ID = '0123456789abcdef0123456789abcdef01234567'
|
||||
|
||||
* :doc:`KISSinsights <services/kiss_insights>`::
|
||||
|
||||
KISS_INSIGHTS_ACCOUNT_NUMBER = '12345'
|
||||
|
|
|
|||
147
docs/services/intercom.rst
Normal file
147
docs/services/intercom.rst
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
=============================
|
||||
Intercom.io -- Real-time tracking
|
||||
=============================
|
||||
|
||||
Intercom.io_ is an easy way to implement real-chat and individual
|
||||
support for a website
|
||||
|
||||
.. _Intercom.io: http://www.intercom.io/
|
||||
|
||||
|
||||
.. intercom-installation:
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
To start using the Intercom.io integration, you must have installed the
|
||||
django-analytical package and have added the ``analytical`` application
|
||||
to :const:`INSTALLED_APPS` in your project :file:`settings.py` file.
|
||||
See :doc:`../install` for details.
|
||||
|
||||
Next you need to add the Intercom.io template tag to your templates.
|
||||
This step is only needed if you are not using the generic
|
||||
:ttag:`analytical.*` tags. If you are, skip to
|
||||
:ref:`intercom-configuration`.
|
||||
|
||||
The Intercom.io Javascript code is inserted into templates using a
|
||||
template tag. Load the :mod:`intercom` template tag library and
|
||||
insert the :ttag:`intercom` tag. Because every page that you want to
|
||||
track must have the tag, it is useful to add it to your base template.
|
||||
Insert the tag at the bottom of the HTML body::
|
||||
|
||||
{% load intercom %}
|
||||
<html>
|
||||
<head></head>
|
||||
<body>
|
||||
<!-- Your page -->
|
||||
{% intercom %}
|
||||
</body>
|
||||
</html>
|
||||
...
|
||||
|
||||
|
||||
.. _intercom-configuration:
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
Before you can use the Intercom.io integration, you must first set your
|
||||
app id.
|
||||
|
||||
|
||||
.. _intercom-site-id:
|
||||
|
||||
Setting the app id
|
||||
--------------------------
|
||||
|
||||
Intercom.io gives you a unique app id, and the :ttag:`intercom`
|
||||
tag will include it in the rendered Javascript code. You can find your
|
||||
app id by clicking the *Tracking Code* link when logged into
|
||||
the on the intercom.io website. A page will display containing
|
||||
HTML code looking like this::
|
||||
|
||||
<script id="IntercomSettingsScriptTag">
|
||||
window.intercomSettings = { name: "Jill Doe", email: "jill@example.com", created_at: 1234567890, app_id: "XXXXXXXXXXXXXXXXXXXXXXX" };
|
||||
</script>
|
||||
<script>(function(){var w=window;var ic=w.Intercom;if(typeof ic==="function"){ic('reattach_activator');ic('update',intercomSettings);}else{var d=document;var i=function(){i.c(arguments)};i.q=[];i.c=function(args){i.q.push(args)};w.Intercom=i;function l(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='https://static.intercomcdn.com/intercom.v1.js';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);}if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})()</script>
|
||||
|
||||
The code ``XXXXXXXXXXXXXXXXXXXXXXX`` is your app id. Set
|
||||
:const:`INTERCOM_APP_ID` in the project :file:`settings.py`
|
||||
file::
|
||||
|
||||
INTERCOM_APP_ID = 'XXXXXXXXXXXXXXXXXXXXXXX'
|
||||
|
||||
If you do not set an app id, the Javascript code will not be
|
||||
rendered.
|
||||
|
||||
|
||||
Custom data
|
||||
-----------
|
||||
|
||||
As described in the Intercom documentation on `custom visitor data`_,
|
||||
the data that is tracked by Intercom can be customized. Using template
|
||||
context variables, you can let the :ttag:`intercom` tag pass custom data
|
||||
to Intercom automatically. You can set the context variables in your view
|
||||
when your render a template containing the tracking code::
|
||||
|
||||
context = RequestContext({'intercom_cart_value': cart.total_price})
|
||||
return some_template.render(context)
|
||||
|
||||
For some data, it is annoying to do this for every view, so you may want
|
||||
to set variables in a context processor that you add to the
|
||||
:data:`TEMPLATE_CONTEXT_PROCESSORS` list in :file:`settings.py`::
|
||||
|
||||
from django.utils.hashcompat import md5_constructor as md5
|
||||
|
||||
GRAVATAR_URL = 'http://www.gravatar.com/avatar/'
|
||||
|
||||
def intercom_custom_data(request):
|
||||
try:
|
||||
email = request.user.email
|
||||
except AttributeError:
|
||||
return {}
|
||||
email_hash = md5(email).hexdigest()
|
||||
avatar_url = "%s%s" % (GRAVATAR_URL, email_hash)
|
||||
return {'intercom_avatar': avatar_url}
|
||||
|
||||
Just remember that if you set the same context variable in the
|
||||
:class:`~django.template.context.RequestContext` constructor and in a
|
||||
context processor, the latter clobbers the former.
|
||||
|
||||
Standard variables that will be displayed in the Intercom live visitor
|
||||
data are listed in the table below, but you can define any ``intercom_*``
|
||||
variable you like and have that detail passed from within the visitor
|
||||
live stream data when viewing Intercom.
|
||||
|
||||
==================== ===========================================
|
||||
Context variable Description
|
||||
==================== ===========================================
|
||||
``intercom_name`` The visitor's full name.
|
||||
-------------------- -------------------------------------------
|
||||
``intercom_email`` The visitor's email address.
|
||||
-------------------- -------------------------------------------
|
||||
``created_at`` The date the visitor created an account
|
||||
==================== ===========================================
|
||||
|
||||
|
||||
.. _`custom visitor data`: http://docs.intercom.io/custom-data/adding-custom-data
|
||||
|
||||
|
||||
Identifying authenticated users
|
||||
-------------------------------
|
||||
|
||||
If you have not set the ``intercom_name`` or ``intercom_email`` variables
|
||||
explicitly, the username and email address of an authenticated user are
|
||||
passed to Intercom automatically. See :ref:`identifying-visitors`.
|
||||
|
||||
.. _intercom-internal-ips:
|
||||
|
||||
Internal IP addresses
|
||||
---------------------
|
||||
|
||||
Usually you do not want to track clicks from your development or
|
||||
internal IP addresses. By default, if the tags detect that the client
|
||||
comes from any address in the :const:`ANALYTICAL_INTERNAL_IPS` setting
|
||||
(which is :const:`INTERNAL_IPS` by default,) the tracking code is
|
||||
commented out. See :ref:`identifying-visitors` for important information
|
||||
about detecting the visitor IP address.
|
||||
Loading…
Reference in a new issue