/**
* @class
* @name Page
* @memberof ATInternet.Tracker.Plugins
* @type {function}
* @param tag {object} Instance of the Tag used
* @description
* This plugin allows you to define page tag data :
* <ul>
* <li><b>Page values</b>: to declare name, level2, chapters and custom object parameters.
* <li><b>Site variables</b>: to associate information specific to your activity (interface language, load times, number of articles per page, etc.) with your site.</li>
* <li><b>Page variables</b>: to evaluate the performance of specific pages of your site, notably those offering fields to be filled out.</li>
* <li><b>Dynamic labels</b>: to track the history of a page whose content has been modified.</li>
* <li><b>Tags (or keywords)</b>: to define the theme(s) of the content your users visit.</li>
* <li><b>Custom tree structure</b>: to obtain a completely customised view of all your traffic to completely match your analysis criteria.</li>
* </ul>
* It also processes Campaigns and Internal Search contexts.
* @public
*/
ATInternet.Tracker.Plugins.Page = function (tag) {
'use strict';
var self = this;
var _confPage = {
dynamicLabel: {
properties: ['pageId', 'chapterLabel', 'update'],
parameters: ['pid', 'pchap', 'pidt']
},
customVars: {
properties: ['page', 'site'],
parameters: ['f', 'x']
}
};
var _debug = {
level: 'DEBUG',
messageEnd: 'method ended'
};
/**
* Get page name with chapters.
* @memberof ATInternet.Tracker.Plugins.Page#
* @function
* @param tagObject {object} Page object containing properties to use
* @returns {string}
* @private
*/
var _getFullName = function (tagObject) {
return tag.utils.manageChapters(tagObject, 'chapter', 3) + (tagObject['name'] ? tagObject['name'] : '');
};
/**
* Set context with tag object value or default value.
* @memberof ATInternet.Tracker.Plugins.Page#
* @function
* @param context {object} Context property to process
* @param tagProp {object} Tag property to use
* @param def {string} Default value to use if context value is not defined
* @returns {string}
* @private
*/
var _magic = function (context, tagProp, def) {
if (tagProp) {
context = tagProp;
} else if (!context && typeof def !== 'undefined') {
context = def;
}
return context;
};
/**
* Set value if property has been declared.
* @memberof ATInternet.Tracker.Plugins.Page#
* @function
* @param context {object} Context to process
* @param tagObject {object} Page object containing properties to use
* @param key {string} Name of the property to set
* @private
*/
var _setDeclaredProperty = function (context, tagObject, key) {
if (tagObject.hasOwnProperty(key)) {
context[key] = _magic(context[key], tagObject[key], undefined);
}
};
/**
* Add site or page indicators to a local buffer object or global tag buffer.
* @memberof ATInternet.Tracker.Plugins.Page#
* @function
* @param buffer {object} Local buffer from helper send
* @param object {object} Object from tag or page context
* @param isLocal {boolean} True if local buffer, false otherwise
* @private
*/
var _setIndicatorVariables = function (buffer, object, isLocal) {
if (object) {
var props = _confPage.customVars.properties;
var params = _confPage.customVars.parameters;
for (var i = 0; i < props.length; i++) {
if (object.hasOwnProperty(props[i]) && object[props[i]]) {
for (var p in object[props[i]]) {
if (object[props[i]].hasOwnProperty(p)) {
if (isLocal) {
buffer[params[i] + p] = object[props[i]][p];
} else {
tag.setParam(params[i] + p, object[props[i]][p]);
}
}
}
}
}
}
};
/**
* Add dynamic label to a local buffer object or global tag buffer.
* @memberof ATInternet.Tracker.Plugins.Page#
* @function
* @param buffer {object} Local buffer from helper send
* @param object {object} Object from tag or page context
* @param isLocal {boolean} True if local buffer, false otherwise
* @private
*/
var _setDynamicLabel = function (buffer, object, isLocal) {
if (object) {
var data = tag.utils.manageChapters(object, 'chapter', 3);
if (data) {
object.chapterLabel = data.replace(/::$/gi, '');
}
var props = _confPage.dynamicLabel.properties;
var params = _confPage.dynamicLabel.parameters;
for (var i = 0; i < params.length; i++) {
if (object.hasOwnProperty(props[i])) {
if (isLocal) {
buffer[params[i]] = object[props[i]];
} else {
tag.setParam(params[i], object[props[i]]);
}
}
}
}
};
/**
* Add tags (keywords) to a local buffer object or global tag buffer.
* @memberof ATInternet.Tracker.Plugins.Page#
* @function
* @param buffer {object} Local buffer from helper send
* @param object {object} Object from tag or page context
* @param isLocal {boolean} True if local buffer, false otherwise
* @private
*/
var _setTags = function (buffer, object, isLocal) {
if (object && object.keywords instanceof Array) {
var tabLenght = object.keywords.length;
if (tabLenght > 0) {
var str = '';
for (var i = 0; i < tabLenght; i++) {
str += '[' + object.keywords[i] + ']' + (i < (tabLenght - 1) ? '|' : '');
}
if (isLocal) {
buffer.tag = str;
} else {
tag.setParam('tag', str);
}
}
}
};
/**
* Add a custom tree structure to a local buffer object or global tag buffer.
* @memberof ATInternet.Tracker.Plugins.Page#
* @function
* @param buffer {object} Local buffer from helper send
* @param object {object} Object from tag or page context
* @param isLocal {boolean} True if local buffer, false otherwise
* @private
*/
var _setCustomTreeStructure = function (buffer, object, isLocal) {
if (object) {
var str = '';
var checkCategory = function (property) {
return (property ? property : '0');
};
str += checkCategory(object.category1) + '-';
str += checkCategory(object.category2) + '-';
str += checkCategory(object.category3);
if (isLocal) {
buffer.ptype = str;
} else {
tag.setParam('ptype', str);
}
}
};
/**
* Add campaign variables to a local buffer object or global tag buffer.
* @memberof ATInternet.Tracker.Plugins.Page#
* @function
* @param buffer {object} Local buffer from helper send
* @param object {object} Object from campaign context
* @param isLocal {boolean} True if local buffer, false otherwise
* @private
*/
var _setCampaignsVariables = function (buffer, object, isLocal) {
if (object) {
for (var key in object) {
if (object.hasOwnProperty(key) && typeof object[key] !== 'undefined') {
if (isLocal) {
buffer[key] = object[key];
} else {
tag.setParam(key, object[key]);
}
}
}
}
};
/**
* [Object added by plugin {@link ATInternet.Tracker.Plugins.Page Page}] Tags to associate page and site variables specific to your activity.
* @name customVars
* @memberof ATInternet.Tracker.Tag
* @inner
* @type {object}
* @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#customVars.set}
* @public
*/
tag.customVars = {};
/**
* [Helper added by plugin {@link ATInternet.Tracker.Plugins.Page Page}] Set page and site variables.
* @alias customVars.set
* @memberof! ATInternet.Tracker.Tag#
* @function
* @param tagObject {object} 2 properties : site, page
* @example
* <pre><code class="javascript">tag.customVars.set({
* site: {
* 1: 'site1',
* 5: 'site5',
* 20: 'site20'
* },
* page: {
* 1: 'page1',
* 5: 'page5',
* 20: 'page20'
* }
* });
* </code></pre>
* @public
*/
tag.customVars.set = function (tagObject) {
var _getCustomVars = function (target, source) {
if (target) {
if (source) {
for (var key in source) {
if (source.hasOwnProperty(key)) {
target[key] = ATInternet.Utils.completeFstLevelObj(target[key], source[key], true);
}
}
}
} else {
target = source;
}
return target;
};
var contextPageObject = tag.getContext('page') || {};
//Indicators
contextPageObject.customVars = _getCustomVars(contextPageObject.customVars, tagObject);
tag.setContext('page', contextPageObject);
/* @if debug */
tag.debug('Page:customVars:set', _debug.level, _debug.messageEnd, tagObject);
/* @endif */
};
/**
* [Object added by plugin {@link ATInternet.Tracker.Plugins.Page Page}] Tags to track the history of a page whose content has been modified.
* @name dynamicLabel
* @memberof ATInternet.Tracker.Tag
* @inner
* @type {object}
* @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#dynamicLabel.set}
* @public
*/
tag.dynamicLabel = {};
/**
* [Helper added by plugin {@link ATInternet.Tracker.Plugins.Page Page}] Set dynamic label.
* @alias dynamicLabel.set
* @memberof! ATInternet.Tracker.Tag#
* @function
* @param tagObject {object} 5 properties : pageId, chapter1, chapter2, chapter3, update
* @example
* <pre><code class="javascript">tag.dynamicLabel.set({
* pageId: '123456',
* chapter1: 'mychapter1',
* chapter2: 'mychapter2',
* chapter3: 'mychapter3',
* update: '200910031045'
* });
* </code></pre>
* @public
*/
tag.dynamicLabel.set = function (tagObject) {
var contextPageObject = tag.getContext('page') || {};
contextPageObject.dynamicLabel = ATInternet.Utils.completeFstLevelObj(contextPageObject.dynamicLabel, tagObject, true);
tag.setContext('page', contextPageObject);
/* @if debug */
tag.debug('Page:dynamicLabel:set', _debug.level, _debug.messageEnd, tagObject);
/* @endif */
};
/**
* [Object added by plugin {@link ATInternet.Tracker.Plugins.Page Page}] Tags to define the theme(s) of the content your users visit.
* @name tags
* @memberof ATInternet.Tracker.Tag
* @inner
* @type {object}
* @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#tags.set}
* @public
*/
tag.tags = {};
/**
* [Helper added by plugin {@link ATInternet.Tracker.Plugins.Page Page}] Set keywords.
* @alias tags.set
* @memberof! ATInternet.Tracker.Tag#
* @function
* @param tagObject {object} 1 property : keywords
* @example
* <pre><code class="javascript">tag.tags.set({
* keywords: ['tag','Key']
* });
* </code></pre>
* @public
*/
tag.tags.set = function (tagObject) {
var contextPageObject = tag.getContext('page') || {};
contextPageObject.tags = ATInternet.Utils.completeFstLevelObj(contextPageObject.tags, tagObject, true);
tag.setContext('page', contextPageObject);
/* @if debug */
tag.debug('Page:tags:set', _debug.level, _debug.messageEnd, tagObject);
/* @endif */
};
/**
* [Object added by plugin {@link ATInternet.Tracker.Plugins.Page Page}] Tags to obtain a completely customised view of all your traffic.
* @name customTreeStructure
* @memberof ATInternet.Tracker.Tag
* @inner
* @type {object}
* @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#customTreeStructure.set}
* @public
*/
tag.customTreeStructure = {};
/**
* [Helper added by plugin {@link ATInternet.Tracker.Plugins.Page Page}] Set custom tree structure.
* @alias customTreeStructure.set
* @memberof! ATInternet.Tracker.Tag#
* @function
* @param tagObject {object} 3 properties : category1, category2, category3
* @example
* <pre><code class="javascript">tag.customTreeStructure.set({
* mycategory1: 1,
* mycategory2: 2,
* mycategory3: 3
* });
* </code></pre>
* @public
*/
tag.customTreeStructure.set = function (tagObject) {
var contextPageObject = tag.getContext('page') || {};
contextPageObject.customTreeStructure = ATInternet.Utils.completeFstLevelObj(contextPageObject.customTreeStructure, tagObject, true);
tag.setContext('page', contextPageObject);
/* @if debug */
tag.debug('Page:customTreeStructure:set', _debug.level, _debug.messageEnd, tagObject);
/* @endif */
};
/**
* [Object added by plugin {@link ATInternet.Tracker.Plugins.Page Page}] Tags to manage a page.
* @name page
* @memberof ATInternet.Tracker.Tag
* @inner
* @type {object}
* @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#page.set}
* @property {function} send Tag helper, see details here {@link ATInternet.Tracker.Tag#page.send}
* @property {function} reset Tag helper, see details here {@link ATInternet.Tracker.Tag#page.reset}
* @public
*/
tag.page = {};
/**
* [Helper added by plugin {@link ATInternet.Tracker.Plugins.Page Page}] Reset page context.
* @alias page.reset
* @memberof! ATInternet.Tracker.Tag#
* @function
* @example
* <pre><code class="javascript">tag.page.reset();
* </code></pre>
* @public
*/
tag.page.reset = function () {
tag.delContext('page');
/* @if debug */
tag.debug('Page:page:reset', _debug.level, _debug.messageEnd);
/* @endif */
};
/**
* [Helper added by plugin {@link ATInternet.Tracker.Plugins.Page Page}] Set page properties.
* @alias page.set
* @memberof! ATInternet.Tracker.Tag#
* @function
* @param tagObject {object} 5 properties : name, chapter1, chapter2, chapter3, customObject
* @example
* <pre><code class="javascript">tag.page.set({
* name: 'pageName',
* chapter1: 'mychapter1',
* chapter2: 'mychapter2',
* chapter3: 'mychapter3',
* customObject: {
* one: 1,
* two: 2
* }
* });
* </code></pre>
* @public
*/
tag.page.set = function (tagObject) {
tagObject = tagObject || {};
tag.dispatchSubscribe('page');
var contextPageObject = tag.getContext('page') || {};
contextPageObject.name = _magic(contextPageObject.name, tagObject.name, '');
contextPageObject.level2 = _magic(contextPageObject.level2, tagObject.level2, '');
//Cas particulier: Dans le cas des chapitres, on ajoute les propriétés dans le contexte de page ssi elles ont été déclarées explicitement par l'utilisateur.
//Explication: La méthode Utils de gestion des chapitres créée un chapitre vide si le paramètre existe et que sa valeur est undefined.
_setDeclaredProperty(contextPageObject, tagObject, 'chapter1');
_setDeclaredProperty(contextPageObject, tagObject, 'chapter2');
_setDeclaredProperty(contextPageObject, tagObject, 'chapter3');
//customObject
contextPageObject.customObject = ATInternet.Utils.completeFstLevelObj(contextPageObject.customObject, tagObject.customObject, true);
tag.setContext('page', contextPageObject);
/* @if debug */
tag.debug('Page:page:set', _debug.level, _debug.messageEnd, tagObject);
/* @endif */
};
/**
* [Helper added by plugin {@link ATInternet.Tracker.Plugins.Page Page}] Tagging method for page (helper).
* @alias page.send
* @memberof! ATInternet.Tracker.Tag#
* @function
* @param tagObject {object} 5 properties : name, chapter1, chapter2, chapter3, customObject
* @example
* <pre><code class="javascript">tag.page.send({
* name: 'pageName',
* chapter1: 'mychapter1',
* chapter2: 'mychapter2',
* chapter3: 'mychapter3',
* customObject: {
* one: 1,
* two: 2
* },
* customVars: {
* page: {
* 1: 'page1',
* 5: 'page5',
* 20: 'page20'
* },
* site: {
* 1: 'site1',
* 5: 'site5',
* 20: 'site20'
* }
* },
* dynamicLabel: {
* pageId: '123456',
* chapter1: 'mychapter1',
* chapter2: 'mychapter2',
* chapter3: 'mychapter3',
* update: '200910031045'
* },
* tags: {
* keywords: ['tag','Key']
* },
* customTreeStructure: {
* category1: mycategory1,
* category2: mycategory2,
* category3: mycategory3
* }
* });
* </code></pre>
* @public
*/
tag.page.send = function (tagObject) {
tagObject = tagObject || {};
var preservePropagation = true;
var elementType = '';
var buffer = {
'p': _getFullName(tagObject),
's2': (tagObject['level2'] || '')
};
// customObject: If you pass a customObject when there is potentially a permanent one in the buffer, you have to merge them.
// Explanation: The builder ALWAYS sends the permanent elements as long as they are of the right type.
// If there is a permanent stc, it is necessary to recover its value and use it to complete the customObject (priority) passed as parameter.
// If there is no permanent stc in the buffer, we simply send the customObject passed as parameter.
var customObjectValue = tagObject.customObject;
if (customObjectValue) {
var hitParam = 'stc';
var hitType = ['page'];
customObjectValue = tag.processTagObject(hitParam, hitType, customObjectValue);
buffer[hitParam] = {
_value: ATInternet.Utils.jsonSerialize(customObjectValue),
_options: {
hitType: hitType,
encode: true,
separator: ',',
truncate: true
}
};
}
//vrn management.
var contextPageObject = tag.getContext('page') || {};
if (contextPageObject.vrn) {
buffer.vrn = contextPageObject.vrn;
tag.delContext('page', 'vrn');
}
// internalSearch management.
var contextInternalSearch = tag.getContext('InternalSearch') || {};
if (typeof contextInternalSearch.keyword !== 'undefined') {
buffer.mc = ATInternet.Utils.cloneSimpleObject(contextInternalSearch.keyword);
if (typeof contextInternalSearch.resultPageNumber !== 'undefined') {
buffer.np = ATInternet.Utils.cloneSimpleObject(contextInternalSearch.resultPageNumber);
}
tag.delContext('InternalSearch');
}
//Safari preview.
if (ATInternet.Utils.isPreview() && tag.getConfig('preview')) {
buffer.pvw = 1;
}
//Indicators.
_setIndicatorVariables(buffer, tagObject.customVars, true);
//Dynamic label.
_setDynamicLabel(buffer, tagObject.dynamicLabel, true);
//Tags.
_setTags(buffer, tagObject.tags, true);
//Custom Tree Structure.
_setCustomTreeStructure(buffer, tagObject.customTreeStructure, true);
//Campaigns variables.
var contextCampaignsObject = tag.getContext('campaigns') || {};
_setCampaignsVariables(buffer, contextCampaignsObject, true);
tag.delContext('campaigns');
var eventObject = null;
if (tagObject && tagObject.hasOwnProperty('event')) {
eventObject = tagObject.event || window.event;
}
if (!ATInternet.Utils.isTabOpeningAction(eventObject) && tagObject.elem) {
var manage = tag.techClicks.manageClick(tagObject.elem, eventObject);
preservePropagation = manage.preservePropagation;
elementType = manage.elementType;
}
tag.manageSend(function () {
tag.sendHit(buffer, null, tagObject.callback, null, elementType);
});
contextPageObject.name = _magic(contextPageObject.name, tagObject.name, '');
contextPageObject.level2 = _magic(contextPageObject.level2, tagObject.level2, '');
//Create chapters keys with undefined value is not wanted here.
_setDeclaredProperty(contextPageObject, tagObject, 'chapter1');
_setDeclaredProperty(contextPageObject, tagObject, 'chapter2');
_setDeclaredProperty(contextPageObject, tagObject, 'chapter3');
tag.setContext('page', contextPageObject);
/* @if debug */
tag.debug('Page:page:send', _debug.level, _debug.messageEnd, tagObject);
/* @endif */
return preservePropagation;
};
/**
* [Helper added by plugin {@link ATInternet.Tracker.Plugins.Page Page}] Will be called by tracker.dispatch if any page has been set.
* @alias page.onDispatch
* @memberof! ATInternet.Tracker.Tag#
* @function
* @param callback {function} Callback to execute
* @param elementType {string} Element type (mailto, form, redirection)
* @private
*/
tag.page.onDispatch = function (callback, elementType) {
var contextPageObject = tag.getContext('page') || {};
var contextInternalSearch = tag.getContext('InternalSearch') || {};
tag.setParam('p', _getFullName(contextPageObject));
tag.setParam('s2', (contextPageObject.level2 || ''));
//vrn management
if (contextPageObject.vrn) {
tag.setParam('vrn', contextPageObject.vrn);
tag.delContext('page', 'vrn');
}
// internalSearch management
if (typeof contextInternalSearch.keyword !== 'undefined') {
tag.setParam('mc', ATInternet.Utils.cloneSimpleObject(contextInternalSearch.keyword));
if (typeof contextInternalSearch.resultPageNumber !== 'undefined') {
tag.setParam('np', ATInternet.Utils.cloneSimpleObject(contextInternalSearch.resultPageNumber));
}
tag.delContext('InternalSearch');
}
//Safari preview.
if (ATInternet.Utils.isPreview() && tag.getConfig('preview')) {
tag.setParam('pvw', 1);
}
//Indicators.
_setIndicatorVariables(null, contextPageObject.customVars, false);
//Dynamic label.
_setDynamicLabel(null, contextPageObject.dynamicLabel, false);
//Tags.
_setTags(null, contextPageObject.tags, false);
//Custom Tree Structure.
_setCustomTreeStructure(null, contextPageObject.customTreeStructure, false);
//Campaigns variables.
var contextCampaignsObject = tag.getContext('campaigns') || {};
_setCampaignsVariables(null, contextCampaignsObject, false);
tag.delContext('campaigns');
var hitType = ['page'];
var contextObject = contextPageObject.customObject;
if (contextObject) {
var hitParam = 'stc';
var paramOptions = {
'hitType': hitType,
'encode': true,
'separator': ',',
'truncate': true,
'elementType': elementType
};
tag.processContextObjectAndSendHit(hitParam, paramOptions, contextObject, callback);
} else {
tag.manageSend(function () {
tag.sendHit(null, [['hitType', hitType]], callback, null, elementType);
});
}
};
// For unit tests on private elements !!!
/* @if test */
self._getFullName = _getFullName;
self._magic = _magic;
self._setDeclaredProperty = _setDeclaredProperty;
self._setIndicatorVariables = _setIndicatorVariables;
self._setDynamicLabel = _setDynamicLabel;
self._setTags = _setTags;
self._setCustomTreeStructure = _setCustomTreeStructure;
self._setCampaignsVariables = _setCampaignsVariables;
/* @endif */
};
ATInternet.Tracker.addPlugin('Page');