Add support for Olark

This commit is contained in:
Joost Cassee 2011-02-24 22:20:26 +01:00
parent 5ac645aebb
commit 4f2d95f928
5 changed files with 263 additions and 0 deletions

View file

@ -27,6 +27,7 @@ Currently supported services:
* `KISSinsights`_ feedback surveys
* `KISSmetrics`_ funnel analysis
* `Mixpanel`_ event tracking
* `Olark`_ visitor chat
* `Optimizely`_ A/B testing
* `Performable`_ web analytics and landing pages
@ -50,6 +51,7 @@ an issue to discuss your plans.
.. _KISSinsights: http://www.kissinsights.com/
.. _KISSmetrics: http://www.kissmetrics.com/
.. _Mixpanel: http://www.mixpanel.com/
.. _Olark: http://www.olark.com/
.. _Optimizely: http://www.optimizely.com/
.. _Performable: http://www.performable.com/
.. _`read online`: http://packages.python.org/django-analytical/

View file

@ -0,0 +1,76 @@
"""
Olark template tags.
"""
from __future__ import absolute_import
import re
from django.template import Library, Node, TemplateSyntaxError
from django.utils import simplejson
from analytical.utils import get_identity, get_required_setting
SITE_ID_RE = re.compile(r'^\d{4}-\d{3}-\d{2}-\d{4}$')
SETUP_CODE = """
<script type='text/javascript'>
/*{literal}<![CDATA[*/ window.olark||(function(k){var g=window,j=document,a=g.location.protocol=="https:"?"https:":"http:",i=k.name,b="load",h="addEventListener";(function(){g[i]=function(){(c.s=c.s||[]).push(arguments)};var c=g[i]._={},f=k.methods.length;while(f--){(function(l){g[i][l]=function(){g[i]("call",l,arguments)}})(k.methods[f])}c.l=k.loader;c.i=arguments.callee;c.p={0:+new Date};c.P=function(l){c.p[l]=new Date-c.p[0]};function e(){c.P(b);g[i](b)}g[h]?g[h](b,e,false):g.attachEvent("on"+b,e);c.P(1);var d=j.createElement("script"),m=document.getElementsByTagName("script")[0];d.type="text/javascript";d.async=true;d.src=a+"//"+c.l;m.parentNode.insertBefore(d,m);c.P(2)})()})({loader:(function(a){return "static.olark.com/jsclient/loader1.js?ts="+(a?a[1]:(+new Date))})(document.cookie.match(/olarkld=([0-9]+)/)),name:"olark",methods:["configure","extend","declare","identify"]}); olark.identify('%(site_id)s');/*]]>{/literal}*/
%(extra_code)s
</script>
"""
NICKNAME_CODE = "olark('api.chat.updateVisitorNickname', {snippet: '%s'});"
NICKNAME_CONTEXT_KEY = 'olark_nickname'
STATUS_CODE = "olark('api.chat.updateVisitorStatus', {snippet: %s});"
STATUS_CONTEXT_KEY = 'olark_status'
register = Library()
@register.tag
def olark(parser, token):
"""
Olark set-up template tag.
Renders Javascript code to set-up Olark chat. You must supply
your site ID in the ``OLARK_SITE_ID`` setting.
"""
bits = token.split_contents()
if len(bits) > 1:
raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
return OlarkNode()
class OlarkNode(Node):
def __init__(self):
self.site_id = get_required_setting('OLARK_SITE_ID', SITE_ID_RE,
"must be a string looking like 'XXXX-XXX-XX-XXXX'")
def render(self, context):
extra_code = []
try:
extra_code.append(NICKNAME_CODE % context[NICKNAME_CONTEXT_KEY])
except KeyError:
identity = get_identity(context, 'olark', self._get_nickname)
if identity is not None:
extra_code.append(NICKNAME_CODE % identity)
try:
extra_code.append(STATUS_CODE %
simplejson.dumps(context[STATUS_CONTEXT_KEY]))
except KeyError:
pass
html = SETUP_CODE % {'site_id': self.site_id,
'extra_code': " ".join(extra_code)}
return html
def _get_nickname(self, user):
name = user.get_full_name()
if name:
return "%s (%s)" % (name, user.username)
else:
return user.username
def contribute_to_analytical(add_node):
OlarkNode() # ensure properly configured
add_node('body_bottom', OlarkNode)

View file

@ -11,6 +11,7 @@ from analytical.tests.test_tag_hubspot import *
from analytical.tests.test_tag_kiss_insights import *
from analytical.tests.test_tag_kiss_metrics import *
from analytical.tests.test_tag_mixpanel import *
from analytical.tests.test_tag_olark import *
from analytical.tests.test_tag_optimizely import *
from analytical.tests.test_tag_performable import *
from analytical.tests.test_tag_reinvigorate import *

View file

