choreograph-create-pixel 1.0.0 โ†’ 1.1.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/README.md CHANGED
@@ -13,12 +13,12 @@ This library lets you apply best practises to [Choreograph Create](https://www.l
13
13
 
14
14
  ## Quickstart
15
15
 
16
- The following theoretical snippet could be embedded on every page of _example.com_, and would automatically determine when to enable, through URL detection.
16
+ The following theoretical snippet could be embedded on every page of _example.com_, and would automatically determine when to enable through URL validation.
17
17
 
18
- ### Browser
18
+ ### Browser example
19
19
 
20
20
  ```html
21
- <script src="https://unpkg.com/choreograph-create-pixel@^1"></script>
21
+ <script src="https://cdn.jsdelivr.net/npm/choreograph-create-pixel@1"></script>
22
22
  <script>
23
23
  // Scrape pixel
24
24
  new ChoreographCreatePixel({
@@ -60,129 +60,92 @@ The following theoretical snippet could be embedded on every page of _example.co
60
60
  },
61
61
  },
62
62
  });
63
- </script>
64
- ```
65
-
66
- ### ES module
67
-
68
- ```js
69
- import Pixel from "choreograph-create-pixel";
70
-
71
- // Scrape pixel
72
- new Pixel({
73
- // Who is the client? (advertiser ID)
74
- who: 0,
75
-
76
- // What kind of pixel is this?
77
- what: "scrape",
78
-
79
- // Where should the pixel be enabled?
80
- where: /example\.com\/products\/\d/,
81
-
82
- // Which data should be scraped?
83
- which: {
84
- // Data layer example
85
- sku: () => window.dataLayer[0].product.sku,
86
-
87
- // DOM example
88
- name: () => document.querySelector("#product-name").innerText,
89
63
 
90
- // Helper example
91
- url: Pixel.getUrl,
92
- },
93
- });
94
-
95
- // View segment pixel
96
- new Pixel({
97
- who: 0,
98
- what: "view",
99
- where: /example\.com\/products\/\d/,
100
-
101
- which: {
102
- sku: () => window.dataLayer[0].product.sku,
103
- },
104
- });
105
- ```
106
-
107
- > ES modules require manual bundling and transpiling before they can be safely used as browser scripts.
64
+ // Basket segment pixel
65
+ new ChoreographCreatePixel({
66
+ who: 0,
67
+ what: "basket",
68
+ where: /example\.com/,
108
69
 
109
- ## Other scenarios
70
+ // (Optional) When should the pixel be enabled?
71
+ when: {
72
+ listener: "click",
110
73
 
111
- Besides **scrape** and **view** pixels, this library also supports **basket** and **purchase** segment pixels.
74
+ elements: function () {
75
+ return document.querySelectorAll("button.basket[data-sku]");
76
+ },
77
+ },
112
78
 
113
- ### Basket segment
79
+ which: {
80
+ // The "element" parameter only exists while using a "when" condition
81
+ sku: function (element) {
82
+ return element.getAttribute("data-sku");
83
+ },
84
+ },
85
+ });
114
86
 
115
- ```js
116
- {
117
- who: 0,
118
- what: "basket",
119
- where: /example\.com/,
87
+ // Purchase segment pixel
88
+ new ChoreographCreatePixel({
89
+ who: 0,
90
+ what: "purchase",
91
+ where: /example\.com\/cart/,
120
92
 
121
- // (Optional) When should the pixel be enabled?
122
- when: {
123
- listener: "click",
93
+ when: {
94
+ listener: "click",
124
95
 
125
- elements: function () {
126
- return document.querySelectorAll("button.basket[data-sku]");
96
+ elements: function () {
97
+ return document.querySelectorAll("button.checkout");
98
+ },
127
99
  },
128
- },
129
100
 
130
- which: {
131
- // The "element" parameter only exists while using a "when" condition
132
- sku: function (element) {
133
- return element.getAttribute("data-sku");
101
+ which: {
102
+ // which.sku supports returning an array of strings
103
+ sku: function () {
104
+ return window.dataLayer[0].cart.map(function (product) {
105
+ return product.sku;
106
+ });
107
+ },
134
108
  },
135
- },
136
- }
109
+ });
110
+ </script>
137
111
  ```
138
112
 
139
- ### Purchase segment
113
+ ### ES module example
140
114
 
141
115
  ```js
142
- {
143
- who: 0,
144
- what: "purchase",
145
- where: /example\.com\/cart/,
116
+ import Pixel from "choreograph-create-pixel";
146
117
 
147
- when: {
148
- listener: "click",
118
+ new Pixel({
119
+ ...
120
+ });
149
121
 
150
- elements: function () {
151
- return document.querySelectorAll("button.checkout");
152
- },
153
- },
154
-
155
- which: {
156
- // which.sku supports returning an array of strings
157
- sku: function () {
158
- return window.dataLayer[0].cart.map(function (product) {
159
- return product.sku;
160
- });
161
- },
162
- },
163
- }
122
+ new Pixel({
123
+ ...
124
+ });
164
125
  ```
165
126
 
127
+ > ES modules require manual bundling and transpiling before they can be safely used as browser scripts.
128
+
166
129
  ## Debugging
167
130
 
168
131
  Enable the console debugger by adding `?pixel_debug` or `#pixel_debug` to the page's URL.
169
132
 
170
133
  ## Configuration
171
134
 
172
- | Property | Type | Description | Default |
173
- | ---------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- |
174
- | `who` | Number | You can retrieve the advertiser ID from the URL in the [Manage platform](https://manage.lemonpi.io/) _(manage.lemonpi.io/r/AGENCY_ID/advertiser/`ADVERTISER_ID`)_. | _Required_ |
175
- | `what` | String | Pixel type. One of: `"scrape"`, `"view"`, `"basket"`, or `"purchase"`. | _Required_ |
176
- | `where` | RegExp | Disables pixels on page URLs that are not matched by this pattern. | _Required_ |
177
- | `which` | Object | An object holding the data fields to be scraped. | _Required_ |
178
- | `which.sku` | String, Array, or Function | `sku` is the only required data field, as it's the product's unique identifier. In case of segment pixels (`what` equals `"view"`, `"basket"`, or `"purchase"`), an array of strings is allowed to trigger multiple pixel executions. | _Required_ |
179
- | `which.*` | String, Number, Boolean, or Function | `*` should always match with existing field names in the advertiser's product store. | `undefined` |
180
- | `when` | Object | Use this property when you want to enable the pixel only after a specific DOM event. | `undefined` |
181
- | `when.listener` | String | DOM event type. [List of supported values.](https://www.w3schools.com/jsref/dom_obj_event.asp) | _Required_ when using `when` |
182
- | `when.elements` | Function | This function should return DOM element(s) to apply the listener to. | _Required_ when using `when` |
183
- | `optionalFields` | Array | An array of field names (strings) that are allowed to have empty values. | `[]` |
184
- | `beforeSend` | Function | Lifecycle function that's executed just before the pixel's data is sent. | `function (data, callback) { callback(data); }` |
185
- | `afterSend` | Function | Lifecycle function that's executed just after the pixel's data is sent. | `function (data) {}` |
135
+ | Property | Type | Description | Default |
136
+ | --------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- |
137
+ | `who` | Number | You can retrieve the advertiser ID from the URL in the [Manage platform](https://manage.lemonpi.io/) _(manage.lemonpi.io/r/AGENCY_ID/advertiser/`ADVERTISER_ID`)_. | _Required_ |
138
+ | `what` | String | Pixel type. One of: `"scrape"`, `"view"`, `"basket"`, or `"purchase"`. | _Required_ |
139
+ | `where` | RegExp | Disables pixels on page URLs that are not matched by this pattern. | _Required_ |
140
+ | `which` | Object | An object holding the data fields to be scraped. | _Required_ |
141
+ | `which.sku` | String, Array, or Function | `sku` is the only required data field, as it's the product's unique identifier. In case of segment pixels (`what` equals `"view"`, `"basket"`, or `"purchase"`), an array of strings is allowed to trigger multiple pixel executions. | _Required_ |
142
+ | `which.*` | String, Number, Boolean, or Function | `*` should always match with existing field names in the advertiser's product store. | `undefined` |
143
+ | `when` | Object | Use this property when you want to enable the pixel only after a specific DOM event. | `undefined` |
144
+ | `when.listener` | String | DOM event type. [List of supported values.](https://www.w3schools.com/jsref/dom_obj_event.asp) | _Required_ when using `when` |
145
+ | `when.elements` | Function | This function should return DOM element(s) to apply the listener to. | _Required_ when using `when` |
146
+ | `optional` | Array | An array of field names (strings) that are allowed to have empty values. | `[]` |
147
+ | `before` | Function | Lifecycle function that's executed just before the pixel's data is sent. | `function (data, callback) { callback(data); }` |
148
+ | `after` | Function | Lifecycle function that's executed just after the pixel's data is sent. | `function (data) {}` |
186
149
 
187
150
  ## Static methods (helpers)
188
151
 
@@ -1,4 +1,4 @@
1
- /*! choreograph-create-pixel v1.0.0 2022/09/21 */
1
+ /*! choreograph-create-pixel v1.1.0 2022/09/26 */
2
2
  'use strict';
3
3
 
4
4
  class ChoreographCreatePixel {
@@ -20,9 +20,9 @@ class ChoreographCreatePixel {
20
20
 
21
21
  this.config = {
22
22
  debug: /(pixel|lemonpi)_debug/i.test(location.href),
23
- beforeSend: (data, callback) => callback(data),
24
- afterSend: () => {},
25
- optionalFields: [],
23
+ before: (data, callback) => callback(data),
24
+ after: () => {},
25
+ optional: [],
26
26
  ...userConfig,
27
27
  };
28
28
 
@@ -176,7 +176,7 @@ class ChoreographCreatePixel {
176
176
  try {
177
177
  data[fieldName] = data[fieldName](element);
178
178
  } catch (error) {
179
- if (!this.config.optionalFields.includes(fieldName)) {
179
+ if (!this.config.optional.includes(fieldName)) {
180
180
  this.log("error", error.message, {
181
181
  which: { [fieldName]: this.config.which[fieldName] },
182
182
  });
@@ -190,7 +190,7 @@ class ChoreographCreatePixel {
190
190
  data[fieldName] = data[fieldName].replace(/\s+/g, " ").trim();
191
191
 
192
192
  if (data[fieldName] == null || data[fieldName] === "")
193
- if (!this.config.optionalFields.includes(fieldName)) {
193
+ if (!this.config.optional.includes(fieldName)) {
194
194
  this.log("error", "This required field's value is empty", {
195
195
  which: { [fieldName]: data[fieldName] },
196
196
  });
@@ -203,14 +203,14 @@ class ChoreographCreatePixel {
203
203
 
204
204
  if (!hasErrors && this.previouslyScrapedJsonString !== jsonString) {
205
205
  try {
206
- this.config.beforeSend(data, (newData) => {
206
+ this.config.before(data, (newData) => {
207
207
  if (this.config.what !== "scrape" && Array.isArray(newData.sku))
208
208
  newData.sku.forEach((sku) => this.send({ ...newData, sku }));
209
209
  else this.send(newData);
210
210
  });
211
211
  } catch (error) {
212
212
  this.log("error", error.message, {
213
- beforeSend: this.config.beforeSend,
213
+ before: this.config.before,
214
214
  });
215
215
  }
216
216
 
@@ -262,10 +262,10 @@ class ChoreographCreatePixel {
262
262
  this.log("warn", "Successful, with warnings. Details:", result);
263
263
 
264
264
  try {
265
- this.config.afterSend(data);
265
+ this.config.after(data);
266
266
  } catch (error) {
267
267
  this.log("error", error.message, {
268
- afterSend: this.config.afterSend,
268
+ after: this.config.after,
269
269
  });
270
270
  }
271
271
  } else
@@ -282,10 +282,10 @@ class ChoreographCreatePixel {
282
282
  this.log("success", "Successful!", data);
283
283
 
284
284
  try {
285
- this.config.afterSend(data);
285
+ this.config.after(data);
286
286
  } catch (error) {
287
287
  this.log("error", error.message, {
288
- afterSend: this.config.afterSend,
288
+ after: this.config.after,
289
289
  });
290
290
  }
291
291
  } else
@@ -1,4 +1,4 @@
1
- /*! choreograph-create-pixel v1.0.0 2022/09/21 */
1
+ /*! choreograph-create-pixel v1.1.0 2022/09/26 */
2
2
  class ChoreographCreatePixel {
3
3
  constructor(userConfig) {
4
4
  this.previouslyScrapedJsonString = null;
@@ -18,9 +18,9 @@ class ChoreographCreatePixel {
18
18
 
19
19
  this.config = {
20
20
  debug: /(pixel|lemonpi)_debug/i.test(location.href),
21
- beforeSend: (data, callback) => callback(data),
22
- afterSend: () => {},
23
- optionalFields: [],
21
+ before: (data, callback) => callback(data),
22
+ after: () => {},
23
+ optional: [],
24
24
  ...userConfig,
25
25
  };
26
26
 
@@ -174,7 +174,7 @@ class ChoreographCreatePixel {
174
174
  try {
175
175
  data[fieldName] = data[fieldName](element);
176
176
  } catch (error) {
177
- if (!this.config.optionalFields.includes(fieldName)) {
177
+ if (!this.config.optional.includes(fieldName)) {
178
178
  this.log("error", error.message, {
179
179
  which: { [fieldName]: this.config.which[fieldName] },
180
180
  });
@@ -188,7 +188,7 @@ class ChoreographCreatePixel {
188
188
  data[fieldName] = data[fieldName].replace(/\s+/g, " ").trim();
189
189
 
190
190
  if (data[fieldName] == null || data[fieldName] === "")
191
- if (!this.config.optionalFields.includes(fieldName)) {
191
+ if (!this.config.optional.includes(fieldName)) {
192
192
  this.log("error", "This required field's value is empty", {
193
193
  which: { [fieldName]: data[fieldName] },
194
194
  });
@@ -201,14 +201,14 @@ class ChoreographCreatePixel {
201
201
 
202
202
  if (!hasErrors && this.previouslyScrapedJsonString !== jsonString) {
203
203
  try {
204
- this.config.beforeSend(data, (newData) => {
204
+ this.config.before(data, (newData) => {
205
205
  if (this.config.what !== "scrape" && Array.isArray(newData.sku))
206
206
  newData.sku.forEach((sku) => this.send({ ...newData, sku }));
207
207
  else this.send(newData);
208
208
  });
209
209
  } catch (error) {
210
210
  this.log("error", error.message, {
211
- beforeSend: this.config.beforeSend,
211
+ before: this.config.before,
212
212
  });
213
213
  }
214
214
 
@@ -260,10 +260,10 @@ class ChoreographCreatePixel {
260
260
  this.log("warn", "Successful, with warnings. Details:", result);
261
261
 
262
262
  try {
263
- this.config.afterSend(data);
263
+ this.config.after(data);
264
264
  } catch (error) {
265
265
  this.log("error", error.message, {
266
- afterSend: this.config.afterSend,
266
+ after: this.config.after,
267
267
  });
268
268
  }
269
269
  } else
@@ -280,10 +280,10 @@ class ChoreographCreatePixel {
280
280
  this.log("success", "Successful!", data);
281
281
 
282
282
  try {
283
- this.config.afterSend(data);
283
+ this.config.after(data);
284
284
  } catch (error) {
285
285
  this.log("error", error.message, {
286
- afterSend: this.config.afterSend,
286
+ after: this.config.after,
287
287
  });
288
288
  }
289
289
  } else
@@ -0,0 +1,2 @@
1
+ /*! choreograph-create-pixel v1.1.0 2022/09/26 */
2
+ var ChoreographCreatePixel=function(){"use strict";function e(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function t(t){for(var n=1;n<arguments.length;n++){var o=null!=arguments[n]?arguments[n]:{};n%2?e(Object(o),!0).forEach((function(e){r(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 n(e){return n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},n(e)}function o(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var i=function(){function e(n){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.previouslyScrapedJsonString=null,this.logs=[],this.settings={colors:{error:"#f44336",warn:"#ffa726",success:"#66bb6a"},icons:{scrape:"๐Ÿ”",view:"๐Ÿ‘€",basket:"๐Ÿ›’",purchase:"๐Ÿงพ"},titleCss:"font:700 80% HelveticaNeue;margin:12px 0 8px",messageCss:"font:500 120% HelveticaNeue;margin-bottom:12px",eventTypes:{view:"product-viewed",basket:"product-basketed",purchase:"product-purchased"}},this.config=t({debug:/(pixel|lemonpi)_debug/i.test(location.href),before:function(e,t){return t(e)},after:function(){},optional:[]},n),this.validateConfig()&&this.cycle()}var i,s,c;return i=e,s=[{key:"log",value:function(e,t){var n,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;if(this.config.debug&&!this.logs.includes(t)){var r=["%c".concat(this.settings.icons[this.config.what]," ").concat(this.config.what.toUpperCase()," PIXEL DEBUG%c\n%c").concat(t),this.settings.titleCss,"",this.settings.colors[e]?"".concat(this.settings.messageCss,";color:").concat(this.settings.colors[e]):this.settings.messageCss];o&&r.push(o),(n=console).info.apply(n,r),this.logs.push(t)}}},{key:"validateConfig",value:function(){if("number"!=typeof this.config.who)this.log("error","Please use a number",{who:this.config.who});else if(["scrape","view","basket","purchase"].includes(this.config.what))if(this.config.where instanceof RegExp){if("object"===n(this.config.which)&&this.config.which.sku)return!0;this.log("error","Please provide an SKU",{which:this.config.which})}else this.log("error","Please use a regular expression",{where:this.config.where});else this.log("error","Please use scrape, view, basket, or purchase",{what:this.config.what})}},{key:"cycle",value:function(){var e=this;if(this.config.where.test(location.href))if("scrape"===this.config.what&&document.querySelector('html[class*="translated-"]'))this.log("warn","This page has been translated by the browser, and will be excluded");else if(this.config.when)try{var t=this.config.when.elements();t.forEach||(t=[t]),t.forEach((function(t){t.hasAttribute("choreograph-".concat(e.config.when.listener))||(t.addEventListener(e.config.when.listener,(function(){return e.scrape(t)})),t.setAttribute("choreograph-".concat(e.config.when.listener),""))}))}catch(e){this.log("error",e.message,{when:{elements:this.config.when.elements}})}else this.scrape();else this.log("warn",'Pattern does not match "'.concat(location.href,'"'),{where:this.config.where});setTimeout((function(){return e.cycle()}),750)}},{key:"scrape",value:function(e){var n=this,o={},i=!1;Object.keys(this.config.which).forEach((function(t){if(o[t]=n.config.which[t],"function"==typeof o[t])try{o[t]=o[t](e)}catch(e){n.config.optional.includes(t)?delete o[t]:(n.log("error",e.message,{which:r({},t,n.config.which[t])}),i=!0)}"string"==typeof o[t]&&(o[t]=o[t].replace(/\s+/g," ").trim()),null!=o[t]&&""!==o[t]||(n.config.optional.includes(t)?o[t]=null:(n.log("error","This required field's value is empty",{which:r({},t,o[t])}),i=!0))}));var s=JSON.stringify(o);if(!i&&this.previouslyScrapedJsonString!==s){try{this.config.before(o,(function(e){"scrape"!==n.config.what&&Array.isArray(e.sku)?e.sku.forEach((function(o){return n.send(t(t({},e),{},{sku:o}))})):n.send(e)}))}catch(e){this.log("error",e.message,{before:this.config.before})}this.previouslyScrapedJsonString=s,this.logs.length=0}}},{key:"send",value:function(e){var n=this,o=t({},e);delete o.sku;var r="scrape"===this.config.what?"https://d.lemonpi.io/scrapes".concat(this.config.debug?"?validate=true":""):"https://d.lemonpi.io/a/".concat(this.config.who,"/product/event?e=").concat(encodeURIComponent(JSON.stringify({"event-type":this.settings.eventTypes[this.config.what],sku:e.sku})));"scrape"===this.config.what||this.config.debug?fetch(r,"scrape"===this.config.what?{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({"advertiser-id":this.config.who,sku:e.sku,fields:o})}:null).then((function(t){return t.json().then((function(o){if(t.ok){n.log("warn","Successful, with warnings. Details:",o);try{n.config.after(e)}catch(e){n.log("error",e.message,{after:n.config.after})}}else n.log("error","Failed: ".concat(t.status," (").concat(t.statusText,"). Details:"),o);n.logs.length=0})).catch((function(){if(t.ok){n.log("success","Successful!",e);try{n.config.after(e)}catch(e){n.log("error",e.message,{after:n.config.after})}}else n.log("error","Failed: ".concat(t.status," (").concat(t.statusText,"). Details:"),t);n.logs.length=0}))})).catch((function(e){n.log("error","Failed: ".concat(e.message)),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,n=void 0===t?[]:t,o=e.allowHash,r=void 0!==o&&o,i="".concat(location.protocol,"//").concat(location.host).concat(location.pathname),s=new URLSearchParams(location.search);return n.reduce((function(e,t){var n=e?"&":"?",o=encodeURI(t),r=s.get(t);return null!=r?(i+="".concat(n).concat(o).concat(""===r?"":"=".concat(encodeURI(r))),!0):e}),!1),r&&(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,n){return t(t({},e),{},r({},decodeURI(n.split("=")[0]),decodeURI(n.split("=")[1]||"")))}),{})}},{key:"getQueryParameter",value:function(e){return this.getAllQueryParameters()[e]}}],s&&o(i.prototype,s),c&&o(i,c),Object.defineProperty(i,"prototype",{writable:!1}),e}();return i}();
package/package.json CHANGED
@@ -1,15 +1,15 @@
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.0.0",
5
- "author": "Rick Stevens <rick.stevens@choreograph.com> (https://www.lemonpi.io/)",
4
+ "version": "1.1.0",
5
+ "author": "Rick Stevens <rick.stevens@choreograph.com> (https://lemonpi.io)",
6
6
  "repository": "gitlab:GreenhouseGroup/lemonpi/solutions/choreograph-create-pixel",
7
- "homepage": "https://lemonpi.io/",
7
+ "homepage": "https://lemonpi.io",
8
8
  "license": "ISC",
9
9
  "main": "dist/bundle.cjs.js",
10
10
  "module": "dist/bundle.esm.js",
11
- "browser": "dist/bundle.iife.js",
12
- "unpkg": "dist/bundle.iife.js",
11
+ "browser": "dist/bundle.iife.min.js",
12
+ "unpkg": "dist/bundle.iife.min.js",
13
13
  "files": [
14
14
  "dist"
15
15
  ],
@@ -30,7 +30,7 @@
30
30
  "eslint-plugin-prettier": "^4.2.1",
31
31
  "moment": "^2.29.4",
32
32
  "prettier": "^2.7.1",
33
- "rollup": "^2.79.0",
33
+ "rollup": "^2.79.1",
34
34
  "rollup-plugin-terser": "^7.0.2"
35
35
  }
36
36
  }
@@ -1,2 +0,0 @@
1
- /*! choreograph-create-pixel v1.0.0 2022/09/21 */
2
- var ChoreographCreatePixel=function(){"use strict";function e(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function t(t){for(var n=1;n<arguments.length;n++){var o=null!=arguments[n]?arguments[n]:{};n%2?e(Object(o),!0).forEach((function(e){r(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 n(e){return n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},n(e)}function o(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var i=function(){function e(n){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.previouslyScrapedJsonString=null,this.logs=[],this.settings={colors:{error:"#f44336",warn:"#ffa726",success:"#66bb6a"},icons:{scrape:"๐Ÿ”",view:"๐Ÿ‘€",basket:"๐Ÿ›’",purchase:"๐Ÿงพ"},titleCss:"font:700 80% HelveticaNeue;margin:12px 0 8px",messageCss:"font:500 120% HelveticaNeue;margin-bottom:12px",eventTypes:{view:"product-viewed",basket:"product-basketed",purchase:"product-purchased"}},this.config=t({debug:/(pixel|lemonpi)_debug/i.test(location.href),beforeSend:function(e,t){return t(e)},afterSend:function(){},optionalFields:[]},n),this.validateConfig()&&this.cycle()}var i,s,c;return i=e,s=[{key:"log",value:function(e,t){var n,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;if(this.config.debug&&!this.logs.includes(t)){var r=["%c".concat(this.settings.icons[this.config.what]," ").concat(this.config.what.toUpperCase()," PIXEL DEBUG%c\n%c").concat(t),this.settings.titleCss,"",this.settings.colors[e]?"".concat(this.settings.messageCss,";color:").concat(this.settings.colors[e]):this.settings.messageCss];o&&r.push(o),(n=console).info.apply(n,r),this.logs.push(t)}}},{key:"validateConfig",value:function(){if("number"!=typeof this.config.who)this.log("error","Please use a number",{who:this.config.who});else if(["scrape","view","basket","purchase"].includes(this.config.what))if(this.config.where instanceof RegExp){if("object"===n(this.config.which)&&this.config.which.sku)return!0;this.log("error","Please provide an SKU",{which:this.config.which})}else this.log("error","Please use a regular expression",{where:this.config.where});else this.log("error","Please use scrape, view, basket, or purchase",{what:this.config.what})}},{key:"cycle",value:function(){var e=this;if(this.config.where.test(location.href))if("scrape"===this.config.what&&document.querySelector('html[class*="translated-"]'))this.log("warn","This page has been translated by the browser, and will be excluded");else if(this.config.when)try{var t=this.config.when.elements();t.forEach||(t=[t]),t.forEach((function(t){t.hasAttribute("choreograph-".concat(e.config.when.listener))||(t.addEventListener(e.config.when.listener,(function(){return e.scrape(t)})),t.setAttribute("choreograph-".concat(e.config.when.listener),""))}))}catch(e){this.log("error",e.message,{when:{elements:this.config.when.elements}})}else this.scrape();else this.log("warn",'Pattern does not match "'.concat(location.href,'"'),{where:this.config.where});setTimeout((function(){return e.cycle()}),750)}},{key:"scrape",value:function(e){var n=this,o={},i=!1;Object.keys(this.config.which).forEach((function(t){if(o[t]=n.config.which[t],"function"==typeof o[t])try{o[t]=o[t](e)}catch(e){n.config.optionalFields.includes(t)?delete o[t]:(n.log("error",e.message,{which:r({},t,n.config.which[t])}),i=!0)}"string"==typeof o[t]&&(o[t]=o[t].replace(/\s+/g," ").trim()),null!=o[t]&&""!==o[t]||(n.config.optionalFields.includes(t)?o[t]=null:(n.log("error","This required field's value is empty",{which:r({},t,o[t])}),i=!0))}));var s=JSON.stringify(o);if(!i&&this.previouslyScrapedJsonString!==s){try{this.config.beforeSend(o,(function(e){"scrape"!==n.config.what&&Array.isArray(e.sku)?e.sku.forEach((function(o){return n.send(t(t({},e),{},{sku:o}))})):n.send(e)}))}catch(e){this.log("error",e.message,{beforeSend:this.config.beforeSend})}this.previouslyScrapedJsonString=s,this.logs.length=0}}},{key:"send",value:function(e){var n=this,o=t({},e);delete o.sku;var r="scrape"===this.config.what?"https://d.lemonpi.io/scrapes".concat(this.config.debug?"?validate=true":""):"https://d.lemonpi.io/a/".concat(this.config.who,"/product/event?e=").concat(encodeURIComponent(JSON.stringify({"event-type":this.settings.eventTypes[this.config.what],sku:e.sku})));"scrape"===this.config.what||this.config.debug?fetch(r,"scrape"===this.config.what?{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({"advertiser-id":this.config.who,sku:e.sku,fields:o})}:null).then((function(t){return t.json().then((function(o){if(t.ok){n.log("warn","Successful, with warnings. Details:",o);try{n.config.afterSend(e)}catch(e){n.log("error",e.message,{afterSend:n.config.afterSend})}}else n.log("error","Failed: ".concat(t.status," (").concat(t.statusText,"). Details:"),o);n.logs.length=0})).catch((function(){if(t.ok){n.log("success","Successful!",e);try{n.config.afterSend(e)}catch(e){n.log("error",e.message,{afterSend:n.config.afterSend})}}else n.log("error","Failed: ".concat(t.status," (").concat(t.statusText,"). Details:"),t);n.logs.length=0}))})).catch((function(e){n.log("error","Failed: ".concat(e.message)),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,n=void 0===t?[]:t,o=e.allowHash,r=void 0!==o&&o,i="".concat(location.protocol,"//").concat(location.host).concat(location.pathname),s=new URLSearchParams(location.search);return n.reduce((function(e,t){var n=e?"&":"?",o=encodeURI(t),r=s.get(t);return null!=r?(i+="".concat(n).concat(o).concat(""===r?"":"=".concat(encodeURI(r))),!0):e}),!1),r&&(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,n){return t(t({},e),{},r({},decodeURI(n.split("=")[0]),decodeURI(n.split("=")[1]||"")))}),{})}},{key:"getQueryParameter",value:function(e){return this.getAllQueryParameters()[e]}}],s&&o(i.prototype,s),c&&o(i,c),Object.defineProperty(i,"prototype",{writable:!1}),e}();return i}();