choreograph-create-pixel 1.4.1 → 1.4.3
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/README.md +12 -12
- package/dist/bundle.cjs.js +115 -93
- package/dist/bundle.esm.js +115 -93
- package/dist/bundle.iife.min.js +2 -2
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Choreograph Create Pixel
|
|
2
2
|
|
|
3
|
-
This library lets you apply best practises to [Create](https://
|
|
3
|
+
This library lets you apply best practises to [Create](https://create.choreograph.com/) pixel development and implementation.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
@@ -11,25 +11,25 @@ This library lets you apply best practises to [Create](https://www.lemonpi.io/)
|
|
|
11
11
|
- [x] User interaction triggers
|
|
12
12
|
- [x] [Console debugger](#debugging)
|
|
13
13
|
|
|
14
|
-
### Scraper
|
|
14
|
+
### Scraper pixel
|
|
15
15
|
|
|
16
16
|
<small>Type: `scraper`</small>
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
A scraper pixel is used to scrape (collect) data from websites, and store that data as products within an advertiser's product store.
|
|
19
19
|
|
|
20
20
|
### Segment pixels
|
|
21
21
|
|
|
22
22
|
<small>Types: `viewed`, `basketed` and `purchased`</small>
|
|
23
23
|
|
|
24
|
-
Products in ads are
|
|
24
|
+
Products in ads are sorted by recommendation. Segment pixels determine this recommendation on a consumer level, by storing a **cookie** at different moments or events during the consumer's journey.
|
|
25
25
|
|
|
26
26
|
### Post-click pixels
|
|
27
27
|
|
|
28
28
|
<small>Types: `attribution` and `conversion`</small>
|
|
29
29
|
|
|
30
|
-
Post-click conversion attribution tracks which clicked creative variant attributed to a website conversion. The **attribution** pixel collects the creative's impression ID from the URL
|
|
30
|
+
Post-click conversion attribution tracks which clicked creative variant from an ad attributed to a website conversion. The **attribution** pixel collects and stores (through [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage)) the creative's impression ID from the landing URL's `ccpid` query parameter, and the **conversion** pixel logs this ID as a performance metric in Create whenever a user performed a conversion, like a purchase.
|
|
31
31
|
|
|
32
|
-
##
|
|
32
|
+
## Quick start
|
|
33
33
|
|
|
34
34
|
The following theoretical snippet includes all pixel types, can be embedded on every page of _example.com_, and will automatically determine which pixel to enable and disable through continuous URL validation.
|
|
35
35
|
|
|
@@ -38,7 +38,7 @@ The following theoretical snippet includes all pixel types, can be embedded on e
|
|
|
38
38
|
```js
|
|
39
39
|
import Pixel from "choreograph-create-pixel";
|
|
40
40
|
|
|
41
|
-
// Scraper pixel
|
|
41
|
+
// Scraper pixel example
|
|
42
42
|
new Pixel({
|
|
43
43
|
advertiser: 0,
|
|
44
44
|
type: "scraper",
|
|
@@ -59,7 +59,7 @@ new Pixel({
|
|
|
59
59
|
},
|
|
60
60
|
});
|
|
61
61
|
|
|
62
|
-
// Viewed segment pixel
|
|
62
|
+
// Viewed segment pixel example
|
|
63
63
|
new Pixel({
|
|
64
64
|
advertiser: 0,
|
|
65
65
|
type: "viewed",
|
|
@@ -69,7 +69,7 @@ new Pixel({
|
|
|
69
69
|
scrape: () => window.dataLayer[0].product.sku,
|
|
70
70
|
});
|
|
71
71
|
|
|
72
|
-
// Basketed segment pixel
|
|
72
|
+
// Basketed segment pixel example
|
|
73
73
|
new Pixel({
|
|
74
74
|
advertiser: 0,
|
|
75
75
|
type: "basketed",
|
|
@@ -85,7 +85,7 @@ new Pixel({
|
|
|
85
85
|
scrape: (element) => element.getAttribute("data-sku"),
|
|
86
86
|
});
|
|
87
87
|
|
|
88
|
-
// Purchased segment pixel
|
|
88
|
+
// Purchased segment pixel example
|
|
89
89
|
new Pixel({
|
|
90
90
|
advertiser: 0,
|
|
91
91
|
type: "purchased",
|
|
@@ -100,7 +100,7 @@ new Pixel({
|
|
|
100
100
|
scrape: () => window.dataLayer[0].cart.map((product) => product.sku),
|
|
101
101
|
});
|
|
102
102
|
|
|
103
|
-
// Attribution post-click pixel
|
|
103
|
+
// Attribution post-click pixel example
|
|
104
104
|
new Pixel({
|
|
105
105
|
advertiser: 0,
|
|
106
106
|
type: "attribution",
|
|
@@ -112,7 +112,7 @@ new Pixel({
|
|
|
112
112
|
url: /example\.com\/products\/\d/,
|
|
113
113
|
});
|
|
114
114
|
|
|
115
|
-
// Conversion post-click pixel
|
|
115
|
+
// Conversion post-click pixel example
|
|
116
116
|
new Pixel({
|
|
117
117
|
advertiser: 0,
|
|
118
118
|
type: "conversion",
|
package/dist/bundle.cjs.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! choreograph-create-pixel v1.4.
|
|
1
|
+
/*! choreograph-create-pixel v1.4.3 2024/08/27 */
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
class ChoreographCreatePixel {
|
|
@@ -85,8 +85,8 @@ class ChoreographCreatePixel {
|
|
|
85
85
|
if (!this.config.debug || this.logs.includes(message)) return;
|
|
86
86
|
|
|
87
87
|
const args = [
|
|
88
|
-
`%c⸬ create%c ${this.config.icons[this.config.type]} ${
|
|
89
|
-
this.config.
|
|
88
|
+
`%c⸬ create%c ${this.config.icons[this.config.type]} ${
|
|
89
|
+
this.config.type
|
|
90
90
|
} %c${message}`,
|
|
91
91
|
"background:black;color:white;border-radius:3px;padding:3px 6px",
|
|
92
92
|
"font-weight:bold",
|
|
@@ -196,6 +196,7 @@ class ChoreographCreatePixel {
|
|
|
196
196
|
}
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
+
// TO-DO: Move this to each method's end? Pageview conversions are currently recursive
|
|
199
200
|
setTimeout(() => this.cycle(), 750);
|
|
200
201
|
}
|
|
201
202
|
|
|
@@ -211,17 +212,23 @@ class ChoreographCreatePixel {
|
|
|
211
212
|
|
|
212
213
|
const storageItemLabel = `choreograph-${this.config.label}`;
|
|
213
214
|
const storedCcpid = localStorage.getItem(storageItemLabel);
|
|
215
|
+
|
|
216
|
+
if (storedCcpid === "")
|
|
217
|
+
return this.log("warn", `"${this.config.label}" already converted`);
|
|
218
|
+
|
|
214
219
|
if (storedCcpid !== ccpid) localStorage.setItem(storageItemLabel, ccpid);
|
|
215
|
-
this.log("success", "
|
|
220
|
+
this.log("success", `Stored CCPID "${ccpid}" for "${this.config.label}"`);
|
|
216
221
|
}
|
|
217
222
|
|
|
218
223
|
convert() {
|
|
219
|
-
const
|
|
224
|
+
const label = `choreograph-${this.config.label}`;
|
|
225
|
+
const ccpid = localStorage.getItem(label);
|
|
220
226
|
|
|
221
227
|
if (!ccpid)
|
|
222
228
|
return this.log("warn", `"${this.config.label}" attribution not present`);
|
|
223
229
|
|
|
224
230
|
this.send(ccpid);
|
|
231
|
+
localStorage.setItem(label, "");
|
|
225
232
|
}
|
|
226
233
|
|
|
227
234
|
scrape(element) {
|
|
@@ -294,113 +301,128 @@ class ChoreographCreatePixel {
|
|
|
294
301
|
}
|
|
295
302
|
|
|
296
303
|
send(data) {
|
|
304
|
+
let payload;
|
|
297
305
|
let url;
|
|
306
|
+
let method = "GET";
|
|
298
307
|
|
|
299
308
|
switch (this.config.type) {
|
|
300
|
-
case "scraper":
|
|
309
|
+
case "scraper": {
|
|
310
|
+
const { sku } = data;
|
|
311
|
+
delete data.sku;
|
|
312
|
+
|
|
313
|
+
payload = {
|
|
314
|
+
"advertiser-id": this.config.advertiser,
|
|
315
|
+
sku,
|
|
316
|
+
fields: data,
|
|
317
|
+
};
|
|
318
|
+
|
|
301
319
|
url = `https://d.lemonpi.io/scrapes${
|
|
302
320
|
this.config.debug ? "?validate=true" : ""
|
|
303
321
|
}`;
|
|
304
322
|
|
|
323
|
+
method = "POST";
|
|
305
324
|
break;
|
|
325
|
+
}
|
|
306
326
|
|
|
307
|
-
case "
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
"advertiser-id": this.config.advertiser,
|
|
315
|
-
})
|
|
316
|
-
)}`;
|
|
317
|
-
|
|
318
|
-
break;
|
|
327
|
+
case "viewed":
|
|
328
|
+
case "basketed":
|
|
329
|
+
case "purchased":
|
|
330
|
+
payload = {
|
|
331
|
+
"event-type": `product-${this.config.type}`,
|
|
332
|
+
sku: data,
|
|
333
|
+
};
|
|
319
334
|
|
|
320
|
-
default:
|
|
321
335
|
url = `https://d.lemonpi.io/a/${
|
|
322
336
|
this.config.advertiser
|
|
323
|
-
}/product/event?e=${encodeURIComponent(
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
337
|
+
}/product/event?e=${encodeURIComponent(JSON.stringify(payload))}`;
|
|
338
|
+
|
|
339
|
+
break;
|
|
340
|
+
|
|
341
|
+
case "conversion":
|
|
342
|
+
payload = {
|
|
343
|
+
version: 1,
|
|
344
|
+
type: "conversion",
|
|
345
|
+
name: this.config.label,
|
|
346
|
+
"conversion-attribution-id": data,
|
|
347
|
+
"advertiser-id": this.config.advertiser,
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
url = `https://content.lemonpi.io/track/event?e=${encodeURIComponent(
|
|
351
|
+
JSON.stringify(payload)
|
|
328
352
|
)}`;
|
|
329
353
|
|
|
330
354
|
break;
|
|
331
355
|
}
|
|
332
356
|
|
|
333
|
-
if (
|
|
357
|
+
if (
|
|
358
|
+
["viewed", "basketed", "purchased"].includes(this.config.type) &&
|
|
359
|
+
!this.config.debug
|
|
360
|
+
) {
|
|
334
361
|
new Image().src = url;
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
fetch(
|
|
366
|
+
url,
|
|
367
|
+
method === "POST"
|
|
368
|
+
? {
|
|
369
|
+
method: "POST",
|
|
370
|
+
headers: { "Content-Type": "application/json" },
|
|
371
|
+
body: JSON.stringify(payload),
|
|
372
|
+
}
|
|
373
|
+
: null
|
|
374
|
+
)
|
|
375
|
+
.then((response) =>
|
|
376
|
+
response
|
|
377
|
+
.json()
|
|
378
|
+
.then((result) => {
|
|
379
|
+
if (response.ok) {
|
|
380
|
+
this.log("warn", "Successful, with warnings. Details:", {
|
|
381
|
+
payload,
|
|
382
|
+
result,
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
try {
|
|
386
|
+
this.config.after(data);
|
|
387
|
+
} catch (error) {
|
|
388
|
+
this.log("error", error.message, {
|
|
389
|
+
after: this.config.after,
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
} else
|
|
393
|
+
this.log(
|
|
394
|
+
"error",
|
|
395
|
+
`Failed: ${response.status} (${response.statusText}). Details:`,
|
|
396
|
+
{ payload, result }
|
|
397
|
+
);
|
|
398
|
+
|
|
399
|
+
this.logs.length = 0;
|
|
400
|
+
})
|
|
401
|
+
.catch(() => {
|
|
402
|
+
if (response.ok) {
|
|
403
|
+
this.log("success", "Successful!", { payload });
|
|
404
|
+
|
|
405
|
+
try {
|
|
406
|
+
this.config.after(data);
|
|
407
|
+
} catch (error) {
|
|
408
|
+
this.log("error", error.message, {
|
|
409
|
+
after: this.config.after,
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
} else
|
|
413
|
+
this.log(
|
|
414
|
+
"error",
|
|
415
|
+
`Failed: ${response.status} (${response.statusText}). Details:`,
|
|
416
|
+
{ payload, response }
|
|
417
|
+
);
|
|
418
|
+
|
|
419
|
+
this.logs.length = 0;
|
|
420
|
+
})
|
|
349
421
|
)
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
if (response.ok) {
|
|
355
|
-
this.log("warn", "Successful, with warnings. Details:", result);
|
|
356
|
-
|
|
357
|
-
try {
|
|
358
|
-
this.config.after(data);
|
|
359
|
-
} catch (error) {
|
|
360
|
-
this.log("error", error.message, {
|
|
361
|
-
after: this.config.after,
|
|
362
|
-
});
|
|
363
|
-
}
|
|
364
|
-
} else
|
|
365
|
-
this.log(
|
|
366
|
-
"error",
|
|
367
|
-
`Failed: ${response.status} (${response.statusText}). Details:`,
|
|
368
|
-
result
|
|
369
|
-
);
|
|
370
|
-
|
|
371
|
-
this.logs.length = 0;
|
|
372
|
-
})
|
|
373
|
-
.catch(() => {
|
|
374
|
-
if (response.ok) {
|
|
375
|
-
this.log(
|
|
376
|
-
"success",
|
|
377
|
-
"Successful!",
|
|
378
|
-
["viewed", "basketed", "purchased"].includes(this.config.type)
|
|
379
|
-
? { sku: data }
|
|
380
|
-
: data
|
|
381
|
-
);
|
|
382
|
-
|
|
383
|
-
try {
|
|
384
|
-
this.config.after(data);
|
|
385
|
-
} catch (error) {
|
|
386
|
-
this.log("error", error.message, {
|
|
387
|
-
after: this.config.after,
|
|
388
|
-
});
|
|
389
|
-
}
|
|
390
|
-
} else
|
|
391
|
-
this.log(
|
|
392
|
-
"error",
|
|
393
|
-
`Failed: ${response.status} (${response.statusText}). Details:`,
|
|
394
|
-
response
|
|
395
|
-
);
|
|
396
|
-
|
|
397
|
-
this.logs.length = 0;
|
|
398
|
-
})
|
|
399
|
-
)
|
|
400
|
-
.catch((error) => {
|
|
401
|
-
this.log("error", `Failed: ${error.message}`);
|
|
402
|
-
this.logs.length = 0;
|
|
403
|
-
});
|
|
422
|
+
.catch((error) => {
|
|
423
|
+
this.log("error", `Failed: ${error.message}`, { payload });
|
|
424
|
+
this.logs.length = 0;
|
|
425
|
+
});
|
|
404
426
|
}
|
|
405
427
|
}
|
|
406
428
|
|
package/dist/bundle.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! choreograph-create-pixel v1.4.
|
|
1
|
+
/*! choreograph-create-pixel v1.4.3 2024/08/27 */
|
|
2
2
|
class ChoreographCreatePixel {
|
|
3
3
|
constructor(userConfig) {
|
|
4
4
|
this.previouslyScrapedHash = null;
|
|
@@ -83,8 +83,8 @@ class ChoreographCreatePixel {
|
|
|
83
83
|
if (!this.config.debug || this.logs.includes(message)) return;
|
|
84
84
|
|
|
85
85
|
const args = [
|
|
86
|
-
`%c⸬ create%c ${this.config.icons[this.config.type]} ${
|
|
87
|
-
this.config.
|
|
86
|
+
`%c⸬ create%c ${this.config.icons[this.config.type]} ${
|
|
87
|
+
this.config.type
|
|
88
88
|
} %c${message}`,
|
|
89
89
|
"background:black;color:white;border-radius:3px;padding:3px 6px",
|
|
90
90
|
"font-weight:bold",
|
|
@@ -194,6 +194,7 @@ class ChoreographCreatePixel {
|
|
|
194
194
|
}
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
+
// TO-DO: Move this to each method's end? Pageview conversions are currently recursive
|
|
197
198
|
setTimeout(() => this.cycle(), 750);
|
|
198
199
|
}
|
|
199
200
|
|
|
@@ -209,17 +210,23 @@ class ChoreographCreatePixel {
|
|
|
209
210
|
|
|
210
211
|
const storageItemLabel = `choreograph-${this.config.label}`;
|
|
211
212
|
const storedCcpid = localStorage.getItem(storageItemLabel);
|
|
213
|
+
|
|
214
|
+
if (storedCcpid === "")
|
|
215
|
+
return this.log("warn", `"${this.config.label}" already converted`);
|
|
216
|
+
|
|
212
217
|
if (storedCcpid !== ccpid) localStorage.setItem(storageItemLabel, ccpid);
|
|
213
|
-
this.log("success", "
|
|
218
|
+
this.log("success", `Stored CCPID "${ccpid}" for "${this.config.label}"`);
|
|
214
219
|
}
|
|
215
220
|
|
|
216
221
|
convert() {
|
|
217
|
-
const
|
|
222
|
+
const label = `choreograph-${this.config.label}`;
|
|
223
|
+
const ccpid = localStorage.getItem(label);
|
|
218
224
|
|
|
219
225
|
if (!ccpid)
|
|
220
226
|
return this.log("warn", `"${this.config.label}" attribution not present`);
|
|
221
227
|
|
|
222
228
|
this.send(ccpid);
|
|
229
|
+
localStorage.setItem(label, "");
|
|
223
230
|
}
|
|
224
231
|
|
|
225
232
|
scrape(element) {
|
|
@@ -292,113 +299,128 @@ class ChoreographCreatePixel {
|
|
|
292
299
|
}
|
|
293
300
|
|
|
294
301
|
send(data) {
|
|
302
|
+
let payload;
|
|
295
303
|
let url;
|
|
304
|
+
let method = "GET";
|
|
296
305
|
|
|
297
306
|
switch (this.config.type) {
|
|
298
|
-
case "scraper":
|
|
307
|
+
case "scraper": {
|
|
308
|
+
const { sku } = data;
|
|
309
|
+
delete data.sku;
|
|
310
|
+
|
|
311
|
+
payload = {
|
|
312
|
+
"advertiser-id": this.config.advertiser,
|
|
313
|
+
sku,
|
|
314
|
+
fields: data,
|
|
315
|
+
};
|
|
316
|
+
|
|
299
317
|
url = `https://d.lemonpi.io/scrapes${
|
|
300
318
|
this.config.debug ? "?validate=true" : ""
|
|
301
319
|
}`;
|
|
302
320
|
|
|
321
|
+
method = "POST";
|
|
303
322
|
break;
|
|
323
|
+
}
|
|
304
324
|
|
|
305
|
-
case "
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
"advertiser-id": this.config.advertiser,
|
|
313
|
-
})
|
|
314
|
-
)}`;
|
|
315
|
-
|
|
316
|
-
break;
|
|
325
|
+
case "viewed":
|
|
326
|
+
case "basketed":
|
|
327
|
+
case "purchased":
|
|
328
|
+
payload = {
|
|
329
|
+
"event-type": `product-${this.config.type}`,
|
|
330
|
+
sku: data,
|
|
331
|
+
};
|
|
317
332
|
|
|
318
|
-
default:
|
|
319
333
|
url = `https://d.lemonpi.io/a/${
|
|
320
334
|
this.config.advertiser
|
|
321
|
-
}/product/event?e=${encodeURIComponent(
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
335
|
+
}/product/event?e=${encodeURIComponent(JSON.stringify(payload))}`;
|
|
336
|
+
|
|
337
|
+
break;
|
|
338
|
+
|
|
339
|
+
case "conversion":
|
|
340
|
+
payload = {
|
|
341
|
+
version: 1,
|
|
342
|
+
type: "conversion",
|
|
343
|
+
name: this.config.label,
|
|
344
|
+
"conversion-attribution-id": data,
|
|
345
|
+
"advertiser-id": this.config.advertiser,
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
url = `https://content.lemonpi.io/track/event?e=${encodeURIComponent(
|
|
349
|
+
JSON.stringify(payload)
|
|
326
350
|
)}`;
|
|
327
351
|
|
|
328
352
|
break;
|
|
329
353
|
}
|
|
330
354
|
|
|
331
|
-
if (
|
|
355
|
+
if (
|
|
356
|
+
["viewed", "basketed", "purchased"].includes(this.config.type) &&
|
|
357
|
+
!this.config.debug
|
|
358
|
+
) {
|
|
332
359
|
new Image().src = url;
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
fetch(
|
|
364
|
+
url,
|
|
365
|
+
method === "POST"
|
|
366
|
+
? {
|
|
367
|
+
method: "POST",
|
|
368
|
+
headers: { "Content-Type": "application/json" },
|
|
369
|
+
body: JSON.stringify(payload),
|
|
370
|
+
}
|
|
371
|
+
: null
|
|
372
|
+
)
|
|
373
|
+
.then((response) =>
|
|
374
|
+
response
|
|
375
|
+
.json()
|
|
376
|
+
.then((result) => {
|
|
377
|
+
if (response.ok) {
|
|
378
|
+
this.log("warn", "Successful, with warnings. Details:", {
|
|
379
|
+
payload,
|
|
380
|
+
result,
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
try {
|
|
384
|
+
this.config.after(data);
|
|
385
|
+
} catch (error) {
|
|
386
|
+
this.log("error", error.message, {
|
|
387
|
+
after: this.config.after,
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
} else
|
|
391
|
+
this.log(
|
|
392
|
+
"error",
|
|
393
|
+
`Failed: ${response.status} (${response.statusText}). Details:`,
|
|
394
|
+
{ payload, result }
|
|
395
|
+
);
|
|
396
|
+
|
|
397
|
+
this.logs.length = 0;
|
|
398
|
+
})
|
|
399
|
+
.catch(() => {
|
|
400
|
+
if (response.ok) {
|
|
401
|
+
this.log("success", "Successful!", { payload });
|
|
402
|
+
|
|
403
|
+
try {
|
|
404
|
+
this.config.after(data);
|
|
405
|
+
} catch (error) {
|
|
406
|
+
this.log("error", error.message, {
|
|
407
|
+
after: this.config.after,
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
} else
|
|
411
|
+
this.log(
|
|
412
|
+
"error",
|
|
413
|
+
`Failed: ${response.status} (${response.statusText}). Details:`,
|
|
414
|
+
{ payload, response }
|
|
415
|
+
);
|
|
416
|
+
|
|
417
|
+
this.logs.length = 0;
|
|
418
|
+
})
|
|
347
419
|
)
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
if (response.ok) {
|
|
353
|
-
this.log("warn", "Successful, with warnings. Details:", result);
|
|
354
|
-
|
|
355
|
-
try {
|
|
356
|
-
this.config.after(data);
|
|
357
|
-
} catch (error) {
|
|
358
|
-
this.log("error", error.message, {
|
|
359
|
-
after: this.config.after,
|
|
360
|
-
});
|
|
361
|
-
}
|
|
362
|
-
} else
|
|
363
|
-
this.log(
|
|
364
|
-
"error",
|
|
365
|
-
`Failed: ${response.status} (${response.statusText}). Details:`,
|
|
366
|
-
result
|
|
367
|
-
);
|
|
368
|
-
|
|
369
|
-
this.logs.length = 0;
|
|
370
|
-
})
|
|
371
|
-
.catch(() => {
|
|
372
|
-
if (response.ok) {
|
|
373
|
-
this.log(
|
|
374
|
-
"success",
|
|
375
|
-
"Successful!",
|
|
376
|
-
["viewed", "basketed", "purchased"].includes(this.config.type)
|
|
377
|
-
? { sku: data }
|
|
378
|
-
: data
|
|
379
|
-
);
|
|
380
|
-
|
|
381
|
-
try {
|
|
382
|
-
this.config.after(data);
|
|
383
|
-
} catch (error) {
|
|
384
|
-
this.log("error", error.message, {
|
|
385
|
-
after: this.config.after,
|
|
386
|
-
});
|
|
387
|
-
}
|
|
388
|
-
} else
|
|
389
|
-
this.log(
|
|
390
|
-
"error",
|
|
391
|
-
`Failed: ${response.status} (${response.statusText}). Details:`,
|
|
392
|
-
response
|
|
393
|
-
);
|
|
394
|
-
|
|
395
|
-
this.logs.length = 0;
|
|
396
|
-
})
|
|
397
|
-
)
|
|
398
|
-
.catch((error) => {
|
|
399
|
-
this.log("error", `Failed: ${error.message}`);
|
|
400
|
-
this.logs.length = 0;
|
|
401
|
-
});
|
|
420
|
+
.catch((error) => {
|
|
421
|
+
this.log("error", `Failed: ${error.message}`, { payload });
|
|
422
|
+
this.logs.length = 0;
|
|
423
|
+
});
|
|
402
424
|
}
|
|
403
425
|
}
|
|
404
426
|
|
package/dist/bundle.iife.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! choreograph-create-pixel v1.4.
|
|
2
|
-
var ChoreographCreatePixel=function(){"use strict";function e(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function t(t){for(var r=1;r<arguments.length;r++){var
|
|
1
|
+
/*! choreograph-create-pixel v1.4.3 2024/08/27 */
|
|
2
|
+
var ChoreographCreatePixel=function(){"use strict";function e(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function t(t){for(var r=1;r<arguments.length;r++){var o=null!=arguments[r]?arguments[r]:{};r%2?e(Object(o),!0).forEach((function(e){n(t,e,o[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(o)):e(Object(o)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(o,e))}))}return t}function r(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,o(n.key),n)}}function n(e,t,r){return(t=o(t))in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function o(e){var t=function(e,t){if("object"!=typeof e||null===e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var n=r.call(e,t||"default");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:String(t)}var i=function(){function e(r){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.previouslyScrapedHash=null,this.logs=[],this.config=t({colors:{error:"red",warn:"orange",success:"green"},icons:{scraper:"📚",viewed:"👀",basketed:"🛒",purchased:"🧾",attribution:"🔖",conversion:"📈"},debug:/(pixel|lemonpi)_debug/i.test(location.href),before:function(e,t){return t(e)},after:function(){},optional:[]},r),this.validateConfig()&&this.cycle()}var o,i,c;return o=e,i=[{key:"log",value:function(e,t){var r,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;if(this.config.debug&&!this.logs.includes(t)){var o=["%c⸬ create%c ".concat(this.config.icons[this.config.type]," ").concat(this.config.type," %c").concat(t),"background:black;color:white;border-radius:3px;padding:3px 6px","font-weight:bold","color:".concat(this.config.colors[e])];n&&o.push(n),(r=console).info.apply(r,o),this.logs.push(t)}}},{key:"validateConfig",value:function(){if("number"!=typeof this.config.advertiser)this.log("error","Please use a number",{advertiser:this.config.advertiser});else if(["scraper","viewed","basketed","purchased","attribution","conversion"].includes(this.config.type))if(["attribution","conversion"].includes(this.config.type)&&"string"!=typeof this.config.label)this.log("error","Please use a string",{label:this.config.label});else if(this.config.url instanceof RegExp){if(["attribution","conversion"].includes(this.config.type)||this.config.scrape)return!0;this.log("error","Please provide something to scrape",{scrape:this.config.scrape})}else this.log("error","Please use a regular expression",{url:this.config.url});else this.log("error","Please use scraper, viewed, basketed, purchased, attribution or conversion",{type:this.config.type})}},{key:"cycle",value:function(){var e=this;if(this.config.url.test(location.href))if("scraper"===this.config.type&&document.querySelector('html[class*="translated-"]'))this.log("warn","This page has been translated by the browser, and won't be scraped");else if(this.config.trigger){var t="create-".concat(this.config.type,"-").concat(this.config.trigger.event);try{var r="string"==typeof this.config.trigger.elements?document.querySelectorAll(this.config.trigger.elements):this.config.trigger.elements();r.forEach||(r=[r]),r.forEach((function(r){r.hasAttribute(t)||(r.addEventListener(e.config.trigger.event,(function(){return"conversion"===e.config.type?e.convert():e.scrape(r)})),r.setAttribute(t,""))}))}catch(e){this.log("error",e.message,{"trigger.elements":this.config.trigger.elements})}}else switch(this.config.type){case"attribution":this.attribute();break;case"conversion":this.convert();break;default:this.scrape()}else this.log("warn",'URL pattern does not match "'.concat(location.href,'"'),{url:this.config.url});setTimeout((function(){return e.cycle()}),750)}},{key:"attribute",value:function(){var e=this.constructor.getQueryParameter("ccpid");if(!e)return this.log("warn","ccpid query parameter not present");if(!/^[0-9a-f]{20}$/.test(e))return this.log("error","ccpid query parameter is not formatted correctly");var t="choreograph-".concat(this.config.label),r=localStorage.getItem(t);if(""===r)return this.log("warn",'"'.concat(this.config.label,'" already converted'));r!==e&&localStorage.setItem(t,e),this.log("success",'Stored CCPID "'.concat(e,'" for "').concat(this.config.label,'"'))}},{key:"convert",value:function(){var e="choreograph-".concat(this.config.label),t=localStorage.getItem(e);if(!t)return this.log("warn",'"'.concat(this.config.label,'" attribution not present'));this.send(t),localStorage.setItem(e,"")}},{key:"scrape",value:function(e){var r,o=this,i=!1,c=function(t,r){var c=t;if("function"==typeof c)try{c=c(e)}catch(e){if(o.config.optional.includes(r))return;o.log("error",e.message,n({},r?"scrape.".concat(r):"scrape",c)),i=!0}return"string"==typeof c&&(c=c.replace(/\s+/g," ").trim()),null!=c&&""!==c||o.config.optional.includes(r)||(o.log("error","Value is empty",n({},r?"scrape.".concat(r):"scrape",c)),i=!0),c};r="scraper"!==this.config.type?c(this.config.scrape):Object.keys(this.config.scrape).reduce((function(e,r){return t(t({},e),{},n({},r,c(o.config.scrape[r],r)))}),{});var a=JSON.stringify(r);if(!i&&this.previouslyScrapedHash!==a){try{this.config.before(r,(function(e){Array.isArray(e)?e.forEach((function(e){return o.send(e)})):o.send(e)}))}catch(e){this.log("error",e.message,{before:this.config.before})}this.previouslyScrapedHash=a,this.logs.length=0}}},{key:"send",value:function(e){var t,r,n=this,o="GET";switch(this.config.type){case"scraper":var i=e.sku;delete e.sku,t={"advertiser-id":this.config.advertiser,sku:i,fields:e},r="https://d.lemonpi.io/scrapes".concat(this.config.debug?"?validate=true":""),o="POST";break;case"viewed":case"basketed":case"purchased":t={"event-type":"product-".concat(this.config.type),sku:e},r="https://d.lemonpi.io/a/".concat(this.config.advertiser,"/product/event?e=").concat(encodeURIComponent(JSON.stringify(t)));break;case"conversion":t={version:1,type:"conversion",name:this.config.label,"conversion-attribution-id":e,"advertiser-id":this.config.advertiser},r="https://content.lemonpi.io/track/event?e=".concat(encodeURIComponent(JSON.stringify(t)))}!["viewed","basketed","purchased"].includes(this.config.type)||this.config.debug?fetch(r,"POST"===o?{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}:null).then((function(r){return r.json().then((function(o){if(r.ok){n.log("warn","Successful, with warnings. Details:",{payload:t,result:o});try{n.config.after(e)}catch(e){n.log("error",e.message,{after:n.config.after})}}else n.log("error","Failed: ".concat(r.status," (").concat(r.statusText,"). Details:"),{payload:t,result:o});n.logs.length=0})).catch((function(){if(r.ok){n.log("success","Successful!",{payload:t});try{n.config.after(e)}catch(e){n.log("error",e.message,{after:n.config.after})}}else n.log("error","Failed: ".concat(r.status," (").concat(r.statusText,"). Details:"),{payload:t,response:r});n.logs.length=0}))})).catch((function(e){n.log("error","Failed: ".concat(e.message),{payload:t}),n.logs.length=0})):(new Image).src=r}}],c=[{key:"getUrl",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.allowedQueryParameters,r=void 0===t?[]:t,n=e.allowHash,o=void 0!==n&&n,i="".concat(location.protocol,"//").concat(location.host).concat(location.pathname),c=new URLSearchParams(location.search);return r.reduce((function(e,t){var r=e?"&":"?",n=encodeURI(t),o=c.get(t);return null!=o?(i+="".concat(r).concat(n).concat(""===o?"":"=".concat(encodeURI(o))),!0):e}),!1),o&&(i+=location.hash),i}},{key:"getAllPathSegments",value:function(){return location.pathname.split("/").filter((function(e){return e})).map((function(e){return decodeURI(e)}))}},{key:"getPathSegment",value:function(e){return this.getAllPathSegments()[e]}},{key:"getAllQueryParameters",value:function(){return location.search.replace(/^\?/,"").split("&").filter((function(e){return e})).reduce((function(e,r){return t(t({},e),{},n({},decodeURI(r.split("=")[0]),decodeURI(r.split("=")[1]||"")))}),{})}},{key:"getQueryParameter",value:function(e){return this.getAllQueryParameters()[e]}}],i&&r(o.prototype,i),c&&r(o,c),Object.defineProperty(o,"prototype",{writable:!1}),e}();return i}();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "choreograph-create-pixel",
|
|
3
3
|
"description": "This library lets you apply best practises to Choreograph Create pixel development and implementation.",
|
|
4
|
-
"version": "1.4.
|
|
4
|
+
"version": "1.4.3",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"wpp",
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
"opendc",
|
|
12
12
|
"greenhouse"
|
|
13
13
|
],
|
|
14
|
-
"author": "Rick Stevens <rick.stevens@choreograph.com> (https://
|
|
14
|
+
"author": "Rick Stevens <rick.stevens@choreograph.com> (https://create.choreograph.com)",
|
|
15
15
|
"repository": "gitlab:2sixty/choreograph-create/solutions/choreograph-create-pixel",
|
|
16
|
-
"homepage": "https://
|
|
16
|
+
"homepage": "https://create.choreograph.com",
|
|
17
17
|
"license": "ISC",
|
|
18
18
|
"main": "dist/bundle.cjs.js",
|
|
19
19
|
"module": "dist/bundle.esm.js",
|