Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Steur <thomas.steur@googlemail.com>2014-09-03 21:26:55 +0400
committerThomas Steur <thomas.steur@googlemail.com>2014-09-03 21:26:55 +0400
commit4a439299d1b067b2d02d0cd8da37405b97a565af (patch)
treebffddb06db98eb3ef9539ecc8e065907a5a18bb1
parent71c76ffd4435344024c3a9ef332daab8f908572f (diff)
refs #4996 handle interactions better / correct. Code not tested at all yet. Gonna write some tests
-rw-r--r--js/piwik.js160
-rw-r--r--misc/internal-docs/content-tracking.md4
2 files changed, 111 insertions, 53 deletions
diff --git a/js/piwik.js b/js/piwik.js
index d7207c6fd9..b8c027f333 100644
--- a/js/piwik.js
+++ b/js/piwik.js
@@ -1546,11 +1546,33 @@ if (typeof Piwik !== 'object') {
isNodeVisible: function (node) {
return isVisible(node) && this.isNodeInViewport(node);
},
- buildInteractionRequestParams: function (name, piece, interaction)
+ buildInteractionRequestParams: function (interaction, name, piece, target)
{
- return 'c_n=' + encodeWrapper(name) +
- '&c_p=' + encodeWrapper(piece) +
- '&c_i=' + encodeWrapper(interaction);
+ var params = '';
+
+ if (interaction) {
+ params += 'c_i='+ encodeWrapper(interaction);
+ }
+ if (name) {
+ if (params) {
+ params += '&';
+ }
+ params += 'c_n='+ encodeWrapper(name);
+ }
+ if (piece) {
+ if (params) {
+ params += '&';
+ }
+ params += '&c_p='+ encodeWrapper(piece);
+ }
+ if (target) {
+ if (params) {
+ params += '&';
+ }
+ params += '&c_t='+ encodeWrapper(target);
+ }
+
+ return params;
},
buildImpressionRequestParams: function (name, piece, target)
{
@@ -1593,22 +1615,6 @@ if (typeof Piwik !== 'object') {
return contents;
},
- addClickEventIfInternalLink: function (node, callback) {
- addEventListener(node, 'click', function (event) {
- var url = content.findInternalTargetLink(node);
- if (!url) {
- return;
- }
-
- if (event.preventDefault) {
- event.preventDefault();
- } else {
- event.returnValue = false;
- }
-
- callback(url);
- });
- },
findInternalTargetLink: function (node)
{
var clickNode = this.findTargetNode(node);
@@ -1630,10 +1636,6 @@ if (typeof Piwik !== 'object') {
return;
}
- if (0 === (''+ link).indexOf('#')) {
- return;
- }
-
if (link !== this.removeDomainIfIsUrl(link)) {
return; // outlink or download?
}
@@ -1645,21 +1647,18 @@ if (typeof Piwik !== 'object') {
var clickNode = this.findTargetNode(node);
if (!clickNode) {
- return false;
+ return;
}
var elementName = clickNode.nodeName.toLowerCase();
if (elementName !== 'a') {
- return false;
+ return;
}
if (clickNode && clickNode.setAttribute) {
clickNode.setAttribute('href', url);
- return true;
}
-
- return false;
}
};
@@ -2686,7 +2685,7 @@ if (typeof Piwik !== 'object') {
}
}
- function appendContentInteractionToRequestIfPossible(request, anyNode, targetFallback)
+ function appendContentInteractionToRequestIfPossible(request, anyNode, interaction, fallbackTarget)
{
if (!anyNode || !request) {
@@ -2707,17 +2706,15 @@ if (typeof Piwik !== 'object') {
return;
}
- if (!contentPiece.target && targetFallback) {
- contentPiece.target = targetFallback;
- } else if (!contentPiece.target) {
- contentPiece.target = 'Unknown';
+ if (!content.target && fallbackTarget) {
+ content.target = fallbackTarget;
}
if (request) {
request += '&';
}
- request += content.buildInteractionRequestParams(contentPiece.name, contentPiece.piece, contentPiece.target);
+ request += content.buildInteractionRequestParams(interaction, contentPiece.name, contentPiece.piece, contentPiece.target);
return request;
}
@@ -2748,16 +2745,32 @@ if (typeof Piwik !== 'object') {
return base + url
}
- function buildTrackingRedirectUrl(url) {
+ function buildContentInteractionTrackingRedirectUrl(url, contentName, contentPiece, contentTarget) {
if (0 === url.indexOf(configTrackerUrl)) {
return url;
}
var redirectUrl = toAbsoluteUrl(url);
- var request = getRequest('redirecturl=' + redirectUrl + '&c_i=' + url + '&' + buildEventRequest('Content', 'click', url, ''));
+ var request = buildContentInteractionTrackingRequest(url, contentName, contentPiece, contentTarget);
+ request += '&redirecturl=' + redirectUrl;
+
return configTrackerUrl + (configTrackerUrl.indexOf('?') < 0 ? '?' : '&') + request;
}
+ function buildContentInteractionTrackingRequest(url, contentName, contentPiece, contentTarget) {
+ if (0 === url.indexOf(configTrackerUrl)) {
+ return url;
+ }
+
+
+ var contentInteraction = 'click';
+
+ var params = content.buildInteractionRequestParams(contentInteraction, contentName, contentPiece, contentTarget);
+
+ var request = getRequest(params + buildEventRequest('Content', contentInteraction, url, ''));
+ return request;
+ }
+
function wasContentImpressionAlreadyTracked(content)
{
if (!trackedContentImpressions || !trackedContentImpressions.length) {
@@ -2841,23 +2854,68 @@ if (typeof Piwik !== 'object') {
}
for (index = 0; index < contentNodes.length; index++) {
- // TODO we should actually replace the link on the target node, not on the content node !!!IMPORTANT
- var internalLink = content.findInternalTargetLink(contentNodes[index]);
- if (internalLink) {
- content.replaceTargetLink(contentNodes[index], buildTrackingRedirectUrl(internalLink));
+ // TODO should we consult getLinkType()?
+ var targetNode = content.findTargetNode(contentNodes[index]);
+
+ if (!targetNode) {
+ continue;
}
- content.addClickEventIfInternalLink(contentNodes[index], function (url) {
- var targetUrl = buildTrackingRedirectUrl(internalLink);
+ if (targetNode && targetNode.contentTrackingRedirectSetupDone) {
+ continue;
+ }
+
+ targetNode.contentTrackingRedirectSetupDone = true;
+
+ if (targetNode.nodeName.toLowerCase() === 'a' &&
+ query.hasNodeAttributeWithValue(targetNode, 'href')) {
+
+ var internalLink = content.findInternalTargetLink(contentNodes[index]);
+
+ if (internalLink) {
+
+ content.replaceTargetLink(targetNode, buildTrackingRedirectUrl(internalLink));
+
+ addEventListener(targetNode, 'click', function () {
+ var url = content.findInternalTargetLink(this);
+ if (!url) {
+ return;
+ }
+
+ var contentName = content.findContentName(this);
+ var contentPiece = content.findContentPiece(this);
+ var contentTarget = content.findContentTarget(this);
- // location.href does not respect target=_blank so we prefer to use this
- var replaced = content.replaceTargetLink(contentNodes[index], targetUrl);
+ if (0 === internalLink.indexOf('#')) {
+ var request = buildContentInteractionTrackingRequest('click', contentName, contentPiece, contentTarget);
+ sendRequest(request);
+ } else {
+ var targetUrl = buildContentInteractionTrackingRedirectUrl(internalLink, contentName, contentPiece, contentTarget);
+
+ // location.href does not respect target=_blank so we prefer to use this
+ content.replaceTargetLink(content.findTargetNode(this), targetUrl);
+ }
- if (!replaced) {
- // fallback to location.href
- location.href = targetUrl;
+ });
+
+ } else {
+ // outlink or download
}
- });
+
+ } else {
+ // trigger event
+
+ addEventListener(targetNode, 'click', function () {
+ var contentName = content.findContentName(this);
+ var contentPiece = content.findContentPiece(this);
+ var contentTarget = content.findContentTarget(this);
+
+ var request = buildContentInteractionTrackingRequest('', contentName, contentPiece, contentTarget);
+
+ sendRequest(request);
+ });
+ }
+
}
var index, request;
@@ -2901,7 +2959,7 @@ if (typeof Piwik !== 'object') {
function logContentInteraction(contentName, contentPiece, contentInteraction)
{
- var params = content.buildInteractionRequestParams(contentName, contentPiece, contentInteraction);
+ var params = content.buildInteractionRequestParams(contentInteraction, contentName, contentPiece);
if (!params) {
return;
@@ -2980,7 +3038,7 @@ if (typeof Piwik !== 'object') {
var linkParams = linkType + '=' + encodeWrapper(purify(url));
- linkParams = appendContentInteractionToRequestIfPossible(linkParams, sourceElement, url);
+ linkParams = appendContentInteractionToRequestIfPossible(linkParams, sourceElement, 'click', url);
var request = getRequest(linkParams, customData, 'link');
sendRequest(request, (callback ? 0 : configTrackerPause), callback);
diff --git a/misc/internal-docs/content-tracking.md b/misc/internal-docs/content-tracking.md
index ebbc8ebea5..2642a65e8f 100644
--- a/misc/internal-docs/content-tracking.md
+++ b/misc/internal-docs/content-tracking.md
@@ -302,7 +302,7 @@ There are several ways to track a content impression and/or interaction manually
#### `trackContentImpressions()`
You can use this method to scan the entire DOM for content blocks.
-For each content block we will track a content impression immediately unless you enable `enableTrackOnlyVisbleContent` see below.
+For each content block we will track a content impression immediately unless you enable `enableTrackOnlyVisibleContent` see below.
Note: We will not send an impression of the same content block twice if you call this method multiple times unless `trackPageView()` is called meanwhile. This is useful for single page applications. The "same" content blocks means if a content block has the identical name, piece and target as an already tracked one.
Note: At this stage we do not exeute this method automatically along with a trackPageView(), we can do this later once we know it works
@@ -323,7 +323,7 @@ We would detect two new content blocks in this example.
Please note: In case you have enabled to only track visible content blocks we will respect this. In case it contains a content block that was already tracked we will not track it again.
-#### `enableTrackOnlyVisbleContent(checkOnSroll, timeIntervalInMs)`
+#### `enableTrackOnlyVisibleContent(checkOnSroll, timeIntervalInMs)`
If you enable to track only visible content we will only track an impression if a content block is actually visible. With visible we mean the content block has been in the view port, it is actually in the DOM and is not hidden via CSS (opacity, visibility, display, ...).
* Optionally you can tell us to rescan the DOM automatically after each scroll event by passing `checkOnSroll=true`. We will then check whether the previously hidden content blocks are visible now and if so track the impression.