-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathevgHelpers.js
181 lines (176 loc) · 8.46 KB
/
evgHelpers.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
var evgHelpers = {
//Brightlog - console.log messages appear in a highlighed colour in the browser.
//Useful for debugging.
//Usage: evgHelpers.brightLog(<message>,<(OPTIONAL)hex colour code>)
brightLog: function(m, c='#0095da') {
console.log(`%cEvergage::-> ${m}`, `color: white;background-color:${c};font-size:10px`)
},
//cleanString returns a string stripped of certain non [a-zA-Z] characters in languages such as
//Turkish are not supported by IS at this time.
//Usage: evgHelpers.cleanString(<string>)
cleanString: function(i) {
return i().replace(/[^\x20-\x7E]/g, '')
},
//capThis returns a string with the first letter capitalised. Useful for catalog items.
capThis: function(w) {
if (w) return [w.charAt(0).toUpperCase() + w.slice(1)]
},
//simpleURLParam consumes URL parameters and returns the parameter found at a specific position
//NOTE: THIS ASSUMES THAT THE ORDER OF URL PARAMS IS CONSISTENT - IT DOES NOT TAKE THE KEY INTO ACCOUNT
//OR MATCH THE KEY TO AN ATTRIBUTE!
//Use this in config.global.onActionEvent as follows:
//const qsMapping = { source:evgHelpers.domain(0),utmtags:evgHelpers.urlParam(1)}
//event.user = event.user || {};
//event.user.attributes = event.user.attributes || {};
//event.user.attributes.camefrom = qsMapping.domain;
//event.user.attributes.campaigntags = qsMapping.utmtags;
simpleURLParam: function (pos) {
let qs = window.location.href.split('?')[1].split("&")
qs.forEach(function(part, i) {
this[i] = this[i].substring(this[i].indexOf("=") + 1)
}, qs);
return qs[pos];
},
//findBiggestImage returns the src of the biggest image found on the page. Useful for catalog building.
//There is a filer on this example of images that have an src containing 'hover'. This is to
//differentiate product images from others on the page. You will need to adjust this to reflect
// your brand.
//Usage: evgHelpers.findBiggestImage()
findBiggestImage: function () {
let imgElements = document.getElementsByTagName('img');
let maxDimension = 0;
let maxImage = null;
for (var index in imgElements) {
var img = imgElements[index];
var currDimension = img.width * img.height;
if (currDimension > maxDimension && !img.src.includes("hover")){
maxDimension = currDimension
maxImage = img;
}
}
if (maxImage) return (maxImage.src);
},
//waitForElement waits for a specific element to appear before trying to do anything with it. This is the recommended approach from Salesforce/ Evergage
// in the event of an element not appearing immediately as it is non-blocking. It returns a promise:
//// - resolved if the element is found within x time
//// - rejected if the element does not appear in time
// Use the following code in your sitemap to call this function:
/*
evgHelpers.waitForElement("#nn-vue-fieldid-phoneNumber")
.then((res)=>{/*Do something now we have the value*//*})
.catch((error) => {console.log('error '+error)});
*/
waitForElement: function(el) {
return new Promise((resolve, reject) => {
let c=0
let int = setInterval(_=>{
if (document.querySelector(el)) {
clearInterval(int)
let i = el
resolve(i)
}
else {
c < 100 && c++
console.log('plus',c)
if(c >= 10) {
clearInterval(int)
reject('We didnt see the element and waited long enough.')
}
}
},100)
});
},
//getDatalayer waits for the datalayer to become accessible to the browser, then it returns
//a resolved promise that contains the Krux DL object. It tries 10 times then gives up if not found
//See DATALAYER code block below for a full example of using this.
getDataLayer: async function() {
return await new Promise((resolve, reject) => {
let c=0
let int = setInterval(_=>{
if (window.DataLayerKrx){
clearInterval(int)
let i = window.DataLayerKrx
return resolve(i)
}
else{
c < 10 && c++
if(c >= 10) {
clearInterval(int)
return reject('This page appears to have no Krux datalayer')
}
}
},300)
});
},
//readFromDataLayer takes the DataLayer, as returned from the function above, and the value to capture
//and returns the value you want in a form that IS can consume. This can be used for a user profile
//or dyamic catalogue building.
//See DATALAYER code block below for a full example of using these together.
readFromDataLayer: function (DL, value){
switch(typeof DL[value]) {
case 'string':
return unescape(encodeURI(DL[value]))
break;
case 'object':
return DL[value].map(v => unescape(encodeURI(v.name)));
break;
}
console.log(`Found something we didn't account for: ${typeof DL[value]} is a ${value}`)
}
}
//END OF HELPERS
/////////////////////////////////////////////////////
//DATALAYER EXAMPLE
//THE BELOW IS AN EXAMPLE OF USING MULTIPLE HELPERS FROM ABOVE TO POPULATE THE CATALOG.
//THIS CODE NEEDS TO BE FIRED AFTER EVERGAGE.INIT HAS RESOLVED. (I.E. INERT IT IN THE .then(()=>{})
const waitForDataLayer = (evgHelpers.getDataLayer()
.then(function(DL) {
evgHelpers.brightLog(`Returned datalayer:`, 'green')
console.log(DL)
const theCategory = [evgHelpers.readFromDataLayer(DL,'primaryCategory')]
const theGeo = evgHelpers.readFromDataLayer(DL,'geoRegion')
const theLanguage = evgHelpers.readFromDataLayer(DL,'language')
const theSubCategory = evgHelpers.readFromDataLayer(DL,'subCategory1')
const theTitle = evgHelpers.readFromDataLayer(DL,'pageTitle')
const theTheme = evgHelpers.readFromDataLayer(DL,'thematic')
//Next is an example of why we use a Helper as Tags is an array of objects in the datalayer and needs converting for IS.
const theTags = evgHelpers.readFromDataLayer(DL,'tags')
// In this next section you just send an event into IS that contains the data you want - in this case it
//creates an article and sets a 'viewed' action against the visitor.
//User attributes
const theAdblocker = evgHelpers.readFromDataLayer(DL,'adblocker')
const theUserType = evgHelpers.readFromDataLayer(DL,'userType')
const theProfileID = evgHelpers.readFromDataLayer(DL,'profileID')
const theRaisedPaywall = evgHelpers.readFromDataLayer(DL,'raisedPaywall')
Evergage.sendEvent({
action: 'Viewed an Article',
itemAction: Evergage.ItemAction.ViewItem,
catalog: {
Article: {
_id: theTitle.substring(0, 20).replace(/[^\x20-\x7E]/g, ''),
name: theTitle,
url: window.location.href,
imageUrl: evgHelpers.findBiggestImage(),
dimensions:{
ItemClass: theCategory,
Tags: theTags
}
}
}
});
Evergage.sendEvent({
action: 'User Visit',
user: {
id: theProfileID,
attributes:{
adblocker: theAdblocker,
userType: theUserType,
raisedpaywall:theRaisedPaywall
}
}
});
})
.catch(e =>{
console.error(`Could not get datalayer: ${e}`)
})
);