Add report action
This commit is contained in:
parent
86ec2858a5
commit
67b599ce1a
|
@ -49,7 +49,6 @@ jobs:
|
|||
- uses: actions/checkout@v2
|
||||
- name: Install requirements
|
||||
run: |
|
||||
pip install -r requirements.txt
|
||||
pip install -r dev-requirements.txt
|
||||
pip install -e .
|
||||
# Replace default path to CKAN core config file with the one on the container
|
||||
|
|
|
@ -11,9 +11,13 @@ groups:
|
|||
|
||||
- key: googleanalytics.account
|
||||
|
||||
- key: googleanalytics.profile_id
|
||||
|
||||
- key: googleanalytics.domain
|
||||
default: auto
|
||||
|
||||
- key: googleanalytics.credentials.path
|
||||
|
||||
- key: googleanalytics.fields
|
||||
default: "{}"
|
||||
|
||||
|
|
|
@ -1,44 +1,35 @@
|
|||
import httplib2
|
||||
from apiclient.discovery import build
|
||||
from oauth2client.service_account import ServiceAccountCredentials
|
||||
|
||||
from ckanext.googleanalytics import utils
|
||||
|
||||
|
||||
def _prepare_credentials(credentials_filename):
|
||||
"""
|
||||
Either returns the user's oauth credentials or uses the credentials
|
||||
file to generate a token (by forcing the user to login in the browser)
|
||||
"""
|
||||
scope = ["https://www.googleapis.com/auth/analytics.readonly"]
|
||||
credentials = ServiceAccountCredentials.from_json_keyfile_name(
|
||||
credentials_filename, scopes=scope
|
||||
)
|
||||
return credentials
|
||||
from . import utils
|
||||
|
||||
|
||||
def init_service(credentials_file):
|
||||
"""
|
||||
Given a file containing the user's oauth token (and another with
|
||||
credentials in case we need to generate the token) will return a
|
||||
service object representing the analytics API.
|
||||
"""
|
||||
http = httplib2.Http()
|
||||
"""Get a service that communicates to a Google API."""
|
||||
scope = ["https://www.googleapis.com/auth/analytics.readonly"]
|
||||
credentials = ServiceAccountCredentials.from_json_keyfile_name(
|
||||
credentials_file, scopes=scope
|
||||
)
|
||||
|
||||
credentials = _prepare_credentials(credentials_file)
|
||||
http = credentials.authorize(http) # authorize the http object
|
||||
|
||||
return build("analytics", "v3", http=http)
|
||||
return build("analytics", "v3", credentials=credentials)
|
||||
|
||||
|
||||
def get_profile_id(service):
|
||||
"""
|
||||
"""Get static profile ID or fetch one from the service.
|
||||
|
||||
Get the profile ID for this user and the service specified by the
|
||||
'googleanalytics.id' configuration option. This function iterates
|
||||
over all of the accounts available to the user who invoked the
|
||||
service to find one where the account name matches (in case the
|
||||
user has several).
|
||||
|
||||
If not user configured, the first account is used
|
||||
"""
|
||||
|
||||
profile_id = utils.config_profile_id()
|
||||
if profile_id:
|
||||
return profile_id
|
||||
|
||||
accounts = service.management().accounts().list().execute()
|
||||
|
||||
if not accounts.get("items"):
|
||||
|
@ -46,14 +37,9 @@ def get_profile_id(service):
|
|||
accountName = utils.config_account()
|
||||
webPropertyId = utils.config_id()
|
||||
for acc in accounts.get("items"):
|
||||
if acc.get("name") == accountName:
|
||||
if not accountName or acc.get("name") == accountName:
|
||||
accountId = acc.get("id")
|
||||
|
||||
# TODO: check, whether next line is doing something useful.
|
||||
service.management().webproperties().list(
|
||||
accountId=accountId
|
||||
).execute()
|
||||
|
||||
profiles = (
|
||||
service.management()
|
||||
.profiles()
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
header_code = """
|
||||
<script type="text/javascript">
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', '%s']);
|
||||
_gaq.push(['_setDomainName', '%s']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
(function() {
|
||||
var ga = document.createElement('script');
|
||||
ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ?
|
||||
'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
</script>
|
||||
"""
|
||||
|
||||
footer_code = """
|
||||
<script type="text/javascript" src="%s"></script>
|
||||
"""
|
||||
|
||||
download_style = """
|
||||
<style type="text/css">
|
||||
span.downloads-count {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
</style>
|
||||
"""
|
|
@ -4,19 +4,22 @@ import ckan.plugins.toolkit as tk
|
|||
from ckan.logic import validate
|
||||
|
||||
from . import schema
|
||||
from .. import utils
|
||||
from ..model import PackageStats, ResourceStats
|
||||
from ..ga_auth import init_service, get_profile_id
|
||||
|
||||
|
||||
def get_actions():
|
||||
return dict(
|
||||
googleanalytics_package_stats_show=googleanalytics_package_stats_show,
|
||||
googleanalytics_resource_stats_show=googleanalytics_resource_stats_show
|
||||
googleanalytics_package_stats_show=package_stats_show,
|
||||
googleanalytics_resource_stats_show=resource_stats_show,
|
||||
googleanalytics_event_report=event_report,
|
||||
)
|
||||
|
||||
|
||||
@validate(schema.googleanalytics_package_stats_show)
|
||||
@validate(schema.package_stats_show)
|
||||
@tk.side_effect_free
|
||||
def googleanalytics_package_stats_show(context, data_dict):
|
||||
def package_stats_show(context, data_dict):
|
||||
tk.check_access("googleanalytics_package_stats_show", context, data_dict)
|
||||
rec = (
|
||||
context["session"]
|
||||
|
@ -31,9 +34,9 @@ def googleanalytics_package_stats_show(context, data_dict):
|
|||
return rec.for_json(context)
|
||||
|
||||
|
||||
@validate(schema.googleanalytics_resource_stats_show)
|
||||
@validate(schema.resource_stats_show)
|
||||
@tk.side_effect_free
|
||||
def googleanalytics_resource_stats_show(context, data_dict):
|
||||
def resource_stats_show(context, data_dict):
|
||||
tk.check_access("googleanalytics_resource_stats_show", context, data_dict)
|
||||
rec = (
|
||||
context["session"]
|
||||
|
@ -46,3 +49,35 @@ def googleanalytics_resource_stats_show(context, data_dict):
|
|||
raise tk.ObjectNotFound()
|
||||
|
||||
return rec.for_json(context)
|
||||
|
||||
|
||||
@validate(schema.event_report)
|
||||
@tk.side_effect_free
|
||||
def event_report(context, data_dict):
|
||||
tk.check_access("sysadmin", context, data_dict)
|
||||
|
||||
se = init_service(utils.config_credentials())
|
||||
filters = "ga:eventAction=={action};ga:eventCategory=={category}".format(
|
||||
action=data_dict["action"], category=data_dict["category"]
|
||||
)
|
||||
if "label" in data_dict:
|
||||
filters += ";ga:eventLabel=={label}".format(label=data_dict["label"])
|
||||
|
||||
report = (
|
||||
se.data()
|
||||
.ga()
|
||||
.get(
|
||||
ids="ga:{id}".format(id=get_profile_id(se)),
|
||||
dimensions=",".join(data_dict["dimensions"]),
|
||||
metrics=",".join(data_dict["metrics"]),
|
||||
start_date=data_dict["start_date"].date().isoformat(),
|
||||
end_date=data_dict["end_date"].date().isoformat(),
|
||||
filters=filters,
|
||||
)
|
||||
.execute()
|
||||
)
|
||||
|
||||
return {
|
||||
"headers": [h["name"] for h in report["columnHeaders"]],
|
||||
"rows": report["rows"],
|
||||
}
|
||||
|
|
|
@ -5,14 +5,14 @@ from ckan.authz import is_authorized
|
|||
|
||||
def get_auth():
|
||||
return dict(
|
||||
googleanalytics_package_stats_show=googleanalytics_package_stats_show,
|
||||
googleanalytics_resource_stats_show=googleanalytics_resource_stats_show
|
||||
googleanalytics_package_stats_show=package_stats_show,
|
||||
googleanalytics_resource_stats_show=resource_stats_show,
|
||||
)
|
||||
|
||||
|
||||
def googleanalytics_package_stats_show(context, data_dict):
|
||||
def package_stats_show(context, data_dict):
|
||||
return {"success": is_authorized("package_show", context, data_dict)}
|
||||
|
||||
|
||||
def googleanalytics_resource_stats_show(context, data_dict):
|
||||
def resource_stats_show(context, data_dict):
|
||||
return {"success": is_authorized("resource_show", context, data_dict)}
|
||||
|
|
|
@ -2,10 +2,31 @@ from ckan.logic.schema import validator_args
|
|||
|
||||
|
||||
@validator_args
|
||||
def googleanalytics_package_stats_show(not_empty):
|
||||
def package_stats_show(not_empty):
|
||||
return {"id": [not_empty]}
|
||||
|
||||
|
||||
@validator_args
|
||||
def googleanalytics_resource_stats_show(not_empty):
|
||||
def resource_stats_show(not_empty):
|
||||
return {"id": [not_empty]}
|
||||
|
||||
|
||||
@validator_args
|
||||
def event_report(
|
||||
not_empty, isodate, ignore_missing, json_list_or_string, default
|
||||
):
|
||||
return {
|
||||
"start_date": [not_empty, isodate],
|
||||
"end_date": [not_empty, isodate],
|
||||
"category": [not_empty],
|
||||
"action": [not_empty],
|
||||
"label": [ignore_missing, not_empty],
|
||||
"dimensions": [
|
||||
default("ga:eventCategory,ga:eventAction,ga:eventLabel"),
|
||||
json_list_or_string,
|
||||
],
|
||||
"metrics": [
|
||||
default("ga:totalEvents,ga:uniqueEvents,ga:eventValue"),
|
||||
json_list_or_string,
|
||||
],
|
||||
}
|
||||
|
|
|
@ -14,6 +14,14 @@ def config_account():
|
|||
return tk.config.get("googleanalytics.account")
|
||||
|
||||
|
||||
def config_profile_id():
|
||||
return tk.config.get("googleanalytics.profile_id")
|
||||
|
||||
|
||||
def config_credentials():
|
||||
return tk.config.get("googleanalytics.credentials.path")
|
||||
|
||||
|
||||
def config_domain():
|
||||
return tk.config.get("googleanalytics.domain", "auto")
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[metadata]
|
||||
name = ckanext-googleanalytics
|
||||
version = 2.0.8
|
||||
version = 2.1.0
|
||||
description = Add GA tracking and reporting to CKAN instance
|
||||
long_description = file: README.md
|
||||
long_description_content_type = text/markdown
|
||||
|
@ -23,6 +23,7 @@ keywords =
|
|||
# python_requires = >= 3.7
|
||||
install_requires =
|
||||
ckantoolkit
|
||||
google-api-python-client
|
||||
|
||||
packages = find:
|
||||
namespace_packages = ckanext
|
||||
|
|
Loading…
Reference in New Issue