@ -0,0 +1,61 @@
"""
Tests for the Olark template tags and filters.
"""
from django.contrib.auth.models import User
from django.template import Context
from analytical.templatetags.olark import OlarkNode
from analytical.tests.utils import TagTestCase
from analytical.utils import AnalyticalException
class OlarkTestCase(TagTestCase):
"""
Tests for the ``olark`` template tag.
"""
def setUp(self):
super(OlarkTestCase, self).setUp()
self.settings_manager.set(OLARK_SITE_ID='1234-567-89-0123')
def test_tag(self):
r = self.render_tag('olark', 'olark')
self.assertTrue("olark.identify('1234-567-89-0123');" in r, r)
def test_node(self):
r = OlarkNode().render(Context())
self.assertTrue("olark.identify('1234-567-89-0123');" in r, r)
def test_no_site_id(self):
self.settings_manager.delete('OLARK_SITE_ID')
self.assertRaises(AnalyticalException, OlarkNode)
def test_wrong_site_id(self):
self.settings_manager.set(OLARK_SITE_ID='1234-567-89-012')
self.assertRaises(AnalyticalException, OlarkNode)
self.settings_manager.set(OLARK_SITE_ID='1234-567-89-01234')
self.assertRaises(AnalyticalException, OlarkNode)
def test_identify(self):
self.settings_manager.set(ANALYTICAL_AUTO_IDENTIFY=True)
r = OlarkNode().render(Context({'user':
User(username='test', first_name='Test', last_name='User')}))
self.assertTrue("olark('api.chat.updateVisitorNickname', "
"{snippet: 'Test User (test)'});" in r, r)
def test_nickname(self):
r = OlarkNode().render(Context({'olark_nickname': 'testnick'}))
self.assertTrue("olark('api.chat.updateVisitorNickname', "
"{snippet: 'testnick'});" in r, r)
def test_status_string(self):
r = OlarkNode().render(Context({'olark_status': 'teststatus'}))
self.assertTrue("olark('api.chat.updateVisitorStatus', "
'{snippet: "teststatus"});' in r, r)
def test_status_string_list(self):
r = OlarkNode().render(Context({'olark_status':
['teststatus1', 'teststatus2']}))
self.assertTrue("olark('api.chat.updateVisitorStatus', "
'{snippet: ["teststatus1", "teststatus2"]});' in r, r)

123
docs/services/olark.rst Normal file
View file

@ -0,0 +1,123 @@
=====================
Olark -- visitor chat
=====================
Olark_ is a lightweight tool to chat with visitors to your website using
your existing instant messaging client. Chat with your website visitors
while they browse, using your mobile device or instant messenger. Olark
is fully customizable, supports multiple operators and keeps chat
transcripts.
.. _Olark: http://www.olark.com/
Installation
============
To start using the Olark 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 Olark 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:`olark-configuration`.
The Olark Javascript code is inserted into templates using a template
tag. Load the :mod:`olark` template tag library and insert the
:ttag:`olark` 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 olark %}
...
{% olark %}
</body>
</html>
.. _olark-configuration:
Configuration
=============
Before you can use the Olark integration, you must first set your site
ID. You can also customize the visitor nickname and add information to
their status in the operator buddy list.
Setting the site ID
-------------------
In order to install the chat code, you need to set your Olark site ID.
The :ttag:`olark` tag will include it in the rendered Javascript code.
You can find the site ID on `installation page`_ of you Olark account.
Set :const:`OLARK_SITE_ID` in the project :file:`settings.py` file::
OLARK_SITE_ID = 'XXXX-XXX-XX-XXXX'
If you do not set the site ID, the chat window will not be rendered.
.. _`installation page`: https://www.olark.com/install
Setting the visitor nickname
----------------------------
If your websites identifies visitors, you can use that to set their
nickname in the operator buddy list. By default, the name and username
of an authenticated user are automatically used to set the nickname.
See :ref:`identifying-visitors`.
You can also set the visitor nickname yourself by adding either the
``olark_nickname`` (alias: ``olark_identity``) or the
``analytical_identity`` variable to the template context. If both
variables are set, the former takes precedence. For example::
context = RequestContext({'olark_nickname': nick})
return some_template.render(context)
If you can derive the identity from the HTTP request, you can also use
a context processor that you add to the
:data:`TEMPLATE_CONTEXT_PROCESSORS` list in :file:`settings.py`::
def set_olark_nickname(request):
try:
return {'olark_nickname': request.user.email}
except AttributeError:
return {}
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.
See also `api.chat.updateVisitorNickname`_ in the Olark Javascript API
documentation.
.. _`api.chat.updateVisitorNickname`: http://www.olark.com/documentation/javascript/api.chat.updateVisitorNickname
Adding status information
-------------------------
If you want to send more information about the visitor to the operators,
you can add text snippets to the status field in the buddy list. Set
the ``olark_status`` context variable to a string or a list of strings
and the :ttag:`olark` tag will pass them to Olark as status messages::
context = RequestContext({'olark_status': [
'has %d items in cart' % cart.item_count,
'value of items is $%0.2f' % cart.total_value,
]})
return some_template.render(context)
See also `api.chat.updateVisitorStatus`_ in the Olark Javascript API
documentation.
.. _`api.chat.updateVisitorStatus`: http://www.olark.com/documentation/javascript/api.chat.updateVisitorStatus
----
Thanks go to Olark for their support with the development of this
application.