mirror of
https://github.com/jazzband/django-analytical.git
synced 2026-03-16 22:20:25 +00:00
Add Performable service. Update docs layout.
Use included README.rst in documentation. Bump version to 0.3.0.
This commit is contained in:
parent
e3a652766b
commit
6ea7e85b02
14 changed files with 326 additions and 54 deletions
|
|
@ -1,5 +1,5 @@
|
|||
Development
|
||||
-----------
|
||||
Version 0.3.0
|
||||
-------------
|
||||
* Added support for the Performable service.
|
||||
|
||||
Version 0.2.0
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
include LICENSE.txt
|
||||
include LICENSE.txt *.rst
|
||||
recursive-include docs *.rst *.py
|
||||
|
|
|
|||
15
README.rst
15
README.rst
|
|
@ -1,5 +1,5 @@
|
|||
django-analytical
|
||||
-----------------
|
||||
=================
|
||||
|
||||
The django-analytical application integrates analytics services into a
|
||||
Django_ project.
|
||||
|
|
@ -8,6 +8,7 @@ Using an analytics service with a Django project means adding Javascript
|
|||
tracking code to the project templates. Of course, every service has
|
||||
its own specific installation instructions. Furthermore, you need to
|
||||
include your unique identifiers, which then end up in the templates.
|
||||
|
||||
This application hides the details of the different analytics services
|
||||
behind a generic interface, and keeps personal information and
|
||||
configuration out of the templates. Its goal is to make the basic
|
||||
|
|
@ -30,12 +31,12 @@ Currently supported services:
|
|||
The documentation can be found in the ``docs`` directory or `read
|
||||
online`_. The project source is `hosted by GitHub`_.
|
||||
|
||||
If you want to help out with development of django-analytical, by
|
||||
posting detailed bug reports, suggesting new features or other analytics
|
||||
services to support, or doing some development work yourself, please use
|
||||
the `issue tracker`_. If you want to get your hands dirty yourself,
|
||||
great! Clone the repository, make changes and send a pull request.
|
||||
Please do create an issue to discuss your plans.
|
||||
If you want to help out with the development of django-analytical, by
|
||||
posting detailed bug reports, proposing new features or other analytics
|
||||
services to support, or suggesting documentation improvements, use the
|
||||
`issue tracker`_. If you want to get your hands dirty, great! Clone
|
||||
the repository, make changes and send a pull request. Please do create
|
||||
an issue to discuss your plans.
|
||||
|
||||
.. _Django: http://www.djangoproject.com/
|
||||
.. _Chartbeat: http://www.chartbeat.com/
|
||||
|
|
|
|||
|
|
@ -10,6 +10,6 @@ Django_ project. See the ``docs`` directory for more information.
|
|||
|
||||
__author__ = "Joost Cassee"
|
||||
__email__ = "joost@cassee.net"
|
||||
__version__ = "0.2.0"
|
||||
__version__ = "0.3.0"
|
||||
__copyright__ = "Copyright (C) 2011 Joost Cassee"
|
||||
__license__ = "MIT License"
|
||||
|
|
|
|||
77
analytical/templatetags/performable.py
Normal file
77
analytical/templatetags/performable.py
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
"""
|
||||
Performable template tags and filters.
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import re
|
||||
|
||||
from django.template import Library, Node, TemplateSyntaxError
|
||||
|
||||
from analytical.utils import is_internal_ip, disable_html, get_identity, \
|
||||
get_required_setting
|
||||
|
||||
|
||||
API_KEY_RE = re.compile(r'^\w{6}$')
|
||||
SETUP_CODE = """<script src="//d1nu2rn22elx8m.cloudfront.net/performable/pax/%(api_key)s.js" type="text/javascript"></script>"""
|
||||
IDENTIFY_CODE = """
|
||||
<script type="text/javascript">
|
||||
var _paq = _paq || [];
|
||||
_paq.push(["identify", {identity: "%s"}]);
|
||||
</script>
|
||||
"""
|
||||
EMBED_CODE = """
|
||||
<script type="text/javascript" src="//d1nu2rn22elx8m.cloudfront.net/performable/embed/page.js"></script>
|
||||
<script type="text/javascript">
|
||||
(function() {
|
||||
var $f = new PerformableEmbed();
|
||||
$f.initialize({'host': '%(hostname)s', 'page': '%(page_id)s'});
|
||||
$f.write();
|
||||
})()
|
||||
</script>
|
||||
"""
|
||||
|
||||
register = Library()
|
||||
|
||||
|
||||
@register.tag
|
||||
def performable(parser, token):
|
||||
"""
|
||||
Performable template tag.
|
||||
|
||||
Renders Javascript code to set-up Performable tracking. You must
|
||||
supply your Performable API key in the ``PERFORMABLE_API_KEY``
|
||||
setting.
|
||||
"""
|
||||
bits = token.split_contents()
|
||||
if len(bits) > 1:
|
||||
raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
|
||||
return PerformableNode()
|
||||
|
||||
class PerformableNode(Node):
|
||||
def __init__(self):
|
||||
self.api_key = get_required_setting(
|
||||
'PERFORMABLE_API_KEY', API_KEY_RE,
|
||||
"must be a string containing five alphanumerical characters")
|
||||
|
||||
def render(self, context):
|
||||
html = SETUP_CODE % {'api_key': self.api_key}
|
||||
identity = get_identity(context, 'performable')
|
||||
if identity is not None:
|
||||
html = "%s%s" % (IDENTIFY_CODE % identity, html)
|
||||
if is_internal_ip(context, 'PERFORMABLE'):
|
||||
html = disable_html(html, 'Performable')
|
||||
return html
|
||||
|
||||
|
||||
@register.simple_tag
|
||||
def performable_embed(hostname, page_id):
|
||||
"""
|
||||
Include a Performable landing page.
|
||||
"""
|
||||
return EMBED_CODE % locals()
|
||||
|
||||
|
||||
def contribute_to_analytical(add_node):
|
||||
PerformableNode() # ensure properly configured
|
||||
add_node('body_bottom', PerformableNode)
|
||||
|
|
@ -12,4 +12,5 @@ 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_optimizely import *
|
||||
from analytical.tests.test_tag_performable import *
|
||||
from analytical.tests.test_utils import *
|
||||
|
|
|
|||
69
analytical/tests/test_tag_performable.py
Normal file
69
analytical/tests/test_tag_performable.py
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
"""
|
||||
Tests for the Performable template tags and filters.
|
||||
"""
|
||||
|
||||
from django.http import HttpRequest
|
||||
from django.template import Context
|
||||
|
||||
from analytical.templatetags.performable import PerformableNode
|
||||
from analytical.tests.utils import TagTestCase
|
||||
from analytical.utils import AnalyticalException
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
|
||||
class PerformableTagTestCase(TagTestCase):
|
||||
"""
|
||||
Tests for the ``performable`` template tag.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(PerformableTagTestCase, self).setUp()
|
||||
self.settings_manager.set(PERFORMABLE_API_KEY='123ABC')
|
||||
|
||||
def test_tag(self):
|
||||
r = self.render_tag('performable', 'performable')
|
||||
self.assertTrue('/performable/pax/123ABC.js' in r, r)
|
||||
|
||||
def test_node(self):
|
||||
r = PerformableNode().render(Context())
|
||||
self.assertTrue('/performable/pax/123ABC.js' in r, r)
|
||||
|
||||
def test_no_api_key(self):
|
||||
self.settings_manager.delete('PERFORMABLE_API_KEY')
|
||||
self.assertRaises(AnalyticalException, PerformableNode)
|
||||
|
||||
def test_wrong_account_number(self):
|
||||
self.settings_manager.set(PERFORMABLE_API_KEY='123AB')
|
||||
self.assertRaises(AnalyticalException, PerformableNode)
|
||||
self.settings_manager.set(PERFORMABLE_API_KEY='123ABCD')
|
||||
self.assertRaises(AnalyticalException, PerformableNode)
|
||||
|
||||
def test_render_internal_ip(self):
|
||||
self.settings_manager.set(ANALYTICAL_INTERNAL_IPS=['1.1.1.1'])
|
||||
req = HttpRequest()
|
||||
req.META['REMOTE_ADDR'] = '1.1.1.1'
|
||||
context = Context({'request': req})
|
||||
r = PerformableNode().render(context)
|
||||
self.assertTrue(r.startswith(
|
||||
'<!-- Performable disabled on internal IP address'), r)
|
||||
self.assertTrue(r.endswith('-->'), r)
|
||||
|
||||
def test_identify(self):
|
||||
self.settings_manager.set(ANALYTICAL_AUTO_IDENTIFY=True)
|
||||
r = PerformableNode().render(Context({'user': User(username='test')}))
|
||||
self.assertTrue('_paq.push(["identify", {identity: "test"}]);' in r, r)
|
||||
|
||||
|
||||
class PerformableEmbedTagTestCase(TagTestCase):
|
||||
"""
|
||||
Tests for the ``performable_embed`` template tag.
|
||||
"""
|
||||
|
||||
def test_tag(self):
|
||||
d = 'example.com'
|
||||
p = 'test'
|
||||
r = self.render_tag('performable', 'performable_embed "%s" "%s"'
|
||||
% (d, p))
|
||||
self.assertTrue(
|
||||
"$f.initialize({'host': 'example.com', 'page': 'test'});" in r,
|
||||
r)
|
||||
|
|
@ -26,11 +26,5 @@ Credits
|
|||
Helping out
|
||||
===========
|
||||
|
||||
If you want to help out with development of django-analytical, by
|
||||
posting detailed bug reports, suggesting new features or other analytics
|
||||
services to support, or doing some development work yourself, please use
|
||||
the `issue tracker`_. If you want to get your hands dirty yourself,
|
||||
great! Clone the repository, make changes and send a pull request.
|
||||
Please do create an issue to discuss your plans.
|
||||
|
||||
.. _`issue tracker`: http://github.com/jcassee/django-analytical/issues
|
||||
.. include:: ../README.rst
|
||||
:start-line: 32
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
========================================
|
||||
Analytics service integration for Django
|
||||
========================================
|
||||
=================
|
||||
django-analytical
|
||||
=================
|
||||
|
||||
The django-analytical application integrates various analytics services
|
||||
into a Django_ project.
|
||||
The django-analytical application integrates analytics services into a
|
||||
Django_ project.
|
||||
|
||||
.. _Django: http://www.djangoproject.com/
|
||||
|
||||
|
|
@ -14,17 +14,9 @@ into a Django_ project.
|
|||
Overview
|
||||
========
|
||||
|
||||
If your want to integrating an analytics service into a Django project,
|
||||
you need to add Javascript tracking code to the project templates.
|
||||
Of course, every service has its own specific installation instructions.
|
||||
Furthermore, you need to include your unique identifiers, which then end
|
||||
up in the templates. This application hides the details of the
|
||||
different analytics services behind a generic interface, and keeps
|
||||
personal information and configuration out of the templates. Its goal
|
||||
is to make basic usage set-up very simple, while allowing advanced users
|
||||
to customize tracking. Each service is set up as recommended by the
|
||||
services themselves, using an asynchronous version of the Javascript
|
||||
code if possible.
|
||||
.. include:: ../README.rst
|
||||
:start-line: 6
|
||||
:end-line: 17
|
||||
|
||||
To get a feel of how django-analytics works, check out the
|
||||
:doc:`tutorial`.
|
||||
|
|
|
|||
|
|
@ -51,13 +51,13 @@ portal ID and domain.
|
|||
Setting the portal ID and domain
|
||||
--------------------------------
|
||||
|
||||
Your HubSpot account has its own portal ID and primary websit, and the
|
||||
:ttag:`hubspot` tag will include them in the rendered Javascript code.
|
||||
You can find the portal ID and domain by going to the *Domains* tab in
|
||||
your HubSpot account. The domain you need to use is listed as *Primary
|
||||
Domain* on that page, and the portal ID can be found in the footer. Set
|
||||
:const:`HUBSPOT_PORTAL_ID` and :const:`HUBSPOT_DOMAIN` in the
|
||||
project :file:`settings.py` file::
|
||||
Your HubSpot account has its own portal ID and primary domain name, and
|
||||
the :ttag:`hubspot` tag will include them in the rendered Javascript
|
||||
code. You can find the portal ID and domain by going to the *Domains*
|
||||
tab in your HubSpot account. The domain you need to use is listed as
|
||||
*Primary Domain* on that page, and the portal ID can be found in the
|
||||
footer. Set :const:`HUBSPOT_PORTAL_ID` and :const:`HUBSPOT_DOMAIN` in
|
||||
the project :file:`settings.py` file::
|
||||
|
||||
HUBSPOT_PORTAL_ID = 'XXXX'
|
||||
HUBSPOT_DOMAIN = 'XXXXXXXX.web101.hubspot.com'
|
||||
|
|
|
|||
|
|
@ -26,9 +26,9 @@ This step is only needed if you are not using the generic
|
|||
:ref:`optimizely-configuration`.
|
||||
|
||||
The Optimizely Javascript code is inserted into templates using a
|
||||
template tag. Load the :mod:`mixpanel` template tag library and insert
|
||||
the :ttag:`optimizely` tag. Because every page that you want to track
|
||||
must have the tag, it is useful to add it to your base template.
|
||||
template tag. Load the :mod:`optimizely` template tag library and
|
||||
insert the :ttag:`optimizely` 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 top of the HTML head::
|
||||
|
||||
{% load optimizely %}
|
||||
|
|
@ -54,7 +54,7 @@ Setting the account number
|
|||
|
||||
Optimizely gives you a unique account number, and the :ttag:`optimizely`
|
||||
tag will include it in the rendered Javascript code. You can find your
|
||||
account number by clicking the `Implementation` link in the top
|
||||
account number by clicking the *Implementation* link in the top
|
||||
right-hand corner of the Optimizely website. A pop-up window will
|
||||
appear containing HTML code looking like this::
|
||||
|
||||
|
|
|
|||
133
docs/services/performable.rst
Normal file
133
docs/services/performable.rst
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
==============================================
|
||||
Performable -- web analytics and landing pages
|
||||
==============================================
|
||||
|
||||
Performable_ provides a platform for inbound marketing, landing pages
|
||||
and web analytics. Its analytics module tracks individual customer
|
||||
interaction, funnel and e-commerce analysis. Landing pages can be
|
||||
created and designed on-line, and integrated with you existing website.
|
||||
|
||||
.. _Performable: http://www.performable.com/
|
||||
|
||||
|
||||
.. performable-installation:
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
To start using the Performable 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 Performable template tags to your templates.
|
||||
This step is only needed if you are not using the generic
|
||||
:ttag:`analytical.*` tags. If you are, skip to
|
||||
:ref:`performable-configuration`.
|
||||
|
||||
The Performable Javascript code is inserted into templates using a
|
||||
template tag. Load the :mod:`performable` template tag library and
|
||||
insert the :ttag:`performable` 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 performable %}
|
||||
...
|
||||
{% performable %}
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
.. _performable-configuration:
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
Before you can use the Performable integration, you must first set your
|
||||
API key.
|
||||
|
||||
|
||||
.. _performable-account-code:
|
||||
|
||||
Setting the API key
|
||||
-------------------
|
||||
|
||||
You Performable account has its own API key, which :ttag:`performable`
|
||||
tag will include it in the rendered Javascript code. You can find your
|
||||
API key on the *Account Settings* page (click 'Account Settings' in the
|
||||
top right-hand corner of your Performable dashboard. Set
|
||||
:const:`PERFORMABLE_API_KEY` in the project :file:`settings.py` file::
|
||||
|
||||
PERFORMABLE_API_KEY = 'XXXXXX'
|
||||
|
||||
If you do not set an API key, the Javascript code will not be rendered.
|
||||
|
||||
|
||||
.. _performable-identity-user:
|
||||
|
||||
Identifying authenticated users
|
||||
-------------------------------
|
||||
|
||||
If your websites identifies visitors, you can pass this information on
|
||||
to Performable so that you can tie survey submissions to customers.
|
||||
By default, the username of an authenticated user is passed to
|
||||
Performable automatically. See :ref:`identifying-visitors`.
|
||||
|
||||
You can also send the visitor identity yourself by adding either the
|
||||
``performable_identity`` or the ``analytical_identity`` variable to
|
||||
the template context. If both variables are set, the former takes
|
||||
precedence. For example::
|
||||
|
||||
context = RequestContext({'performable_identity': identity})
|
||||
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 identify(request):
|
||||
try:
|
||||
return {'performable_identity': 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.
|
||||
|
||||
|
||||
.. _performable-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:`PERFORMABLE_INTERNAL_IPS` setting,
|
||||
the tracking code is commented out. It takes the value of
|
||||
:const:`ANALYTICAL_INTERNAL_IPS` by default (which in turn is
|
||||
:const:`INTERNAL_IPS` by default). See :ref:`identifying-visitors` for
|
||||
important information about detecting the visitor IP address.
|
||||
|
||||
|
||||
.. _performable-embed-page:
|
||||
|
||||
Embedding a landing page
|
||||
========================
|
||||
|
||||
You can embed a Performable landing page in your Django website. The
|
||||
:ttag:`performable_embed` template tag adds the Javascript code to embed
|
||||
the page. It takes two arguments: the hostname and the page ID::
|
||||
|
||||
{% performable_embed HOSTNAME PAGE_ID %}
|
||||
|
||||
To find the hostname and page ID, select :menuselection:`Manage -->
|
||||
Manage Landing Pages` on your Performable dashboard. Select the landing
|
||||
page you want to embed. Look at the URL in your browser address bar; it
|
||||
will look like this::
|
||||
|
||||
http://my.performable.com/s/HOSTNAME/page/PAGE_ID/
|
||||
|
||||
(If you are placing the hostname and page id values in the template, do
|
||||
not forget to enclose them in quotes or they will be considered context
|
||||
variable names.)
|
||||
|
|
@ -9,16 +9,20 @@ their default values.
|
|||
|
||||
.. data:: ANALYTICAL_AUTO_IDENTIFY
|
||||
|
||||
Default: ``True``
|
||||
Default: ``True``
|
||||
|
||||
Automatically identify logged in users by their username. See
|
||||
:ref:`identifying-visitors`.
|
||||
Automatically identify logged in users by their username. See
|
||||
:ref:`identifying-visitors`.
|
||||
|
||||
|
||||
.. data:: ANALYTICAL_INTERNAL_IPS
|
||||
|
||||
Default: :data:`INTERNAL_IPS`
|
||||
Default: :data:`INTERNAL_IPS`
|
||||
|
||||
A list or tuple of internal IP addresses. Tracking code will be
|
||||
commented out for visitors from any of these addresses. See
|
||||
:ref:`internal-ips`.
|
||||
A list or tuple of internal IP addresses. Tracking code will be
|
||||
commented out for visitors from any of these addresses. You can
|
||||
configure this setting for each service individually by substituting
|
||||
``ANALYTICAL`` for the upper-case service name. For example, set
|
||||
``GOOGLE_ANALYTICS_INTERNAL_IPS`` to configure for Google Analytics.
|
||||
|
||||
See :ref:`internal-ips`.
|
||||
|
|
|
|||
3
setup.py
3
setup.py
|
|
@ -43,7 +43,7 @@ setup(
|
|||
name = 'django-analytical',
|
||||
version = analytical.__version__,
|
||||
license = analytical.__license__,
|
||||
description = 'Analytics services for Django projects',
|
||||
description = 'Analytics service integration for Django projects',
|
||||
long_description = read('README.rst'),
|
||||
author = analytical.__author__,
|
||||
author_email = analytical.__email__,
|
||||
|
|
@ -51,6 +51,7 @@ setup(
|
|||
'analytical',
|
||||
'analytical.templatetags',
|
||||
'analytical.tests',
|
||||
'analytical.tests.templatetags',
|
||||
],
|
||||
keywords = ['django', 'analytics'],
|
||||
classifiers = [
|
||||
|
|
|
|||
Loading…
Reference in a new issue