mirror of
https://github.com/jazzband/django-analytical.git
synced 2026-04-28 18:54:43 +00:00
Adds support for custom variables, in a similar pattern to woopra's tag.
This commit is contained in:
parent
6ebdb3de98
commit
a94f0d8bb0
3 changed files with 150 additions and 32 deletions
|
|
@ -3,17 +3,19 @@ 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, get_user_from_context
|
||||
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 = {'app_id': '%(app_id)s', 'full_name': '%(full_name)s', 'email': '%(email)s', 'created_at': %(created_at)s};
|
||||
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>
|
||||
"""
|
||||
|
|
@ -42,17 +44,40 @@ class IntercomNode(Node):
|
|||
'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)
|
||||
if user is not None and user.is_authenticated():
|
||||
html = TRACKING_CODE % {
|
||||
'app_id': self.app_id,
|
||||
'full_name': "%s %s" % (user.first_name, user.last_name),
|
||||
'email': user.email,
|
||||
'created_at': int(time.mktime(user.date_joined.timetuple())),
|
||||
}
|
||||
else:
|
||||
vars = self._get_custom_attrs(context)
|
||||
vars["app_id"] = self.app_id
|
||||
html = TRACKING_CODE % {"settings_json": json.dumps(vars)}
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -20,29 +20,29 @@ class IntercomTagTestCase(TagTestCase):
|
|||
"""
|
||||
|
||||
def test_tag(self):
|
||||
self.assertEqual("""<!-- Intercom disabled on internal IP address
|
||||
|
||||
-->""",
|
||||
self.render_tag('intercom', 'intercom'))
|
||||
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)
|
||||
self.assertEqual(
|
||||
"""
|
||||
<script id="IntercomSettingsScriptTag">
|
||||
window.intercomSettings = {'app_id': '1234567890abcdef0123456789', 'full_name': 'Firstname Lastname', 'email': 'test@example.com', 'created_at': 1397074500};
|
||||
</script>
|
||||
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.assertIn("""<script id="IntercomSettingsScriptTag">
|
||||
window.intercomSettings = {""", rendered_tag)
|
||||
self.assertIn('"app_id": "1234567890abcdef0123456789"', rendered_tag)
|
||||
self.assertIn('"full_name": "Firstname Lastname"', rendered_tag)
|
||||
self.assertIn('"email": "test@example.com"', rendered_tag)
|
||||
self.assertIn('"created_at": 1397074500', rendered_tag)
|
||||
self.assertIn("""</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>
|
||||
""",
|
||||
IntercomNode().render(Context({
|
||||
'user': User(
|
||||
username='test',
|
||||
first_name='Firstname',
|
||||
last_name='Lastname',
|
||||
email="test@example.com",
|
||||
date_joined=now)
|
||||
}))
|
||||
)
|
||||
""", rendered_tag)
|
||||
|
||||
@override_settings(INTERCOM_APP_ID=SETTING_DELETED)
|
||||
def test_no_account_number(self):
|
||||
|
|
@ -57,9 +57,43 @@ class IntercomTagTestCase(TagTestCase):
|
|||
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', "
|
||||
"'full_name': 'Firstname Lastname', "
|
||||
"'email': 'test@example.com', 'created_at': 1397074500};" in r, r)
|
||||
self.assertTrue("window.intercomSettings = {" in r, r)
|
||||
self.assertTrue('"app_id": "1234567890abcdef0123456789"' in r)
|
||||
self.assertTrue('"full_name": "Firstname Lastname"' in r)
|
||||
self.assertTrue('"email": "test@example.com"' in r)
|
||||
self.assertTrue('"created_at": 1397074500' in r)
|
||||
|
||||
def test_custom(self):
|
||||
r = IntercomNode().render(Context({
|
||||
'intercom_var1': 'val1',
|
||||
'intercom_var2': 'val2'
|
||||
}))
|
||||
self.assertTrue('"var1": "val1"' in r)
|
||||
self.assertTrue('"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('"full_name": "Firstname Lastname"' in r)
|
||||
self.assertTrue('"email": "test@example.com"' 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()}))
|
||||
|
|
|
|||
|
|
@ -75,6 +75,65 @@ 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
|
||||
|
|
|
|||
Loading…
Reference in a new issue