From 1165fdf22ff948b2742fa0e98d7d79be3eec8976 Mon Sep 17 00:00:00 2001 From: Gleb Date: Mon, 13 Feb 2017 15:56:10 +0200 Subject: [PATCH 1/2] #16 / reworking google analytics resource download tracking --- ckanext/googleanalytics/controller.py | 26 ------------ ckanext/googleanalytics/plugin.py | 57 ++++++++++++++++++++++++--- 2 files changed, 51 insertions(+), 32 deletions(-) diff --git a/ckanext/googleanalytics/controller.py b/ckanext/googleanalytics/controller.py index a02413c..1a743a5 100644 --- a/ckanext/googleanalytics/controller.py +++ b/ckanext/googleanalytics/controller.py @@ -116,29 +116,3 @@ class GAApiController(ApiController): self._post_analytics(c.user, register, "search", id) return ApiController.search(self, ver, register) - - -class GAResourceController(PackageController): - # intercept API calls to record via google analytics - def _post_analytics( - self, user, request_obj_type, request_function, request_id): - if config.get('googleanalytics.id'): - data_dict = { - "v": 1, - "tid": config.get('googleanalytics.id'), - "cid": hashlib.md5(user).hexdigest(), - # customer id should be obfuscated - "t": "event", - "dh": c.environ['HTTP_HOST'], - "dp": c.environ['PATH_INFO'], - "dr": c.environ.get('HTTP_REFERER', ''), - "ec": "CKAN Resource Download Request", - "ea": request_obj_type+request_function, - "el": request_id, - } - plugin.GoogleAnalyticsPlugin.analytics_queue.put(data_dict) - - def resource_download(self, id, resource_id, filename=None): - self._post_analytics(c.user, "Resource", "Download", resource_id) - return PackageController.resource_download(self, id, resource_id, - filename) diff --git a/ckanext/googleanalytics/plugin.py b/ckanext/googleanalytics/plugin.py index 039e582..c643b14 100644 --- a/ckanext/googleanalytics/plugin.py +++ b/ckanext/googleanalytics/plugin.py @@ -5,21 +5,56 @@ import commands import dbutil import paste.deploy.converters as converters import pylons +from ckan.lib.base import c import ckan.lib.helpers as h import ckan.plugins as p import gasnippet from routes.mapper import SubMapper, Mapper as _Mapper +from pylons import config import urllib2 +import importlib +import hashlib import threading import Queue log = logging.getLogger('ckanext.googleanalytics') + +def _post_analytics( + user, request_obj_type, request_function, request_id): + if config.get('googleanalytics.id'): + data_dict = { + "v": 1, + "tid": config.get('googleanalytics.id'), + "cid": hashlib.md5(c.user).hexdigest(), + # customer id should be obfuscated + "t": "event", + "dh": c.environ['HTTP_HOST'], + "dp": c.environ['PATH_INFO'], + "dr": c.environ.get('HTTP_REFERER', ''), + "ec": "CKAN Resource Download Request", + "ea": request_obj_type + request_function, + "el": request_id, + } + GoogleAnalyticsPlugin.analytics_queue.put(data_dict) + + +def post_analytics_decorator(func): + + def func_wrapper(cls, id, resource_id, filename): + _post_analytics(c.user, "Resource", "Download", resource_id) + + return func(cls, id, resource_id, filename) + + return func_wrapper + + class GoogleAnalyticsException(Exception): pass + class AnalyticsPostThread(threading.Thread): """Threaded Url POST""" def __init__(self, queue): @@ -163,12 +198,6 @@ class GoogleAnalyticsPlugin(p.SingletonPlugin): m.connect('/rest/{register}/{id}', action='update', conditions=POST) m.connect('/rest/{register}/{id}', action='delete', conditions=DELETE) - with SubMapper(map, controller='ckanext.googleanalytics.controller:GAResourceController') as m: - m.connect('/dataset/{id}/resource/{resource_id}/download', - action='resource_download') - m.connect('/dataset/{id}/resource/{resource_id}/download/{filename}', - action='resource_download') - return map def after_map(self, map): @@ -177,6 +206,7 @@ class GoogleAnalyticsPlugin(p.SingletonPlugin): See IRoutes. ''' + self.modify_resource_download_route(map) map.redirect("/analytics/package/top", "/analytics/dataset/top") map.connect( 'analytics', '/analytics/dataset/top', @@ -209,3 +239,18 @@ class GoogleAnalyticsPlugin(p.SingletonPlugin): } return p.toolkit.render_snippet( 'googleanalytics/snippets/googleanalytics_header.html', data) + + def modify_resource_download_route(self, map): + '''Modifies resource_download method in related controller + to attach GA tracking code. + ''' + + if '_routenames' in map.__dict__: + if 'resource_download' in map.__dict__['_routenames']: + route_data = map.__dict__['_routenames']['resource_download'].__dict__ + route_controller = route_data['defaults']['controller'].split( + ':') + module = importlib.import_module(route_controller[0]) + controller_class = getattr(module, route_controller[1]) + controller_class.resource_download = post_analytics_decorator( + controller_class.resource_download) From b7238dc8c8f1874186c0dabe595a6921ce5c89ab Mon Sep 17 00:00:00 2001 From: Gleb Date: Tue, 14 Feb 2017 10:04:34 +0200 Subject: [PATCH 2/2] #16 / ga works with default uploader --- ckanext/googleanalytics/controller.py | 1 - ckanext/googleanalytics/plugin.py | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ckanext/googleanalytics/controller.py b/ckanext/googleanalytics/controller.py index 1a743a5..f375c05 100644 --- a/ckanext/googleanalytics/controller.py +++ b/ckanext/googleanalytics/controller.py @@ -15,7 +15,6 @@ from webob.multidict import UnicodeMultiDict from paste.util.multidict import MultiDict from ckan.controllers.api import ApiController -from ckan.controllers.package import PackageController log = logging.getLogger('ckanext.googleanalytics') diff --git a/ckanext/googleanalytics/plugin.py b/ckanext/googleanalytics/plugin.py index c643b14..58959c1 100644 --- a/ckanext/googleanalytics/plugin.py +++ b/ckanext/googleanalytics/plugin.py @@ -11,6 +11,7 @@ import ckan.plugins as p import gasnippet from routes.mapper import SubMapper, Mapper as _Mapper from pylons import config +from ckan.controllers.package import PackageController import urllib2 import importlib @@ -254,3 +255,7 @@ class GoogleAnalyticsPlugin(p.SingletonPlugin): controller_class = getattr(module, route_controller[1]) controller_class.resource_download = post_analytics_decorator( controller_class.resource_download) + else: + # If no custom uploader applied, use the default one + PackageController.resource_download = post_analytics_decorator( + PackageController.resource_download)