Newer
Older
/*!
* Piwik - Web Analytics
*
* @link http://piwik.org
* @source http://dev.piwik.org/trac/browser/trunk/js/piwik.js
* @license http://www.opensource.org/licenses/bsd-license.php Simplified BSD
// Refer to README for build instructions when minifying this file for distribution.
/*
* Browser [In]Compatibility
*
* This version of piwik.js is known to not work with:
* - IE4 - try..catch and for..in introduced in IE5
* - IE5 - named anonymous functions, array.push, encodeURIComponent, and decodeURIComponent introduced in IE5.5
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
/************************************************************
* JSON - public domain reference implementation by Douglas Crockford
* @link http://www.JSON.org/json2.js
*
* Modifications against json2.js 2011-01-18:
* - handle case JSON already defined (e.g., ECMAScript 5)
* - use new RegExp(pattern) instead of /pattern/ for greater portability
************************************************************/
/*jslint evil: true, strict: true, regexp: false */
if (!this.JSON) {
this.JSON = {};
}
(function () {
"use strict";
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
if (typeof Date.prototype.toJSON !== 'function') {
Date.prototype.toJSON = function (key) {
return isFinite(this.valueOf()) ?
this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z' : null;
};
String.prototype.toJSON =
Number.prototype.toJSON =
Boolean.prototype.toJSON = function (key) {
return this.valueOf();
};
}
var cx = new RegExp("[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]", 'g'),
escapable = new RegExp("[\\\\\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]", 'g'),
gap,
indent,
meta = { // table of character substitutions
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
},
rep;
function quote(string) {
// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.
escapable.lastIndex = 0;
return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
var c = meta[a];
return typeof c === 'string' ? c :
'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
}) + '"' : '"' + string + '"';
}
function str(key, holder) {
// Produce a string from holder[key].
var i, // The loop counter.
k, // The member key.
v, // The member value.
length,
mind = gap,
partial,
value = holder[key];
// If the value has a toJSON method, call it to obtain a replacement value.
if (value && typeof value === 'object' &&
typeof value.toJSON === 'function') {
value = value.toJSON(key);
}
// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.
if (typeof rep === 'function') {
value = rep.call(holder, key, value);
}
// What happens next depends on the value's type.
switch (typeof value) {
case 'string':
return quote(value);
case 'number':
// JSON numbers must be finite. Encode non-finite numbers as null.
return isFinite(value) ? String(value) : 'null';
case 'boolean':
case 'null':
// If the value is a boolean or null, convert it to a string. Note:
// typeof null does not produce 'null'. The case is included here in
// the remote chance that this gets fixed someday.
return String(value);
// If the type is 'object', we might be dealing with an object or an array or
// null.
case 'object':
// Due to a specification blunder in ECMAScript, typeof null is 'object',
// so watch out for that case.
if (!value) {
return 'null';
}
// Make an array to hold the partial results of stringifying this object value.
gap += indent;
partial = [];
// Is the value an array?
if (Object.prototype.toString.apply(value) === '[object Array]') {
// The value is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.
length = value.length;
for (i = 0; i < length; i += 1) {
partial[i] = str(i, value) || 'null';
}
// Join all of the elements together, separated with commas, and wrap them in
// brackets.
v = partial.length === 0 ? '[]' : gap ?
'[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
'[' + partial.join(',') + ']';
gap = mind;
return v;
}
// If the replacer is an array, use it to select the members to be stringified.
if (rep && typeof rep === 'object') {
length = rep.length;
for (i = 0; i < length; i += 1) {
k = rep[i];
if (typeof k === 'string') {
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
} else {
// Otherwise, iterate through all of the keys in the object.
for (k in value) {
if (Object.hasOwnProperty.call(value, k)) {
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
}
// Join all of the member texts together, separated with commas,
// and wrap them in braces.
v = partial.length === 0 ? '{}' : gap ?
'{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
'{' + partial.join(',') + '}';
gap = mind;
return v;
}
}
// If the JSON object does not yet have a stringify method, give it one.
if (typeof JSON.stringify !== 'function') {
JSON.stringify = function (value, replacer, space) {
// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a JSON text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.
var i;
gap = '';
indent = '';
// If the space parameter is a number, make an indent string containing that
// many spaces.
if (typeof space === 'number') {
for (i = 0; i < space; i += 1) {
indent += ' ';
}
// If the space parameter is a string, it will be used as the indent string.
} else if (typeof space === 'string') {
indent = space;
}
// If there is a replacer, it must be a function or an array.
// Otherwise, throw an error.
rep = replacer;
if (replacer && typeof replacer !== 'function' &&
(typeof replacer !== 'object' ||
typeof replacer.length !== 'number')) {
throw new Error('JSON.stringify');
}
// Make a fake root object containing our value under the key of ''.
// Return the result of stringifying the value.
return str('', {'': value});
};
}
// If the JSON object does not yet have a parse method, give it one.
if (typeof JSON.parse !== 'function') {
JSON.parse = function (text, reviver) {
// The parse method takes a text and an optional reviver function, and returns
// a JavaScript value if the text is a valid JSON text.
var j;
function walk(holder, key) {
// The walk method is used to recursively walk the resulting structure so
// that modifications can be made.
var k, v, value = holder[key];
if (value && typeof value === 'object') {
for (k in value) {
if (Object.hasOwnProperty.call(value, k)) {
v = walk(value, k);
if (v !== undefined) {
value[k] = v;
} else {
delete value[k];
}
}
}
}
return reviver.call(holder, key, value);
}
// Parsing happens in four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.
text = String(text);
cx.lastIndex = 0;
if (cx.test(text)) {
text = text.replace(cx, function (a) {
return '\\u' +
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
});
}
// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with '()' and 'new'
// because they can cause invocation, and '=' because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.
// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
if ((new RegExp('^[\\],:{}\\s]*$'))
.test(text.replace(new RegExp('\\\\(?:["\\\\/bfnrt]|u[0-9a-fA-F]{4})', 'g'), '@')
.replace(new RegExp('"[^"\\\\n\\r]*"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?', 'g'), ']')
.replace(new RegExp('(?:^|:|,)(?:\\s*\\[)+', 'g'), ''))) {
// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.
j = eval('(' + text + ')');
// In the optional fourth stage, we recursively walk the new structure, passing
// each name/value pair to a reviver function for possible transformation.
return typeof reviver === 'function' ?
walk({'': j}, '') : j;
}
// If the text is not JSON parseable, then a SyntaxError is thrown.
throw new SyntaxError('JSON.parse');
};
}
}());
/************************************************************
* end JSON
************************************************************/
/*jslint browser:true, forin:true, plusplus:false, onevar:false, strict:true, evil:true */
/*global window unescape ActiveXObject _paq:true */
var
// asynchronous tracker (or proxy)
_paq = _paq || [],
// Piwik singleton and namespace
Piwik = Piwik || (function () {
"use strict";
/************************************************************
* Private data
************************************************************/
var expireDateTime,
robocoder
a validé
/* plugins */
plugins = {},
robocoder
a validé
/* alias frequently used globals for added minification */
documentAlias = document,
navigatorAlias = navigator,
screenAlias = screen,
windowAlias = window,
robocoder
a validé
/* DOM Ready */
hasLoaded = false,
registeredOnLoadHandlers = [],
robocoder
a validé
/*
* encode
*/
encodeWrapper = windowAlias.encodeURIComponent,
robocoder
a validé
/*
* decode
*/
decodeWrapper = windowAlias.decodeURIComponent,
robocoder
a validé
/* asynchronous tracker */
asyncTracker,
robocoder
a validé
/* iterator */
i;
/************************************************************
* Private methods
************************************************************/
/*
*/
function isDefined(property) {
return typeof property !== 'undefined';
/*
* Is property a function?
*/
function isFunction(property) {
return typeof property === 'function';
}
/*
* Is property an object?
*
* @return bool Returns true if property is null, an Object, or subclass of Object (i.e., an instanceof String, Date, etc.)
*/
function isObject(property) {
return typeof property === 'object';
}
/*
* Is property a string?
*/
function isString(property) {
return typeof property === 'string' || property instanceof String;
}
/*
* apply wrapper
*
* @param array parameterArray An array comprising either:
*/
function apply(parameterArray) {
var f = parameterArray.shift();
if (isString(f)) {
asyncTracker[f].apply(asyncTracker, parameterArray);
/*
* Cross-browser helper function to add event handler
*/
function addEventListener(element, eventType, eventHandler, useCapture) {
if (element.addEventListener) {
element.addEventListener(eventType, eventHandler, useCapture);
return true;
return element.attachEvent('on' + eventType, eventHandler);
}
element['on' + eventType] = eventHandler;
}
/*
* Call plugin hook methods
*/
function executePluginMethod(methodName, callback) {
var result = '', i, pluginMethod;
for (i in plugins) {
pluginMethod = plugins[i][methodName];
if (isFunction(pluginMethod)) {
result += pluginMethod(callback);
}
}
return result;
}
/*
* Handle beforeunload event
*/
function beforeUnloadHandler() {
/*
* Delay/pause (blocks UI)
*/
if (expireDateTime) {
// the things we do for backwards compatibility...
// in ECMA-262 5th ed., we could simply use: while (Date.now() < expireDateTime) { }
now = new Date();
}
}
/*
* Handler for onload event
*/
function loadHandler() {
var i;
robocoder
a validé
if (!hasLoaded) {
hasLoaded = true;
executePluginMethod('load');
for (i = 0; i < registeredOnLoadHandlers.length; i++) {
registeredOnLoadHandlers[i]();
}
}
return true;
}
/*
* Add onload or DOM ready handler
*/
function addReadyListener() {
if (documentAlias.addEventListener) {
addEventListener(documentAlias, 'DOMContentLoaded', function ready() {
robocoder
a validé
documentAlias.removeEventListener('DOMContentLoaded', ready, false);
loadHandler();
});
} else if (documentAlias.attachEvent) {
documentAlias.attachEvent('onreadystatechange', function ready() {
if (documentAlias.readyState === 'complete') {
documentAlias.detachEvent('onreadystatechange', ready);
loadHandler();
}
});
if (documentAlias.documentElement.doScroll && windowAlias === top) {
(function ready() {
if (!hasLoaded) {
try {
documentAlias.documentElement.doScroll('left');
} catch (error) {
setTimeout(ready, 0);
return;
}
loadHandler();
}
}());
}
}
// fallback
addEventListener(windowAlias, 'load', loadHandler, false);
}
/*
* Get page referrer
*/
function getReferrer() {
var referrer = '';
robocoder
a validé
try {
referrer = top.document.referrer;
} catch (e) {
if (parent) {
try {
referrer = parent.document.referrer;
} catch (e2) {
referrer = '';
}
}
}
if (referrer === '') {
referrer = documentAlias.referrer;
}
return referrer;
}
/*
* Extract hostname from URL
*/
// scheme : // [username [: password] @] hostame [: port] [/ [path] [? query] [# fragment]]
var e = new RegExp('^(?:(?:https?|ftp):)/*(?:[^@]+@)?([^:/#]+)'),
matches = e.exec(url);
robocoder
a validé
return matches ? matches[1] : url;
}
* Extract parameter from URL
*/
function getParameter(url, varName) {
// scheme : // [username [: password] @] hostame [: port] [/ [path] [? query] [# fragment]]
var e = new RegExp('^(?:https?|ftp)(?::/*(?:[^?]+)[?])([^#]+)'),
matches = e.exec(url),
f = new RegExp('(?:^|&)' + varName + '=([^&]*)'),
result = matches ? f.exec(matches[1]) : 0;
robocoder
a validé
return result ? decodeWrapper(result[1]) : '';
}
/*
function setCookie(cookieName, value, msToExpire, path, domain, secure) {
var expiryDate;
// relative time to expire in milliseconds
if (msToExpire) {
expiryDate = new Date();
expiryDate.setTime(expiryDate.getTime() + msToExpire);
}
documentAlias.cookie = cookieName + '=' + encodeWrapper(value) +
(msToExpire ? ';expires=' + expiryDate.toGMTString() : '') +
';path=' + (path ? path : '/') +
(domain ? ';domain=' + domain : '') +
(secure ? ';secure' : '');
}
/*
* Get cookie value
*/
function getCookie(cookieName) {
var cookiePattern = new RegExp('(^|;)[ ]*' + cookieName + '=([^;]*)'),
cookieMatch = cookiePattern.exec(documentAlias.cookie);
return cookieMatch ? decodeWrapper(cookieMatch[2]) : 0;
/*
* UTF-8 encoding
*/
function utf8_encode(argString) {
return unescape(encodeWrapper(argString));
}
/************************************************************
* sha1
* - based on sha1 from http://phpjs.org/functions/sha1:512 (MIT / GPL v2)
************************************************************/
function sha1(str) {
// + original by: Webtoolkit.info (http://www.webtoolkit.info/)
// + namespaced by: Michael White (http://getsprink.com)
// + input by: Brett Zamir (http://brett-zamir.me)
// + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// + jslinted by: Anthon Pang (http://piwik.org)
var
rotate_left = function (n, s) {
return (n << s) | (n >>> (32 - s));
},
cvt_hex = function (val) {
var str = "",
i,
v;
for (i = 7; i >= 0; i--) {
v = (val >>> (i * 4)) & 0x0f;
str += v.toString(16);
}
return str;
},
blockstart,
robocoder
a validé
i,
j,
W = [],
H0 = 0x67452301,
H1 = 0xEFCDAB89,
H2 = 0x98BADCFE,
H3 = 0x10325476,
H4 = 0xC3D2E1F0,
robocoder
a validé
A,
B,
C,
D,
E,
temp,
str_len,
word_array = [];
robocoder
a validé
str = utf8_encode(str);
str_len = str.length;
for (i = 0; i < str_len - 3; i += 4) {
j = str.charCodeAt(i) << 24 | str.charCodeAt(i + 1) << 16 |
str.charCodeAt(i + 2) << 8 | str.charCodeAt(i + 3);
word_array.push(j);
}
switch (str_len & 3) {
robocoder
a validé
case 0:
i = 0x080000000;
break;
case 1:
i = str.charCodeAt(str_len - 1) << 24 | 0x0800000;
break;
case 2:
i = str.charCodeAt(str_len - 2) << 24 | str.charCodeAt(str_len - 1) << 16 | 0x08000;
break;
case 3:
i = str.charCodeAt(str_len - 3) << 24 | str.charCodeAt(str_len - 2) << 16 | str.charCodeAt(str_len - 1) << 8 | 0x80;
break;
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
}
word_array.push(i);
while ((word_array.length & 15) !== 14) {
word_array.push(0);
}
word_array.push(str_len >>> 29);
word_array.push((str_len << 3) & 0x0ffffffff);
for (blockstart = 0; blockstart < word_array.length; blockstart += 16) {
for (i = 0; i < 16; i++) {
W[i] = word_array[blockstart + i];
}
for (i = 16; i <= 79; i++) {
W[i] = rotate_left(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);
}
A = H0;
B = H1;
C = H2;
D = H3;
E = H4;
for (i = 0; i <= 19; i++) {
temp = (rotate_left(A, 5) + ((B & C) | (~B & D)) + E + W[i] + 0x5A827999) & 0x0ffffffff;
E = D;
D = C;
C = rotate_left(B, 30);
B = A;
A = temp;
}
for (i = 20; i <= 39; i++) {
temp = (rotate_left(A, 5) + (B ^ C ^ D) + E + W[i] + 0x6ED9EBA1) & 0x0ffffffff;
E = D;
D = C;
C = rotate_left(B, 30);
B = A;
A = temp;
}
for (i = 40; i <= 59; i++) {
temp = (rotate_left(A, 5) + ((B & C) | (B & D) | (C & D)) + E + W[i] + 0x8F1BBCDC) & 0x0ffffffff;
E = D;
D = C;
C = rotate_left(B, 30);
B = A;
A = temp;
}
for (i = 60; i <= 79; i++) {
temp = (rotate_left(A, 5) + (B ^ C ^ D) + E + W[i] + 0xCA62C1D6) & 0x0ffffffff;
E = D;
D = C;
C = rotate_left(B, 30);
B = A;
A = temp;
}
H0 = (H0 + A) & 0x0ffffffff;
H1 = (H1 + B) & 0x0ffffffff;
H2 = (H2 + C) & 0x0ffffffff;
H3 = (H3 + D) & 0x0ffffffff;
H4 = (H4 + E) & 0x0ffffffff;
}
temp = cvt_hex(H0) + cvt_hex(H1) + cvt_hex(H2) + cvt_hex(H3) + cvt_hex(H4);
return temp.toLowerCase();
}
/************************************************************
* end sha1
************************************************************/
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
/*
* Fix-up URL when page rendered from search engine cache or translated page
*/
function urlFixup(hostName, href, referrer) {
if (hostName === 'webcache.googleusercontent.com' || // Google
hostName === 'cc.bingj.com' || // Bing
hostName.substring(0, 5) === '74.6.') { // Yahoo (via Inktomi 74.6.0.0/16)
href = documentAlias.links[0].href;
hostName = getHostName(href);
} else if (hostName === 'translate.googleusercontent.com') { // Google
if (referrer === '') {
referrer = href;
}
href = getParameter(href, 'u');
hostName = getHostName(href);
}
return [hostName, href, referrer];
}
/*
* Fix-up domain
*/
function domainFixup(domain) {
var dl = domain.length;
return (domain.charAt(--dl) === '.') ? domain.substring(0, dl) : domain;
}
/*
* Piwik Tracker class
*
* trackerUrl and trackerSiteId are optional arguments to the constructor
*
* See: Tracker.setTrackerUrl() and Tracker.setSiteId()
*/
function Tracker(trackerUrl, siteId) {
/************************************************************
* Private members
************************************************************/
var
robocoder
a validé
/*<DEBUG>*/
robocoder
a validé
/*
* registered test hooks
*/
registeredHooks = {},
robocoder
a validé
/*</DEBUG>*/
robocoder
a validé
// Current URL and Referrer URL
locationArray = urlFixup(documentAlias.domain, windowAlias.location.href, getReferrer()),
domainAlias = domainFixup(locationArray[0]),
locationHrefAlias = locationArray[1],
configReferrerUrl = locationArray[2],
robocoder
a validé
// Request method (GET or POST)
configRequestMethod = 'GET',
robocoder
a validé
// Tracker URL
configTrackerUrl = trackerUrl || '',
robocoder
a validé
// Site ID
configTrackerSiteId = siteId || '',
robocoder
a validé
// Document URL
configCustomUrl,
robocoder
a validé
// Document title
configTitle = documentAlias.title,
robocoder
a validé
// Extensions to be treated as download links
configDownloadExtensions = '7z|aac|ar[cj]|as[fx]|avi|bin|csv|deb|dmg|doc|exe|flv|gif|gz|gzip|hqx|jar|jpe?g|js|mp(2|3|4|e?g)|mov(ie)?|ms[ip]|od[bfgpst]|og[gv]|pdf|phps|png|ppt|qtm?|ra[mr]?|rpm|sea|sit|tar|t?bz2?|tgz|torrent|txt|wav|wm[av]|wpd||xls|xml|z|zip',
robocoder
a validé
// Hosts or alias(es) to not treat as outlinks
configHostsAlias = [domainAlias],
robocoder
a validé
// HTML anchor element classes to not track
configIgnoreClasses = [],
robocoder
a validé
// HTML anchor element classes to treat as downloads
configDownloadClasses = [],
robocoder
a validé
// HTML anchor element classes to treat at outlinks
configLinkClasses = [],
robocoder
a validé
// Maximum delay to wait for web bug image to be fetched (in milliseconds)
configTrackerPause = 500,
// Minimum visit time after initial page view (in milliseconds)
configMinimumVisitTime,
// Recurring heart beat after initial ping (in milliseconds)
configHeartBeatTimer,
robocoder
a validé
// Disallow hash tags in URL
configDiscardHashTag,
robocoder
a validé
// Custom data
configCustomData,
robocoder
a validé
// First-party cookie name prefix
configCookieNamePrefix = '_pk_',
robocoder
a validé
// First-party cookie domain
// User agent defaults to origin hostname
configCookieDomain,
robocoder
a validé
// First-party cookie path
// Default is user agent defined.
configCookiePath,
// Do Not Track
configDoNotTrack,
robocoder
a validé
// Do we attribute the conversion to the first referrer or the most recent referrer?
configConversionAttributionFirstReferrer,
robocoder
a validé
// Life of the visitor cookie (in milliseconds)
configVisitorCookieTimeout = 63072000000, // 2 years
robocoder
a validé
// Life of the session cookie (in milliseconds)
configSessionCookieTimeout = 1800000, // 30 minutes
robocoder
a validé
// Life of the referral cookie (in milliseconds)
configReferralCookieTimeout = 15768000000, // 6 months
robocoder
a validé
// Custom Variables read from cookie
customVariables = false,
robocoder
a validé
// Custom Variables names and values are each truncated before being sent in the request or recorded in the cookie
customVariableMaximumLength = 100,
robocoder
a validé
// Client-side data collection
browserHasCookies = '0',
// Plugin, Parameter name, MIME type, detected
pluginMap = {
// document types
pdf: ['pdf', 'application/pdf', '0'],
// media players
quicktime: ['qt', 'video/quicktime', '0'],
realplayer: ['realp', 'audio/x-pn-realaudio-plugin', '0'],
wma: ['wma', 'application/x-mplayer2', '0'],
// interactive multimedia
director: ['dir', 'application/x-director', '0'],
flash: ['fla', 'application/x-shockwave-flash', '0'],
// RIA
java: ['java', 'application/x-java-vm', '0'],
gears: ['gears', 'application/x-googlegears', '0'],
silverlight: ['ag', 'application/x-silverlight', '0']
},
// Guard against installing the link tracker more than once per Tracker instance
linkTrackingInstalled = false,
// Guard against installing the activity tracker more than once per Tracker instance
activityTrackingInstalled = false,
robocoder
a validé
// Last activity timestamp
lastActivityTime,
robocoder
a validé
// Internal state of the pseudo click handler
lastButton,
lastTarget,
// Visitor ID
visitorId,
robocoder
a validé
// Domain hash value
domainHash;
function purify(str) {
var targetPattern;
if (configDiscardHashTag) {
targetPattern = new RegExp('#.*');
return str.replace(targetPattern, '');
}
return str;
}
/*
function isSiteHostName(hostName) {
var i, alias, offset;
for (i = 0; i < configHostsAlias.length; i++) {
alias = configHostsAlias[i].toLowerCase();
if (hostName === alias) {
return true;
}
if (alias.substring(0, 2) === '*.') {
if (hostName === alias.substring(2)) {
return true;
}
offset = hostName.length - alias.length + 1;
if ((offset > 0) && (hostName.substring(offset) === alias.substring(1))) {
return true;
}
}
* Send image request to Piwik server using GET.
* The infamous web bug is a transparent, single pixel (1x1) image
function getImage(request) {
var image = new Image(1, 1);
robocoder
a validé
image.onLoad = function () { };