Add basic click & view tracking
parent
5b3b1a843d
commit
bf7cb1df3c
|
@ -1,5 +1,9 @@
|
|||
import random
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
|
||||
DISPLAY_CHOICES = (
|
||||
('doc', 'Documentation Pages'),
|
||||
|
@ -50,9 +54,26 @@ class SupporterPromo(models.Model):
|
|||
|
||||
def as_dict(self):
|
||||
"A dict respresentation of this for JSON encoding"
|
||||
image_url = reverse(
|
||||
'donate_view_proxy',
|
||||
kwargs={'promo_id': self.pk, 'hash': random.random()}
|
||||
)
|
||||
link_url = reverse(
|
||||
'donate_click_proxy',
|
||||
kwargs={'promo_id': self.pk}
|
||||
)
|
||||
return {
|
||||
'id': self.analytics_id,
|
||||
'text': self.text,
|
||||
'link': self.link,
|
||||
'image': self.image,
|
||||
'link': link_url,
|
||||
'image': image_url,
|
||||
}
|
||||
|
||||
|
||||
class SupporterImpressions(models.Model):
|
||||
promo = models.ForeignKey(SupporterPromo, related_name='impressions',
|
||||
blank=True, null=True)
|
||||
date = models.DateField(_('Date'))
|
||||
offers = models.IntegerField(_('Offer'), default=0)
|
||||
views = models.IntegerField(_('View'), default=0)
|
||||
clicks = models.IntegerField(_('Clicks'), default=0)
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
import json
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
from django_dynamic_fixture import get
|
||||
|
||||
from .models import SupporterPromo
|
||||
from readthedocs.projects.models import Project
|
||||
|
||||
|
||||
class PromoTests(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.promo = get(SupporterPromo,
|
||||
slug='promo-slug',
|
||||
link='http://example.com',
|
||||
image='http://media.example.com/img.png')
|
||||
|
||||
def test_clicks(self):
|
||||
resp = self.client.get('http://testserver/sustainability/click/%s/' % self.promo.id)
|
||||
self.assertEqual(resp._headers['location'][1], 'http://example.com')
|
||||
promo = SupporterPromo.objects.get(pk=self.promo.pk)
|
||||
impression = promo.impressions.first()
|
||||
self.assertEqual(impression.clicks, 1)
|
||||
|
||||
def test_views(self):
|
||||
resp = self.client.get('http://testserver/sustainability/click/%s/random_hash/' % self.promo.id)
|
||||
self.assertEqual(resp._headers['location'][1], 'http://media.example.com/img.png')
|
||||
promo = SupporterPromo.objects.get(pk=self.promo.pk)
|
||||
impression = promo.impressions.first()
|
||||
self.assertEqual(impression.views, 1)
|
||||
|
||||
|
||||
class FooterTests(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.promo = get(SupporterPromo,
|
||||
live=True,
|
||||
slug='promo-slug',
|
||||
display_type='doc',
|
||||
link='http://example.com',
|
||||
image='http://media.example.com/img.png')
|
||||
self.pip = get(Project, slug='pip')
|
||||
|
||||
def test_footer(self):
|
||||
r = self.client.get(
|
||||
'/api/v2/footer_html/?project=pip&version=latest&page=index'
|
||||
)
|
||||
resp = json.loads(r.content)
|
||||
self.assertEqual(resp['promo_data']['link'], '/sustainability/click/%s/' % self.promo.pk)
|
|
@ -3,6 +3,7 @@ from django.conf.urls import url, patterns, include
|
|||
from .views import DonateCreateView
|
||||
from .views import DonateListView
|
||||
from .views import DonateSuccessView
|
||||
from .views import click_proxy, view_proxy
|
||||
|
||||
|
||||
urlpatterns = patterns(
|
||||
|
@ -10,4 +11,6 @@ urlpatterns = patterns(
|
|||
url(r'^$', DonateListView.as_view(), name='donate'),
|
||||
url(r'^contribute/$', DonateCreateView.as_view(), name='donate_add'),
|
||||
url(r'^contribute/thanks$', DonateSuccessView.as_view(), name='donate_success'),
|
||||
url(r'^click/(?P<promo_id>\d+)/(?P<hash>.+)/$', view_proxy, name='donate_view_proxy'),
|
||||
url(r'^click/(?P<promo_id>\d+)/$', click_proxy, name='donate_click_proxy'),
|
||||
)
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
"""Donation views"""
|
||||
|
||||
import logging
|
||||
import datetime
|
||||
|
||||
from django.views.generic import TemplateView
|
||||
from django.conf import settings
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.db.models import F
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.shortcuts import redirect
|
||||
|
||||
from vanilla import CreateView, ListView
|
||||
from redis import Redis, ConnectionError
|
||||
import pytz
|
||||
|
||||
from readthedocs.payments.mixins import StripeMixin
|
||||
|
||||
from .models import Supporter
|
||||
from .models import Supporter, SupporterPromo
|
||||
from .forms import SupporterForm
|
||||
from .mixins import DonateProgressMixin
|
||||
|
||||
|
@ -54,3 +61,51 @@ class DonateListView(DonateProgressMixin, ListView):
|
|||
|
||||
def get_template_names(self):
|
||||
return [self.template_name]
|
||||
|
||||
|
||||
def click_proxy(request, promo_id, redis=False):
|
||||
promo = SupporterPromo.objects.get(pk=promo_id)
|
||||
date = pytz.utc.localize(datetime.datetime.utcnow())
|
||||
day = datetime.datetime(
|
||||
year=date.year,
|
||||
month=date.month,
|
||||
day=date.day,
|
||||
tzinfo=pytz.utc,
|
||||
)
|
||||
if redis:
|
||||
redis = Redis.from_url(settings.BROKER_URL)
|
||||
redis.incr('{slug}-{year}-{month}-{day}-clicks'.format(
|
||||
slug=promo.analytics_id,
|
||||
year=day.year,
|
||||
month=day.month,
|
||||
day=day.day,
|
||||
))
|
||||
else:
|
||||
impression, _ = promo.impressions.get_or_create(date=day)
|
||||
impression.clicks = F('clicks') + 1
|
||||
impression.save()
|
||||
return redirect(promo.link)
|
||||
|
||||
|
||||
def view_proxy(request, promo_id, hash, redis=False):
|
||||
promo = SupporterPromo.objects.get(pk=promo_id)
|
||||
date = pytz.utc.localize(datetime.datetime.utcnow())
|
||||
day = datetime.datetime(
|
||||
year=date.year,
|
||||
month=date.month,
|
||||
day=date.day,
|
||||
tzinfo=pytz.utc,
|
||||
)
|
||||
if redis:
|
||||
redis = Redis.from_url(settings.BROKER_URL)
|
||||
redis.incr('{slug}-{year}-{month}-{day}-views'.format(
|
||||
slug=promo.analytics_id,
|
||||
year=day.year,
|
||||
month=day.month,
|
||||
day=day.day,
|
||||
))
|
||||
else:
|
||||
impression, _ = promo.impressions.get_or_create(date=day)
|
||||
impression.views = F('views') + 1
|
||||
impression.save()
|
||||
return redirect(promo.image)
|
||||
|
|
Loading…
Reference in New Issue