Skip to content

Commit

Permalink
📈(funmooc) use web analytics context
Browse files Browse the repository at this point in the history
Richie provides now a web_analytics context. So we do not need to add it to
marking_context anymore. Furthermore we refactor the way tarteaucitron includes
or not the active tracker.
  • Loading branch information
jbpenrath committed Sep 30, 2021
1 parent bc83dcf commit 5fa2bb6
Show file tree
Hide file tree
Showing 8 changed files with 218 additions and 188 deletions.
1 change: 1 addition & 0 deletions sites/funmooc/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Versioning](https://semver.org/spec/v2.0.0.html).

### Changed

- Remove `MARKETING_CONTEXT` and use `WEB_ANALYTICS_*` context instead
- Upgrade richie to 2.8.1
- Rename `LTI_TEST_*` settings to `LTI_*` as "TEST" does not make sense here

Expand Down
39 changes: 1 addition & 38 deletions sites/funmooc/src/backend/base/context_processors.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,24 @@
"""
import json

from django.conf import settings
from django.db.models import Q
from django.utils.translation import get_language_from_request

from cms.models import Page
from richie.apps.courses.models import Organization


def site_metas(request):
"""
Context processor to add all information required by frontend scripts.
"""

page = request.current_page or None
language = get_language_from_request(request, check_path=True)

def get_organizations():
"""
Return organization attached to the page and
organizations linked to the current page via an organization plugin in any of the
placeholders on the page
"""
return list(
Organization.objects.filter(
Q(
extended_object__organization_plugins__cmsplugin_ptr__language=language,
extended_object__organization_plugins__cmsplugin_ptr__placeholder__page=page,
)
| Q(
extended_object__exact=page,
),
extended_object__title_set__published=True,
)
.distinct()
.values_list("code", flat=True)
)

def get_privacy_policy_uri():
"""
Check if a privacy policy page is published in the request language
then return its url.
"""

try:
page = Page.objects.get(
publisher_is_draft=False,
Expand All @@ -65,19 +41,6 @@ def get_privacy_policy_uri():
},
}
),
"MARKETING_CONTEXT": json.dumps(
{
"xiti": {
"level2": str(page.node.get_root().pk),
"organizations": get_organizations() if not page.is_home else [],
"site_id": settings.MARKETING_SITE_ID,
}
if getattr(settings, "MARKETING_SITE_ID", None)
and page is not None
and page.publisher_is_draft is False
else {},
}
),
}

return context
58 changes: 21 additions & 37 deletions sites/funmooc/src/backend/base/static/funmooc/js/tarteaucitron.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,45 +4,29 @@
var privacyUrl = window.__funmooc_context__.privacy.tarteaucitron.privacyUrl || '';

tarteaucitron.init({
"AcceptAllCta": true, /* Show the accept all button when highPrivacy on */
"adblocker": false, /* Show a Warning if an adblocker is detected */
"bodyPosition": "top", /* Position in the html */
"closePopup": true, /* Show a close X on the banner */
AcceptAllCta: true /* Show the accept all button when highPrivacy on */,
adblocker: false /* Show a Warning if an adblocker is detected */,
bodyPosition: 'top' /* Position in the html */,
closePopup: true /* Show a close X on the banner */,
// "cookieDomain": ".my-multisite-domaine.fr", /* Shared cookie for multisite */
"cookieName": "tarteaucitron", /* Cookie name */
"cookieslist": false, /* Show the cookie list */
"DenyAllCta": true, /* Show the deny all button */
"handleBrowserDNTRequest": true, /* If Do Not Track == 1, disallow all */
"hashtag": "#tarteaucitron", /* Open the panel with this hashtag */
"highPrivacy": true, /* Disable auto consent */
"iconPosition": "BottomRight", /* BottomRight, BottomLeft, TopRight and TopLeft */
"mandatory": true, /* Show a message about mandatory cookies */
"moreInfoLink": true, /* Show more info link */
"orientation": "bottom", /* Banner position (top - bottom) */
"privacyUrl": privacyUrl, /* Privacy policy url */
"readmoreLink": "", /* Change the default readmore link */
"removeCredit": true, /* Remove credit link */
"showAlertSmall": false, /* Show the small banner on bottom right */
"showIcon": false, /* Show cookie icon to manage cookies */
"useExternalCss": false, /* If false, the tarteaucitron.css file will be loaded */
"useExternalJs": false, /* If false, the tarteaucitron.js file will be loaded */
cookieName: 'tarteaucitron' /* Cookie name */,
cookieslist: false /* Show the cookie list */,
DenyAllCta: true /* Show the deny all button */,
handleBrowserDNTRequest: true /* If Do Not Track == 1, disallow all */,
hashtag: '#tarteaucitron' /* Open the panel with this hashtag */,
highPrivacy: true /* Disable auto consent */,
iconPosition: 'BottomRight' /* BottomRight, BottomLeft, TopRight and TopLeft */,
mandatory: true /* Show a message about mandatory cookies */,
moreInfoLink: true /* Show more info link */,
orientation: 'bottom' /* Banner position (top - bottom) */,
privacyUrl: privacyUrl /* Privacy policy url */,
readmoreLink: '' /* Change the default readmore link */,
removeCredit: true /* Remove credit link */,
showAlertSmall: false /* Show the small banner on bottom right */,
showIcon: false /* Show cookie icon to manage cookies */,
useExternalCss: false /* If false, the tarteaucitron.css file will be loaded */,
useExternalJs: false /* If false, the tarteaucitron.js file will be loaded */,
});

tarteaucitron.job = tarteaucitron.job || [];

// If xiti is used, add this service
if (!!window.__funmooc_context__.marketing.xiti.site_id) {
tarteaucitron.services.xiti = {
key: 'xiti',
type: 'analytic',
name: 'Xiti',
uri: 'https://www.atinternet.com/societe/rgpd-et-vie-privee/',
needConsent: true,
safeanalytic: true,
cookies: ['atid', 'idrxvr', 'atuserid', 'atidx', 'atidvisitor'],
}

tarteaucitron.job.push('xiti');
}
})();

196 changes: 112 additions & 84 deletions sites/funmooc/src/backend/base/static/funmooc/js/xiti.js
Original file line number Diff line number Diff line change
@@ -1,53 +1,80 @@
(function () {
/**
* Deserialize a context analytic dimension
*
* @param dimension - string with items joined by ' | '
* @return data
* - undefined if the dimension string was empty
* - A single value if the dimension cannot be split
* - An array of value if dimension has been split
*/
function deserialize(dimension) {
const data = dimension.split(' | ');
if (data.length === 1) {
if (!data[0].trim()) return undefined;
return data[0];
}
return data;
}

/**
*
* An object to initialize then use AT Internet SmartTag.
*
* @param metadata - analytics context
*
* - id: AT Internet site id to identify the site on Analytics Suite
* - provider: 'xiti',
* - dimensions: some serialized data related to the current page
* + course_code
* + course_runs_resource_links
* + course_runs_titles
* + organizations_codes
* + page_title
* + root_page_id: level2
*
*/
function SmartTag(metadata) {
/**
*
* SmartTag
* An object to install, initialize then use Xiti SmartTag.
*
* @param metadata
* site_id Xiti id to identify the site on Analytics Suite
* level2 the level2 of the page - an id used by Xiti to group records by root pages
* organizations - list of all organizations included on the page
*
*/
this.data = null;
this.level2 = metadata.level2;
this.organizations = metadata.organizations;
this.siteId = metadata.site_id;
this.level2 = metadata.dimensions.root_page_id;
this.organizations = deserialize(metadata.dimensions.organizations_codes);
this.siteId = metadata.id;
this.tag = null;

/* Populate the data object sent to Xiti on dispatch
It includes level2, name and chapters
To get name and chapters we split the url pathname "/"
name is the first element of this destructuring
chapters are the remaining elements
*/
/**
* Populate the data object sent to Xiti on dispatch.
* It includes level2, name and chapters
*
* To get name and chapters we split the url pathname "/"
* name is the first element of this destructuring
* chapters are the remaining elements
*/
this.populateData = function () {
var self = this;
var chapters = location.pathname
.split('/')
.filter(function (slug) { return slug.length > 0 })
.slice(1) // Remove lang
.filter(function (slug) {
return slug.length > 0;
})
.slice(1); // Remove lang

var name = chapters.shift();

this.data = {
level2: this.level2,
name: name || '/',
}
};

chapters.forEach(function (chapter, index) {
self.data["chapter" + (index + 1)] = '[' + chapter + ']';
self.data['chapter' + (index + 1)] = '[' + chapter + ']';
});
};

/* Dispatch data on page load
Set customVars, customObject and internalSearch if it is relevant
then dispatch a record.
*/
/**
* Dispatch data on page load
* Set customVars, customObject and internalSearch if it is relevant
* then dispatch a record.
*/
this.dispatch = function () {
// Detail language
var lang = (document.documentElement.lang || '-').split('-')[0].toLowerCase();
Expand All @@ -56,10 +83,15 @@
}

// Detail organizations related to the page
if (this.organizations.length > 0) {
var serializedOrganizations = '[' + this.organizations.map(function (organization) {
return '"' + organization + '"';
}).toString() + ']';
if (this.organizations && this.organizations.length > 0) {
var serializedOrganizations =
'[' +
this.organizations
.map(function (organization) {
return '"' + organization + '"';
})
.toString() +
']';
this.tag.setProp('a:s:organizations', serializedOrganizations, true);
}

Expand All @@ -72,56 +104,24 @@
}

// Dispatch data
this.tag.page.set(this.data)
this.tag.page.set(this.data);
this.tag.dispatch();
}


/* Instantiate the Xiti tag
};

Check if ATInternet exists then create a new tag.
*/
/**
* Instantiate the Xiti tag
* Check if ATInternet exists then create a new tag.
*/
this.createTag = function () {
if (ATInternet) {
this.tag = new ATInternet.Tracker.Tag({ site: this.siteId, secure: true });
}
}

/* Initialize SmartTag
Load Xiti scripts then dispatch a record and add click listeners on buttons
*/
this.init = function () {
var self = this;
this.load(function () {
self.dispatch();
self.spyClickOnButtons();
})
}

/* Load Xiti scripts on the page
Dynamicaly load scripts required by Xiti only if needed
*/
this.load = function (onload) {
var self = this;
var script = document.createElement('script');
script.type = "text/javascript";
script.async = true;
script.onload = function () {
self.createTag();
self.populateData();
onload && onload();
};
script.onerror = function (error) { throw error };
script.src = "https://tag.aticdn.net/" + this.siteId + "/smarttag.js"
document.body.append(script)
};

/* Add click event listeners on all buttons on the page
Send a record each time a visitor click on an action button on the page.
*/
/**
* Add click event listeners on all buttons on the page.
* Send a record each time a visitor click on an action button on the page.
*/
this.spyClickOnButtons = function () {
var self = this;

Expand All @@ -137,16 +137,44 @@
self.tag.click.send(parameters);
}

document.getElementsByTagName('button').forEach(function ($button) {
// Some browsers do not implement `HTMLCollection.forEach` method
// so we transform HTMLCollection into an Array
var $buttons = [].slice.call(document.getElementsByTagName('button'));
$buttons.forEach(($button) => {
$button.addEventListener('click', spyClick, false);
});
}
}
};

// Ensure that Xiti is configured and user does not rejected Xiti cookies
if (!!window.__funmooc_context__.marketing.xiti.site_id && !tarteaucitron.cookie.read().includes('xiti=false')) {
var smartTag = new SmartTag(__funmooc_context__.marketing.xiti);
smartTag.init();
/**
* Initialize SmartTag
*
* Create smartTag, populate data then dispatch a record
* and add click listeners on buttons
*/
this.init = function () {
this.createTag();
this.populateData();
this.dispatch();
this.spyClickOnButtons();
};
}
})();

var context = window.__funmooc_context__.analytics;
tarteaucitron.services.xitiFun = {
key: 'xiti',
type: 'analytic',
name: 'Xiti',
uri: 'https://www.atinternet.com/societe/rgpd-et-vie-privee/',
needConsent: false,
cookies: ['atid', 'idrxvr', 'atuserid', 'atidx', 'atidvisitor'],
js: function () {
var smarttag_url = 'https://tag.aticdn.net/' + context.id + '/smarttag.js';
function onLoad() {
var smartTag = new SmartTag(context);
smartTag.init();
}
tarteaucitron.addScript(smarttag_url, '', onLoad);
},
};
tarteaucitron.job.push('xitiFun');
})();
Loading

0 comments on commit 5fa2bb6

Please sign in to comment.