@salesforce/pwa-kit-create-app 3.3.0-preview.0 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/bootstrap/js/.eslintignore +1 -1
- package/assets/bootstrap/js/overrides/app/static/dwac-21.7.js +475 -0
- package/assets/bootstrap/js/overrides/app/static/dwanalytics-22.2.js +502 -0
- package/assets/bootstrap/js/overrides/app/static/head-active_data.js +43 -0
- package/assets/bootstrap/js/package.json.hbs +1 -1
- package/package.json +5 -5
- package/templates/express-minimal.tar.gz +0 -0
- package/templates/mrt-reference-app.tar.gz +0 -0
- package/templates/retail-react-app.tar.gz +0 -0
- package/templates/typescript-minimal.tar.gz +0 -0
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
// Enhance the dw.ac namespace
|
|
2
|
+
(function(dw) {
|
|
3
|
+
if (typeof dw.ac === "undefined") {
|
|
4
|
+
return; // don't do anything if there was no <isactivedatahead> tag, that would create the ac namespace.
|
|
5
|
+
}
|
|
6
|
+
// Returns the value of the first cookie found whose name is accepted by the given function
|
|
7
|
+
function getCookieValue(/*function(x)*/ acceptFunction) {
|
|
8
|
+
var cookiePairs = document.cookie.split(';');
|
|
9
|
+
for (var i = 0; i < cookiePairs.length; i++)
|
|
10
|
+
{
|
|
11
|
+
var index = cookiePairs[i].indexOf('=');
|
|
12
|
+
if (index != -1) {
|
|
13
|
+
var name = trim(cookiePairs[i].substring(0, index));
|
|
14
|
+
if (acceptFunction(name)) {
|
|
15
|
+
return trim(unescape(cookiePairs[i].substring(index + 1)));
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return null;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// trims a string, replacing the jquery.trim
|
|
24
|
+
function trim(/*string*/value) {
|
|
25
|
+
return value.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// Sets a cookie with the given name and value
|
|
29
|
+
function setCookieValue(/*string*/ name, /*string*/ value, /*integer*/ millisToExpiry) {
|
|
30
|
+
var cookie = name + '=' + escape(value) + ';path=/';
|
|
31
|
+
if (millisToExpiry != -1) {
|
|
32
|
+
cookie += ";expires=" + expires.toGMTString();
|
|
33
|
+
}
|
|
34
|
+
document.cookie = cookie;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// URL encodes the given string to match the Java URLEncoder class
|
|
38
|
+
function urlencode(/*string*/ value) {
|
|
39
|
+
var convertByte = function(code) {
|
|
40
|
+
if(code < 32) {
|
|
41
|
+
//numbers lower than 32 are control chars, not printable
|
|
42
|
+
return '';
|
|
43
|
+
} else {
|
|
44
|
+
return '%' + new Number(code).toString(16).toUpperCase();
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
var encoded = '';
|
|
49
|
+
for (var i = 0; i < value.length; i++) {
|
|
50
|
+
var c = value.charCodeAt(i);
|
|
51
|
+
if (((c >= 97) && (c <= 122)) || ((c >= 65) && (c <= 90)) || ((c >= 48) && (c <= 57)) || (c == 46) || (c == 45) || (c == 42) || (c == 95)) {
|
|
52
|
+
encoded += value.charAt(i); // a-z A-z 0-9 . - * _
|
|
53
|
+
}
|
|
54
|
+
else if (c == 32) {
|
|
55
|
+
encoded += '+'; // (space)
|
|
56
|
+
}
|
|
57
|
+
else if (c < 128) {
|
|
58
|
+
encoded += convertByte(c);
|
|
59
|
+
}
|
|
60
|
+
else if ((c >= 128) && (c < 2048)) {
|
|
61
|
+
encoded += convertByte((c >> 6) | 0xC0);
|
|
62
|
+
encoded += convertByte((c & 0x3F) | 0x80);
|
|
63
|
+
}
|
|
64
|
+
else if ((c >= 2048) && (c < 65536)) {
|
|
65
|
+
encoded += convertByte((c >> 12) | 0xE0);
|
|
66
|
+
encoded += convertByte(((c >> 6) & 0x3F) | 0x80);
|
|
67
|
+
encoded += convertByte((c & 0x3F) | 0x80);
|
|
68
|
+
}
|
|
69
|
+
else if (c >= 65536) {
|
|
70
|
+
encoded += convertByte((c >> 18) | 0xF0);
|
|
71
|
+
encoded += convertByte(((c >> 12) & 0x3F) | 0x80);
|
|
72
|
+
encoded += convertByte(((c >> 6) & 0x3F) | 0x80);
|
|
73
|
+
encoded += convertByte((c & 0x3F) | 0x80);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return encoded;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Returns the value of the analytics cookie set on the server
|
|
81
|
+
function getAnalyticsCookieValue() {
|
|
82
|
+
var acceptFunction = function(name) {
|
|
83
|
+
return (name.length > 5) && (name.substring(0, 5) === 'dwac_');
|
|
84
|
+
};
|
|
85
|
+
return getCookieValue(acceptFunction);
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
// Contextual information retrieved from the server
|
|
89
|
+
var analyticsContext = (function() {
|
|
90
|
+
if (dw.ac._analytics_enabled === "false") {
|
|
91
|
+
return {
|
|
92
|
+
enabled: false,
|
|
93
|
+
dwEnabled: false
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
var cookieValue = getAnalyticsCookieValue();
|
|
97
|
+
if (cookieValue == null) {
|
|
98
|
+
return {
|
|
99
|
+
visitorID: '__ANNONYMOUS__',
|
|
100
|
+
customer: '__ANNONYMOUS__',
|
|
101
|
+
siteCurrency: '',
|
|
102
|
+
sourceCode: '',
|
|
103
|
+
enabled: "true",
|
|
104
|
+
timeZone: dw.ac._timeZone,
|
|
105
|
+
dwEnabled: "true",
|
|
106
|
+
encoding: 'ISO-8859-1'
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
var tokens = cookieValue.split('|');
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
visitorID: tokens[0],
|
|
114
|
+
repository: tokens[1],
|
|
115
|
+
customer: tokens[2],
|
|
116
|
+
sourceCode: tokens[3],
|
|
117
|
+
siteCurrency: tokens[4],
|
|
118
|
+
enabled: tokens[5] == "true",
|
|
119
|
+
timeZone: tokens[6],
|
|
120
|
+
dwEnabled: tokens[7] == "true",
|
|
121
|
+
encoding: 'ISO-8859-1'
|
|
122
|
+
};
|
|
123
|
+
}());
|
|
124
|
+
|
|
125
|
+
// Turn debugging on or off
|
|
126
|
+
var setDebugEnabled = function(enabled) {
|
|
127
|
+
if (typeof enabled != 'boolean') {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
setCookieValue('dwacdebug', '' + enabled, -1);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
// Returns true if debug is enabled, false otherwise
|
|
135
|
+
function isDebugEnabled() {
|
|
136
|
+
var acceptFunction = function(name) {
|
|
137
|
+
return name === 'dwacdebug';
|
|
138
|
+
};
|
|
139
|
+
return getCookieValue(acceptFunction) === 'true';
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
// Map data structure
|
|
143
|
+
function Map() {
|
|
144
|
+
var data = [];
|
|
145
|
+
|
|
146
|
+
// Returns an array containing the entries in this map
|
|
147
|
+
this.getEntries = function() {
|
|
148
|
+
return data;
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
// Puts the given value in this map under the given key
|
|
152
|
+
this.put = function(/*object*/ key, /*object*/ value) {
|
|
153
|
+
for (var i = 0; i < data.length; i++) {
|
|
154
|
+
if (data[i].key == key) {
|
|
155
|
+
data[i].value = value;
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
data.push({key: key, value: value});
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// Puts all the key value pairs in the given map into this map
|
|
164
|
+
this.putAll = function(/*Map*/ map) {
|
|
165
|
+
var entries = map.getEntries();
|
|
166
|
+
for (var i = 0; i < entries.length; i++) {
|
|
167
|
+
this.put(entries[i].key, entries[i].value);
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
// Returns the value in this map under the given key, or null if there is no such value
|
|
172
|
+
this.get = function(/*object*/ key) {
|
|
173
|
+
for (var i = 0; i < data.length; i++) {
|
|
174
|
+
if (data[i].key == key) {
|
|
175
|
+
return data[i].value;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return null;
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
// Clears this map of entries
|
|
183
|
+
this.clear = function() {
|
|
184
|
+
data.length = 0;
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
// Returns if this map is empty of values
|
|
188
|
+
this.isEmpty = function() {
|
|
189
|
+
return data.length == 0;
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
// Delay in milliseconds before actually submitting data once some is ready
|
|
194
|
+
var SUBMIT_DELAY_MILLIS = 500;
|
|
195
|
+
|
|
196
|
+
// Set when the DOM is ready
|
|
197
|
+
var domReady = false;
|
|
198
|
+
|
|
199
|
+
// Timeout to submit data after a delay
|
|
200
|
+
var submitTimeout = null;
|
|
201
|
+
|
|
202
|
+
// Product impressions found on the page
|
|
203
|
+
var productImpressions = new Map();
|
|
204
|
+
|
|
205
|
+
// Product views found on the page
|
|
206
|
+
var productViews = new Map();
|
|
207
|
+
|
|
208
|
+
// Product recommendations found on the page
|
|
209
|
+
var productRecommendations = new Map();
|
|
210
|
+
|
|
211
|
+
// Applies values from the given source for fields defined in the given target
|
|
212
|
+
function applyFields(/*object*/ source, /*object*/ target) {
|
|
213
|
+
for (e in target) {
|
|
214
|
+
if (typeof source[e] != 'undefined') {
|
|
215
|
+
target[e] = source[e];
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return target;
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
// Collects the given product impression, and returns true if it is valid or false if it is not
|
|
222
|
+
var collectProductImpression = function(/*object*/ configs) {
|
|
223
|
+
if (typeof configs != 'object') {
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
var pi = applyFields(configs, {id:null});
|
|
228
|
+
|
|
229
|
+
// Quit if no SKU provided or is invalid
|
|
230
|
+
if (typeof pi.id != 'string') {
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Throw out the impression if SKU already seen
|
|
235
|
+
var previousImpression = productImpressions.get(pi.id);
|
|
236
|
+
if (previousImpression != null) {
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
productImpressions.put(pi.id, pi);
|
|
241
|
+
return true;
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
// Collects the given product recommendation, and returns true if it is valid or false if it is not
|
|
245
|
+
var collectProductRecommendation = function(/*object*/ configs) {
|
|
246
|
+
if (typeof configs != 'object') {
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
var pr = applyFields(configs, {id:null});
|
|
251
|
+
|
|
252
|
+
// Quit if no SKU provided or is invalid
|
|
253
|
+
if (typeof pr.id != 'string') {
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Throw out the recommendation if SKU already seen
|
|
258
|
+
var previousRecommendation = productRecommendations.get(pr.id);
|
|
259
|
+
if (previousRecommendation != null) {
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
productRecommendations.put(pr.id, pr);
|
|
264
|
+
return true;
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
// Collects the given product view, and returns true if it is valid or false if it is not
|
|
268
|
+
var collectProductView = function(/*object*/ configs) {
|
|
269
|
+
if (typeof configs != 'object') {
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
var pv = applyFields(configs, {id:null});
|
|
274
|
+
|
|
275
|
+
// Quit if no SKU provided or is invalid
|
|
276
|
+
if (typeof pv.id != 'string') {
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Throw out the view if SKU already seen
|
|
281
|
+
var previousView = productViews.get(pv.id);
|
|
282
|
+
if (previousView != null) {
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
productViews.put(pv.id, pv);
|
|
287
|
+
return true;
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
// Returns a new Map with the same contents as the given Map,
|
|
291
|
+
// clearing the given Map in the process
|
|
292
|
+
function copyAndClearMap(/*Map*/ map) {
|
|
293
|
+
var copy = new Map();
|
|
294
|
+
copy.putAll(map);
|
|
295
|
+
map.clear();
|
|
296
|
+
return copy;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Returns if there are collected data to submit
|
|
300
|
+
function containsProductDataToSubmit() {
|
|
301
|
+
return !productImpressions.isEmpty() || !productRecommendations.isEmpty()
|
|
302
|
+
|| !productViews.isEmpty();
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Performs the actual submission of collected data for analytics processing
|
|
306
|
+
var performDataSubmission = function() {
|
|
307
|
+
|
|
308
|
+
if (dw.ac._analytics != null)
|
|
309
|
+
{
|
|
310
|
+
var collectedData = {
|
|
311
|
+
pageInfo: dw.ac._category,
|
|
312
|
+
productImpressions: productImpressions,
|
|
313
|
+
productViews: productViews,
|
|
314
|
+
productRecommendations: productRecommendations,
|
|
315
|
+
debugEnabled: isDebugEnabled()
|
|
316
|
+
};
|
|
317
|
+
dw.ac._analytics.trackPageViewWithProducts(analyticsContext, collectedData, null);
|
|
318
|
+
productImpressions.clear();
|
|
319
|
+
productViews.clear();
|
|
320
|
+
productRecommendations.clear();
|
|
321
|
+
dw.ac._events.length = 0;
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
// Submits the collected data for analytics processing after a short delay
|
|
326
|
+
function submitCollectedData() {
|
|
327
|
+
// don't submit the data before dom is ready, the data is still collected,
|
|
328
|
+
// when dom is ready, the onDocumentReady method will call this method again.
|
|
329
|
+
if(!domReady) {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
if (submitTimeout) {
|
|
334
|
+
clearTimeout(submitTimeout);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
submitTimeout = setTimeout(performDataSubmission, SUBMIT_DELAY_MILLIS);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// Returns an object with the same properties as the given object, but with string type properties
|
|
341
|
+
// in the given array of names set to the URL encoded form of their values using the escape function
|
|
342
|
+
function escapeProperties(/*object*/ o, /*Array*/ props) {
|
|
343
|
+
if (typeof o == 'undefined') {
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
var copy = {};
|
|
348
|
+
for (e in o) {
|
|
349
|
+
var escapeProp = false;
|
|
350
|
+
for (var i = 0; (i < props.length) && !escapeProp; i++) {
|
|
351
|
+
var prop = props[i];
|
|
352
|
+
if ((e === prop) && (typeof o[prop] == 'string')) {
|
|
353
|
+
escapeProp = true;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
copy[e] = escapeProp ? urlencode(o[e]) : o[e];
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
return copy;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// Captures the given object data collected in subsequent events on the page,
|
|
364
|
+
// and returns true if the given object data is valid, or returns false if not
|
|
365
|
+
function captureObject(/*object*/ configs) {
|
|
366
|
+
if (typeof configs != 'object') {
|
|
367
|
+
return false;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if ((configs.type === dw.ac.EV_PRD_SEARCHHIT) || (configs.type === dw.ac.EV_PRD_SETPRODUCT)) {
|
|
371
|
+
return collectProductImpression(escapeProperties(configs, ['id']));
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if (configs.type === dw.ac.EV_PRD_DETAIL) {
|
|
375
|
+
return collectProductView(escapeProperties(configs, ['id']));
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
if (configs.type === dw.ac.EV_PRD_RECOMMENDATION) {
|
|
379
|
+
return collectProductRecommendation(escapeProperties(configs, ['id']));
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
return false;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// Captures the given data collected in subsequent events on the page
|
|
386
|
+
function captureAndSend(/*object*/ configs) {
|
|
387
|
+
if (typeof configs == 'undefined') {
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// Support both array and single object cases
|
|
392
|
+
if (typeof configs === 'object') {
|
|
393
|
+
if (configs instanceof Array) {
|
|
394
|
+
for (var i = 0; i < configs.length; i++) {
|
|
395
|
+
captureObject(configs[i]);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
if (configs[0] instanceof Object) {
|
|
400
|
+
captureObject(configs[0]);
|
|
401
|
+
}
|
|
402
|
+
else {
|
|
403
|
+
captureObject(configs);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// Submit captured data if appropriate
|
|
409
|
+
if (domReady) {
|
|
410
|
+
submitCollectedData();
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
// Enhance existing capture function with submission step
|
|
415
|
+
dw.ac.capture = captureAndSend;
|
|
416
|
+
|
|
417
|
+
// expose debug API
|
|
418
|
+
dw.ac.setDebugEnabled = setDebugEnabled;
|
|
419
|
+
|
|
420
|
+
dw.ac._handleCollectedData = function () {
|
|
421
|
+
domReady = false;
|
|
422
|
+
dw.ac._events.forEach(captureAndSend);
|
|
423
|
+
domReady = true;
|
|
424
|
+
submitCollectedData();
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
dw.ac._scheduleDataSubmission = function () {
|
|
428
|
+
if (dw.ac._submitTimeout) {
|
|
429
|
+
clearTimeout(dw.ac._submitTimeout);
|
|
430
|
+
}
|
|
431
|
+
dw.ac._submitTimeout = setTimeout(dw.ac._handleCollectedData, 500);
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
// Added specifically for PWA kit to set currency for Analytics Context
|
|
435
|
+
dw.ac._setSiteCurrency = function setSiteCurrency(currency) {
|
|
436
|
+
analyticsContext.siteCurrency = currency;
|
|
437
|
+
};
|
|
438
|
+
|
|
439
|
+
// replace jQuery.ready() function
|
|
440
|
+
(function onDocumentReady(callback) {
|
|
441
|
+
// Catch cases where $(document).ready() is called after the browser event has already occurred.
|
|
442
|
+
if (document.readyState === "complete") {
|
|
443
|
+
// Handle it asynchronously to allow scripts the opportunity to delay ready
|
|
444
|
+
setTimeout(callback, 1);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// Mozilla, Opera and webkit nightlies currently support this event
|
|
448
|
+
if (document.addEventListener) {
|
|
449
|
+
DOMContentLoaded = function() {
|
|
450
|
+
document.removeEventListener("DOMContentLoaded", DOMContentLoaded, false);
|
|
451
|
+
callback();
|
|
452
|
+
};
|
|
453
|
+
// Use the handy event callback
|
|
454
|
+
document.addEventListener("DOMContentLoaded", DOMContentLoaded, false);
|
|
455
|
+
// A fallback to window.onload, that will always work
|
|
456
|
+
window.addEventListener("load", callback, false);
|
|
457
|
+
// If IE event model is used
|
|
458
|
+
} else if (document.attachEvent) {
|
|
459
|
+
DOMContentLoaded = function() {
|
|
460
|
+
// Make sure body exists, at least, in case IE gets a little overzealous
|
|
461
|
+
if (document.readyState === "complete") {
|
|
462
|
+
document.detachEvent("onreadystatechange", DOMContentLoaded);
|
|
463
|
+
callback();
|
|
464
|
+
}
|
|
465
|
+
};
|
|
466
|
+
// ensure firing before onload, maybe late but safe also for iframes
|
|
467
|
+
document.attachEvent("onreadystatechange", DOMContentLoaded);
|
|
468
|
+
|
|
469
|
+
// A fallback to window.onload, that will always work
|
|
470
|
+
window.attachEvent("onload", callback);
|
|
471
|
+
}
|
|
472
|
+
})(function() {
|
|
473
|
+
dw.ac._handleCollectedData();
|
|
474
|
+
});
|
|
475
|
+
}((window.dw||{})));
|
|
@@ -0,0 +1,502 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* dwAnalytics - Web Analytics Tracking
|
|
3
|
+
* Based partially on Piwik
|
|
4
|
+
*
|
|
5
|
+
* @link http://piwik.org
|
|
6
|
+
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// Create dw namespace if necessary
|
|
10
|
+
if (typeof dw == 'undefined') {
|
|
11
|
+
var dw = {};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (typeof dw.__dwAnalyticsLoaded == 'undefined')
|
|
15
|
+
{
|
|
16
|
+
dw.__dwAnalyticsLoaded = true;
|
|
17
|
+
|
|
18
|
+
// DWAnalytics singleton and namespace
|
|
19
|
+
dw.__dwAnalytics = function () {
|
|
20
|
+
/************************************************************
|
|
21
|
+
* Private data
|
|
22
|
+
************************************************************/
|
|
23
|
+
|
|
24
|
+
var MAX_URL_LENGTH = 2000;
|
|
25
|
+
|
|
26
|
+
var expireDateTime,
|
|
27
|
+
|
|
28
|
+
/* plugins */
|
|
29
|
+
plugins = {},
|
|
30
|
+
|
|
31
|
+
/* alias frequently used globals for added minification */
|
|
32
|
+
documentAlias = document,
|
|
33
|
+
navigatorAlias = navigator,
|
|
34
|
+
screenAlias = screen,
|
|
35
|
+
windowAlias = window,
|
|
36
|
+
hostnameAlias = windowAlias.location.hostname;
|
|
37
|
+
|
|
38
|
+
/************************************************************
|
|
39
|
+
* Private methods
|
|
40
|
+
************************************************************/
|
|
41
|
+
|
|
42
|
+
/*
|
|
43
|
+
* Is property (or variable) defined?
|
|
44
|
+
*/
|
|
45
|
+
function isDefined(property) {
|
|
46
|
+
return typeof property !== 'undefined';
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/*
|
|
50
|
+
* DWAnalytics Tracker class
|
|
51
|
+
*
|
|
52
|
+
* trackerUrl and trackerSiteId are optional arguments to the constructor
|
|
53
|
+
*
|
|
54
|
+
* See: Tracker.setTrackerUrl() and Tracker.setSiteId()
|
|
55
|
+
*/
|
|
56
|
+
function Tracker(trackerUrl, siteId) {
|
|
57
|
+
/************************************************************
|
|
58
|
+
* Private members
|
|
59
|
+
************************************************************/
|
|
60
|
+
|
|
61
|
+
var // Tracker URL
|
|
62
|
+
configTrackerUrl = trackerUrl + '?' || '?',
|
|
63
|
+
|
|
64
|
+
// Document URL
|
|
65
|
+
configCustomUrl,
|
|
66
|
+
|
|
67
|
+
// Document title
|
|
68
|
+
configTitle = documentAlias.title,
|
|
69
|
+
|
|
70
|
+
// Client-side data collection
|
|
71
|
+
browserHasCookies = '0',
|
|
72
|
+
pageReferrer,
|
|
73
|
+
|
|
74
|
+
// Plugin, Parameter name, MIME type, detected
|
|
75
|
+
pluginMap = {
|
|
76
|
+
// document types
|
|
77
|
+
pdf: ['pdf', 'application/pdf', '0'],
|
|
78
|
+
// media players
|
|
79
|
+
quicktime: ['qt', 'video/quicktime', '0'],
|
|
80
|
+
realplayer: ['realp', 'audio/x-pn-realaudio-plugin', '0'],
|
|
81
|
+
wma: ['wma', 'application/x-mplayer2', '0'],
|
|
82
|
+
// interactive multimedia
|
|
83
|
+
director: ['dir', 'application/x-director', '0'],
|
|
84
|
+
flash: ['fla', 'application/x-shockwave-flash', '0'],
|
|
85
|
+
// RIA
|
|
86
|
+
java: ['java', 'application/x-java-vm', '0'],
|
|
87
|
+
gears: ['gears', 'application/x-googlegears', '0'],
|
|
88
|
+
silverlight: ['ag', 'application/x-silverlight', '0']
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
// Guard against installing the link tracker more than once per Tracker instance
|
|
92
|
+
linkTrackingInstalled = false,
|
|
93
|
+
|
|
94
|
+
/*
|
|
95
|
+
* encode or escape
|
|
96
|
+
* - encodeURIComponent added in IE5.5
|
|
97
|
+
*/
|
|
98
|
+
escapeWrapper = windowAlias.encodeURIComponent || escape,
|
|
99
|
+
|
|
100
|
+
/*
|
|
101
|
+
* decode or unescape
|
|
102
|
+
* - decodeURIComponent added in IE5.5
|
|
103
|
+
*/
|
|
104
|
+
unescapeWrapper = windowAlias.decodeURIComponent || unescape,
|
|
105
|
+
|
|
106
|
+
/*
|
|
107
|
+
* registered (user-defined) hooks
|
|
108
|
+
*/
|
|
109
|
+
registeredHooks = {};
|
|
110
|
+
|
|
111
|
+
/*
|
|
112
|
+
* Set cookie value
|
|
113
|
+
*/
|
|
114
|
+
function setCookie(cookieName, value, daysToExpire, path, domain, secure) {
|
|
115
|
+
var expiryDate;
|
|
116
|
+
|
|
117
|
+
if (daysToExpire) {
|
|
118
|
+
// time is in milliseconds
|
|
119
|
+
expiryDate = new Date();
|
|
120
|
+
// there are 1000 * 60 * 60 * 24 milliseconds in a day (i.e., 86400000 or 8.64e7)
|
|
121
|
+
expiryDate.setTime(expiryDate.getTime() + daysToExpire * 8.64e7);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
documentAlias.cookie = cookieName + '=' + escapeWrapper(value) +
|
|
125
|
+
(daysToExpire ? ';expires=' + expiryDate.toGMTString() : '') +
|
|
126
|
+
';path=' + (path ? path : '/') +
|
|
127
|
+
(domain ? ';domain=' + domain : '') +
|
|
128
|
+
(secure ? ';secure' : '');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/*
|
|
132
|
+
* Get cookie value
|
|
133
|
+
*/
|
|
134
|
+
function getCookie(cookieName) {
|
|
135
|
+
var cookiePattern = new RegExp('(^|;)[ ]*' + cookieName + '=([^;]*)'),
|
|
136
|
+
|
|
137
|
+
cookieMatch = cookiePattern.exec(documentAlias.cookie);
|
|
138
|
+
|
|
139
|
+
return cookieMatch ? unescapeWrapper(cookieMatch[2]) : 0;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/*
|
|
143
|
+
* Send image request to DWAnalytics server using GET.
|
|
144
|
+
* The infamous web bug is a transparent, single pixel (1x1) image
|
|
145
|
+
* Async with a delay of 100ms.
|
|
146
|
+
*/
|
|
147
|
+
function getImage(urls) {
|
|
148
|
+
dw.__timeoutCallback = function()
|
|
149
|
+
{
|
|
150
|
+
for (var i = 0; i < urls.length; i++)
|
|
151
|
+
{
|
|
152
|
+
var image = new Image(1, 1);
|
|
153
|
+
image.onLoad = function () {};
|
|
154
|
+
image.src = urls[i];
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
setTimeout(dw.__timeoutCallback, 100);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/*
|
|
161
|
+
* Browser plugin tests
|
|
162
|
+
*/
|
|
163
|
+
function detectBrowserPlugins() {
|
|
164
|
+
var i, mimeType;
|
|
165
|
+
|
|
166
|
+
// Safari and Opera
|
|
167
|
+
// IE6: typeof navigator.javaEnabled == 'unknown'
|
|
168
|
+
if (typeof navigatorAlias.javaEnabled !== 'undefined' && navigatorAlias.javaEnabled()) {
|
|
169
|
+
pluginMap.java[2] = '1';
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Firefox
|
|
173
|
+
if (typeof windowAlias.GearsFactory === 'function') {
|
|
174
|
+
pluginMap.gears[2] = '1';
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (navigatorAlias.mimeTypes && navigatorAlias.mimeTypes.length) {
|
|
178
|
+
for (i in pluginMap) {
|
|
179
|
+
mimeType = navigatorAlias.mimeTypes[pluginMap[i][1]];
|
|
180
|
+
if (mimeType && mimeType.enabledPlugin) {
|
|
181
|
+
pluginMap[i][2] = '1';
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/*
|
|
188
|
+
* Get page referrer
|
|
189
|
+
*/
|
|
190
|
+
function getReferrer() {
|
|
191
|
+
var referrer = '';
|
|
192
|
+
try {
|
|
193
|
+
referrer = top.document.referrer;
|
|
194
|
+
} catch (e) {
|
|
195
|
+
if (parent) {
|
|
196
|
+
try {
|
|
197
|
+
referrer = parent.document.referrer;
|
|
198
|
+
} catch (e2) {
|
|
199
|
+
referrer = '';
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
if (referrer === '') {
|
|
204
|
+
referrer = documentAlias.referrer;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return referrer;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/*
|
|
211
|
+
* Does browser have cookies enabled (for this site)?
|
|
212
|
+
*/
|
|
213
|
+
function hasCookies() {
|
|
214
|
+
var testCookieName = '_pk_testcookie';
|
|
215
|
+
if (!isDefined(navigatorAlias.cookieEnabled)) {
|
|
216
|
+
setCookie(testCookieName, '1');
|
|
217
|
+
return getCookie(testCookieName) == '1' ? '1' : '0';
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return navigatorAlias.cookieEnabled ? '1' : '0';
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/*
|
|
224
|
+
* Log the page view / visit
|
|
225
|
+
*/
|
|
226
|
+
function logPageView(analyticsContext, collectedData, customTitle) {
|
|
227
|
+
var id = Math.random();
|
|
228
|
+
|
|
229
|
+
var tuples = constructDataSet(analyticsContext, collectedData, customTitle, id);
|
|
230
|
+
|
|
231
|
+
if (collectedData != null && collectedData.debugEnabled) {
|
|
232
|
+
var text = '';
|
|
233
|
+
for (var i = 0; i < tuples.length; i++)
|
|
234
|
+
{
|
|
235
|
+
text += tuples[i][0] + '"=' + tuples[i][1] + '"\n';
|
|
236
|
+
}
|
|
237
|
+
alert(text);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
var urls = createUrls(analyticsContext, configTrackerUrl, tuples, id);
|
|
242
|
+
getImage(urls);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/************************************************************
|
|
246
|
+
* Constructor
|
|
247
|
+
************************************************************/
|
|
248
|
+
|
|
249
|
+
/*
|
|
250
|
+
* initialize tracker
|
|
251
|
+
*/
|
|
252
|
+
pageReferrer = getReferrer();
|
|
253
|
+
browserHasCookies = hasCookies();
|
|
254
|
+
detectBrowserPlugins();
|
|
255
|
+
|
|
256
|
+
try {
|
|
257
|
+
process_anact_cookie();
|
|
258
|
+
} catch (err) {};
|
|
259
|
+
|
|
260
|
+
/************************************************************
|
|
261
|
+
* Public data and methods
|
|
262
|
+
************************************************************/
|
|
263
|
+
|
|
264
|
+
return {
|
|
265
|
+
/*
|
|
266
|
+
* Log visit to this page (called from the bottom of the page).
|
|
267
|
+
*/
|
|
268
|
+
trackPageView: function (customTitle) {
|
|
269
|
+
logPageView(null, null, customTitle);
|
|
270
|
+
},
|
|
271
|
+
/*
|
|
272
|
+
* Log visit to this page (called from the dwac script).
|
|
273
|
+
*/
|
|
274
|
+
trackPageViewWithProducts: function (analyticsContext, collectedData, customTitle) {
|
|
275
|
+
logPageView(analyticsContext, collectedData, customTitle);
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
function appendToRequest(/*Array*/ tuple, /*string*/ request) {
|
|
281
|
+
|
|
282
|
+
var beginningChar = request.charAt(request.length - 1) == '?' ? '' : '&';
|
|
283
|
+
return request + beginningChar + tuple[0] + "=" + tuple[1];
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function lengthOfTuple(/*Array*/ tuple) {
|
|
287
|
+
return tuple[0].length + tuple[1].length + 2;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function constructDataSet(/*object*/ analyticsContext, collectedData, /*string*/ customTitle, /*number*/ id) {
|
|
291
|
+
var tuples = [
|
|
292
|
+
["url", escapeWrapper(isDefined(configCustomUrl) ? configCustomUrl : documentAlias.location.href)],
|
|
293
|
+
["res", screenAlias.width + 'x' + screenAlias.height],
|
|
294
|
+
["cookie", browserHasCookies],
|
|
295
|
+
["ref", escapeWrapper(pageReferrer)],
|
|
296
|
+
["title", escapeWrapper(isDefined(customTitle) && customTitle != null ? customTitle : configTitle)]
|
|
297
|
+
];
|
|
298
|
+
|
|
299
|
+
// plugin data
|
|
300
|
+
for (var index in pluginMap) {
|
|
301
|
+
tuples.push([pluginMap[index][0], pluginMap[index][2]])
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if (analyticsContext != null && analyticsContext.dwEnabled)
|
|
305
|
+
{
|
|
306
|
+
tuples.push(["dwac", id]);
|
|
307
|
+
tuples.push(["cmpn", analyticsContext.sourceCode]);
|
|
308
|
+
tuples.push(["tz", analyticsContext.timeZone]);
|
|
309
|
+
|
|
310
|
+
analyticsContext.category = dw.ac._category;
|
|
311
|
+
if (dw.ac._searchData) {
|
|
312
|
+
analyticsContext.searchData = dw.ac._searchData;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
addProducts(analyticsContext, collectedData, tuples);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
return tuples;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function addProducts(/*object*/ analyticsContext, /*object*/ collectedData, /*Array*/ tuples)
|
|
322
|
+
{
|
|
323
|
+
tuples.push(["pcc", analyticsContext.siteCurrency]);
|
|
324
|
+
tuples.push(["pct", analyticsContext.customer]);
|
|
325
|
+
tuples.push(["pcat", analyticsContext.category]);
|
|
326
|
+
if (analyticsContext.searchData) {
|
|
327
|
+
if (analyticsContext.searchData.q) tuples.push(["pst-q", analyticsContext.searchData.q]);
|
|
328
|
+
if (analyticsContext.searchData.searchID) tuples.push(["pst-id", analyticsContext.searchData.searchID]);
|
|
329
|
+
if (analyticsContext.searchData.refs) tuples.push(["pst-refs", analyticsContext.searchData.refs]);
|
|
330
|
+
if (analyticsContext.searchData.sort) tuples.push(["pst-sort", analyticsContext.searchData.sort]);
|
|
331
|
+
if (undefined != analyticsContext.searchData.persd) tuples.push(["pst-pers", analyticsContext.searchData.persd]);
|
|
332
|
+
if (analyticsContext.searchData.imageUUID) tuples.push(["pst-img", analyticsContext.searchData.imageUUID]);
|
|
333
|
+
if (analyticsContext.searchData.suggestedSearchText) tuples.push(["pst-sug", analyticsContext.searchData.suggestedSearchText]);
|
|
334
|
+
if (analyticsContext.searchData.locale) tuples.push(["pst-loc", analyticsContext.searchData.locale]);
|
|
335
|
+
if (analyticsContext.searchData.queryLocale) tuples.push(["pst-qloc", analyticsContext.searchData.queryLocale]);
|
|
336
|
+
if (undefined != analyticsContext.searchData.showProducts) tuples.push(["pst-show", analyticsContext.searchData.showProducts]);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
var pies = collectedData.productImpressions.getEntries();
|
|
340
|
+
var pres = collectedData.productRecommendations.getEntries();
|
|
341
|
+
var pves = collectedData.productViews.getEntries();
|
|
342
|
+
|
|
343
|
+
var count = 0;
|
|
344
|
+
for (var i = 0; i < pies.length; i++) {
|
|
345
|
+
tuples.push([("pid-" + count), pies[i].value.id]);
|
|
346
|
+
tuples.push([("pev-" + count), "event3"]);
|
|
347
|
+
count++;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
for (var j = 0; j < pres.length; j++) {
|
|
351
|
+
tuples.push([("pid-" + count), pres[j].value.id]);
|
|
352
|
+
tuples.push([("pev-" + count), "event3"]);
|
|
353
|
+
tuples.push([("evr4-" + count), 'Yes']);
|
|
354
|
+
count++;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
for (var k = 0; k < pves.length; k++) {
|
|
358
|
+
tuples.push([("pid-" + count), pves[k].value.id]);
|
|
359
|
+
tuples.push([("pev-" + count), "event4"]);
|
|
360
|
+
count++;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function createUrls(analyticsContext, configTrackerUrl, tuples, id) {
|
|
365
|
+
var urls = [];
|
|
366
|
+
var request = configTrackerUrl;
|
|
367
|
+
for (var i = 0; i < tuples.length; i++) {
|
|
368
|
+
// we don't want to break up a product grouping, for example,
|
|
369
|
+
// ["pid-0","p1"],["pev-0","event3"],["evr4-0",'Yes'] should not be broken into two separate requests
|
|
370
|
+
var nextTupleIsProductAndWouldMakeRequestTooLong = (tuples[i][0].slice(0, "pid-".length) == "pid-")
|
|
371
|
+
&& (lengthOfTuple(tuples[i])
|
|
372
|
+
+ ((i + 1) < tuples.length ? lengthOfTuple(tuples[i + 1]) : 0)
|
|
373
|
+
+ ((i + 2) < tuples.length ? lengthOfTuple(tuples[i + 2]) : 0)
|
|
374
|
+
+ request.length > MAX_URL_LENGTH);
|
|
375
|
+
|
|
376
|
+
var nextTupleIsNotProductAndWouldMakeRequestTooLong = (tuples[i][0].slice(0, "pid-".length) != "pid-")
|
|
377
|
+
&& (lengthOfTuple(tuples[i]) + request.length > MAX_URL_LENGTH);
|
|
378
|
+
|
|
379
|
+
if (nextTupleIsProductAndWouldMakeRequestTooLong || nextTupleIsNotProductAndWouldMakeRequestTooLong) {
|
|
380
|
+
urls.push(request);
|
|
381
|
+
// close the current request and create a new one,
|
|
382
|
+
// the new request should have the basic dwac, cmpn,tz, pcc, pct, pcat values
|
|
383
|
+
request = appendToRequest(["dwac", id], configTrackerUrl);
|
|
384
|
+
if (analyticsContext != null && analyticsContext.dwEnabled) {
|
|
385
|
+
request = appendToRequest(["cmpn", analyticsContext.sourceCode], request);
|
|
386
|
+
request = appendToRequest(["tz", analyticsContext.timeZone], request);
|
|
387
|
+
request = appendToRequest(["pcc", analyticsContext.siteCurrency], request);
|
|
388
|
+
request = appendToRequest(["pct", analyticsContext.customer], request);
|
|
389
|
+
request = appendToRequest(["pcat", analyticsContext.category], request);
|
|
390
|
+
if (analyticsContext.searchData) {
|
|
391
|
+
if (analyticsContext.searchData.q) appendToRequest(["pst-q", analyticsContext.searchData.q], request);
|
|
392
|
+
if (analyticsContext.searchData.searchID) appendToRequest(["pst-id", analyticsContext.searchData.searchID], request);
|
|
393
|
+
if (analyticsContext.searchData.refs) appendToRequest(["pst-refs", JSON.stringify(analyticsContext.searchData.refs)], request);
|
|
394
|
+
if (analyticsContext.searchData.sort) appendToRequest(["pst-sort", JSON.stringify(analyticsContext.searchData.sort)], request);
|
|
395
|
+
if (undefined != analyticsContext.searchData.persd) appendToRequest(["pst-pers", analyticsContext.searchData.persd], request);
|
|
396
|
+
if (analyticsContext.searchData.imageUUID) appendToRequest(["pst-img", analyticsContext.searchData.imageUUID], request);
|
|
397
|
+
if (analyticsContext.searchData.suggestedSearchText) appendToRequest(["pst-sug", analyticsContext.searchData.suggestedSearchText], request);
|
|
398
|
+
if (analyticsContext.searchData.locale) appendToRequest(["pst-loc", analyticsContext.searchData.locale], request);
|
|
399
|
+
if (analyticsContext.searchData.queryLocale) appendToRequest(["pst-qloc", analyticsContext.searchData.queryLocale], request);
|
|
400
|
+
if (undefined != analyticsContext.searchData.showProducts) appendToRequest(["pst-show", analyticsContext.searchData.showProducts], request);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
request = appendToRequest(tuples[i], request);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// Add the "do not follow" cookie in the URL as a query param
|
|
409
|
+
// The cookie is set per-site, and gets applied to all sub-sites, if present
|
|
410
|
+
var doNotFollowCookieValue = getCookie('dw_dnt');
|
|
411
|
+
|
|
412
|
+
// If cookie not found
|
|
413
|
+
if (doNotFollowCookieValue === 0
|
|
414
|
+
|| doNotFollowCookieValue === ''
|
|
415
|
+
|| doNotFollowCookieValue === null
|
|
416
|
+
|| doNotFollowCookieValue === false) {
|
|
417
|
+
// do nothing, meaning tracking is allowed
|
|
418
|
+
}
|
|
419
|
+
// Cookie found, i.e. value should be '0' or '1' (string values)
|
|
420
|
+
else {
|
|
421
|
+
// Set whatever the cookie value is
|
|
422
|
+
request = appendToRequest([ "dw_dnt", doNotFollowCookieValue ], request);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
urls.push(request);
|
|
426
|
+
return urls;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
function extractCookieValueAndRemoveCookie(cookieName) {
|
|
431
|
+
var cookieValue = extractEncodedCookieValue (cookieName);
|
|
432
|
+
if (cookieValue) {
|
|
433
|
+
document.cookie = cookieName + '=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT;';
|
|
434
|
+
}
|
|
435
|
+
return cookieValue;
|
|
436
|
+
};
|
|
437
|
+
|
|
438
|
+
function extractEncodedCookieValue (cookieName) {
|
|
439
|
+
return decodeURIComponent (
|
|
440
|
+
document.cookie.replace(
|
|
441
|
+
new RegExp('(?:(?:^|.*;)\\s*'
|
|
442
|
+
+ encodeURIComponent(cookieName).replace(/[\-\.\+\*]/g, '\\$&')
|
|
443
|
+
+ '\\s*\\=\\s*([^;]*).*$)|^.*$')
|
|
444
|
+
, '$1').replace(/\+/g, '%20')
|
|
445
|
+
) || null;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
function process_anact_cookie() {
|
|
449
|
+
if (dw.ac) {
|
|
450
|
+
dw.ac._anact=extractCookieValueAndRemoveCookie('__anact');
|
|
451
|
+
if ( dw.ac._anact && !dw.ac.eventsIsEmpty() ) {
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
if ( dw.ac._anact_nohit_tag || dw.ac._anact ) {
|
|
455
|
+
var unescaped = dw.ac._anact_nohit_tag ? dw.ac._anact_nohit_tag : dw.ac._anact;
|
|
456
|
+
var jsonPayload = JSON.parse(unescaped);
|
|
457
|
+
if (jsonPayload) {
|
|
458
|
+
var payload = Array.isArray(jsonPayload) ? jsonPayload[0] : jsonPayload;
|
|
459
|
+
if (payload
|
|
460
|
+
&& 'viewSearch' == payload.activityType
|
|
461
|
+
&& payload.parameters) {
|
|
462
|
+
var params = payload.parameters;
|
|
463
|
+
var search_params = {};
|
|
464
|
+
search_params.q = params.searchText;
|
|
465
|
+
search_params.suggestedSearchText = params.suggestedSearchText;
|
|
466
|
+
search_params.persd = params.personalized;
|
|
467
|
+
search_params.refs = params.refinements;
|
|
468
|
+
search_params.sort = params.sorting_rule;
|
|
469
|
+
search_params.imageUUID = params.image_uuid;
|
|
470
|
+
search_params.showProducts = params.showProducts;
|
|
471
|
+
search_params.searchID = params.searchID;
|
|
472
|
+
search_params.locale = params.locale;
|
|
473
|
+
search_params.queryLocale = params.queryLocale;
|
|
474
|
+
dw.ac.applyContext({searchData: search_params});
|
|
475
|
+
var products = params.products;
|
|
476
|
+
if (products && Array.isArray(products)) {
|
|
477
|
+
for (i = 0; i < products.length; i++) {
|
|
478
|
+
if (products[i]) {
|
|
479
|
+
dw.ac._capture({ id : products[i].id, type : dw.ac.EV_PRD_SEARCHHIT });
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
};
|
|
488
|
+
|
|
489
|
+
/************************************************************
|
|
490
|
+
* Public data and methods
|
|
491
|
+
************************************************************/
|
|
492
|
+
|
|
493
|
+
return {
|
|
494
|
+
/*
|
|
495
|
+
* Get Tracker
|
|
496
|
+
*/
|
|
497
|
+
getTracker: function (analyticsUrl) {
|
|
498
|
+
return new Tracker(analyticsUrl);
|
|
499
|
+
}
|
|
500
|
+
};
|
|
501
|
+
}();
|
|
502
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
var dw = (window.dw || {});
|
|
2
|
+
dw.ac = {
|
|
3
|
+
_analytics: null,
|
|
4
|
+
_events: [],
|
|
5
|
+
_category: "",
|
|
6
|
+
_searchData: "",
|
|
7
|
+
_anact: "",
|
|
8
|
+
_anact_nohit_tag: "",
|
|
9
|
+
_analytics_enabled: "true",
|
|
10
|
+
_timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
11
|
+
_capture: function(configs) {
|
|
12
|
+
if (Object.prototype.toString.call(configs) === "[object Array]") {
|
|
13
|
+
configs.forEach(captureObject);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
dw.ac._events.push(configs);
|
|
17
|
+
},
|
|
18
|
+
capture: function() {
|
|
19
|
+
dw.ac._capture(arguments);
|
|
20
|
+
// send to CQ as well:
|
|
21
|
+
if (window.CQuotient) {
|
|
22
|
+
window.CQuotient.trackEventsFromAC(arguments);
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
EV_PRD_SEARCHHIT: "searchhit",
|
|
26
|
+
EV_PRD_DETAIL: "detail",
|
|
27
|
+
EV_PRD_RECOMMENDATION: "recommendation",
|
|
28
|
+
EV_PRD_SETPRODUCT: "setproduct",
|
|
29
|
+
applyContext: function(context) {
|
|
30
|
+
if (typeof context === "object" && context.hasOwnProperty("category")) {
|
|
31
|
+
dw.ac._category = context.category;
|
|
32
|
+
}
|
|
33
|
+
if (typeof context === "object" && context.hasOwnProperty("searchData")) {
|
|
34
|
+
dw.ac._searchData = context.searchData;
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
setDWAnalytics: function(analytics) {
|
|
38
|
+
dw.ac._analytics = analytics;
|
|
39
|
+
},
|
|
40
|
+
eventsIsEmpty: function() {
|
|
41
|
+
return 0 == dw.ac._events.length;
|
|
42
|
+
}
|
|
43
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/pwa-kit-create-app",
|
|
3
|
-
"version": "3.3.0
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"description": "Salesforce's project generator tool",
|
|
5
5
|
"homepage": "https://github.com/SalesforceCommerceCloud/pwa-kit/tree/develop/packages/pwa-kit-create-app#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -38,13 +38,13 @@
|
|
|
38
38
|
"tar": "^6.1.13"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@salesforce/pwa-kit-dev": "3.3.0
|
|
42
|
-
"internal-lib-build": "3.3.0
|
|
41
|
+
"@salesforce/pwa-kit-dev": "3.3.0",
|
|
42
|
+
"internal-lib-build": "3.3.0",
|
|
43
43
|
"verdaccio": "^5.22.1"
|
|
44
44
|
},
|
|
45
45
|
"engines": {
|
|
46
46
|
"node": "^16.11.0 || ^18.0.0",
|
|
47
|
-
"npm": "^8.0.0 || ^9.0.0"
|
|
47
|
+
"npm": "^8.0.0 || ^9.0.0 || ^10.0.0"
|
|
48
48
|
},
|
|
49
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "93894bb7d823f3510e10affdb1eb8e6750b25822"
|
|
50
50
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|