@adhese/sdk-lite 1.0.0 → 1.1.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @adhese/sdk-lite
2
2
 
3
+ ## 1.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - d29a909: Remove logger to optmize output js file
8
+
9
+ ## 1.1.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 431b736: When not passing an element to a lite slot the parent element of the script where it's called is selected
14
+
15
+ ### Patch Changes
16
+
17
+ - 431b736: Improve documentation
18
+
3
19
  ## 1.0.0
4
20
 
5
21
  ### Major Changes
package/README.md CHANGED
@@ -1,20 +1,23 @@
1
1
  # @adhese/sdk-lite
2
- Lightweight Adhese SDK that can only render a single slot
3
-
4
- ## Installation
5
- ```bash
6
- npm install @adhese/sdk-lite
7
- ```
2
+ The Adhese SDK Lite is a lightweight version of the Adhese SDK. It is a smaller package that can only render a single
3
+ slot. This package is most useful for use in places like Google Tag Manager.
8
4
 
9
5
  ## Usage
10
- ```js
11
- import {createSlot} from '@adhese/sdk-lite';
6
+ To create a slot, you need to call the `createSlot` function with an object containing the account, location, and format.
7
+
8
+ The slot will be created alongside the script tag in which the function is called.
12
9
 
13
- const slot = createSlot({
14
- account: 'demo',
15
- location: 'location',
16
- format: 'format',
17
- containingElement: document.getElementById('container'),
18
- debug: true,
19
- });
10
+ ```html
11
+ <body>
12
+ <div>
13
+ <script src="adheseLite.js"></script>
14
+ <script>
15
+ AdheseLite.createSlot({
16
+ account: 'your-account-id',
17
+ location: 'location-name',
18
+ format: 'format-name',
19
+ })
20
+ </script>
21
+ </div>
22
+ </body>
20
23
  ```
@@ -1,18 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const sdkShared = require("@adhese/sdk-shared");
4
- const name = "@adhese/sdk-lite";
5
- const version = "1.0.0";
4
+ const version = "1.1.1";
6
5
  const renderFunctions = {
7
6
  iframe: sdkShared.renderIframe,
8
7
  inline: sdkShared.renderInline
9
8
  };
10
9
  function createSlot(options) {
11
- const logger = sdkShared.createLogger({
12
- scope: `${name}@${version}`,
13
- minLogLevelThreshold: options.debug ? "debug" : "info"
14
- });
15
- const name$1 = sdkShared.generateName(options.location, options.format, options.slot);
10
+ var _a;
11
+ const name = sdkShared.generateName(options.location, options.format, options.slot);
16
12
  const trackingPixels = /* @__PURE__ */ new Set();
17
13
  const renderIntersectionObserver = new IntersectionObserver(onRenderIntersection, {
18
14
  rootMargin: "200px",
@@ -32,19 +28,27 @@ function createSlot(options) {
32
28
  ...consentParameters
33
29
  };
34
30
  let isImpressionTracked = false;
31
+ const element = options.containingElement ?? document.createElement("div");
32
+ if (!options.containingElement) {
33
+ element.id = `${name}:${sdkShared.uniqueId(3)}`;
34
+ element.classList.add("adunit");
35
+ element.dataset.format = options.format;
36
+ element.dataset.slot = options.format;
37
+ element.dataset.location = options.location;
38
+ (_a = document.currentScript) == null ? void 0 : _a.insertAdjacentElement("beforebegin", element);
39
+ }
35
40
  const context = {
36
41
  options,
37
- name: name$1,
38
- logger,
42
+ name,
39
43
  parameters,
44
+ element,
40
45
  async request() {
41
- var _a;
42
- logger.debug(`Requesting ad for slot ${name$1}`, this);
46
+ var _a2;
43
47
  const response = await fetch(`${options.host ?? `https://ads-${options.account}.adhese.com`}/json`, {
44
48
  method: "POST",
45
49
  body: JSON.stringify({
46
50
  slots: [{
47
- slotname: name$1
51
+ slotname: name
48
52
  }],
49
53
  parameters
50
54
  }),
@@ -54,50 +58,45 @@ function createSlot(options) {
54
58
  }
55
59
  });
56
60
  if (!response.ok)
57
- throw new Error(`Failed to request ad for slot ${name$1}. Status: ${response.status}`);
61
+ throw new Error(`Failed to request ad for slot ${name}. Status: ${response.status}`);
58
62
  const [data] = await response.json();
59
63
  this.data = data;
60
- logger.debug(`Received ad data for slot ${name$1}`, this);
61
- (_a = options.onRequest) == null ? void 0 : _a.call(options, this);
64
+ (_a2 = options.onRequest) == null ? void 0 : _a2.call(options, this);
62
65
  return data;
63
66
  },
64
67
  async render() {
65
- var _a, _b;
68
+ var _a2, _b;
66
69
  const data = this.data ?? await this.request();
67
- options.containingElement.removeEventListener("click", onClick);
70
+ element.removeEventListener("click", onClick);
68
71
  if (!data) {
69
- (_a = options.onEmpty) == null ? void 0 : _a.call(options, this);
70
- logger.debug(`Slot ${name$1} is empty`, this);
71
- return options.containingElement;
72
+ (_a2 = options.onEmpty) == null ? void 0 : _a2.call(options, this);
73
+ return element;
72
74
  }
73
75
  if (typeof data.tag !== "string")
74
76
  throw new Error("Received invalid ad data, tag is not a string");
75
- renderFunctions[options.renderMode ?? "iframe"](data, options.containingElement);
77
+ renderFunctions[options.renderMode ?? "iframe"](data, element);
76
78
  (_b = options.onRender) == null ? void 0 : _b.call(options, this);
77
- logger.debug(`Rendered slot ${name$1}`, this);
78
79
  if (data.impressionCounter && !isImpressionTracked) {
79
80
  trackingPixels.add(sdkShared.addTrackingPixel(data.impressionCounter));
80
81
  isImpressionTracked = true;
81
82
  }
82
83
  if (data.viewableImpressionCounter) {
83
- viewabilityTrackingIntersectionObserver.observe(options.containingElement);
84
+ viewabilityTrackingIntersectionObserver.observe(element);
84
85
  }
85
- options.containingElement.addEventListener("click", onClick);
86
- return options.containingElement;
86
+ element.addEventListener("click", onClick);
87
+ return element;
87
88
  },
88
89
  dispose() {
89
- var _a;
90
- (_a = options.onDispose) == null ? void 0 : _a.call(options, this);
91
- options.containingElement.innerHTML = "";
90
+ var _a2;
91
+ (_a2 = options.onDispose) == null ? void 0 : _a2.call(options, this);
92
+ element.innerHTML = "";
92
93
  for (const pixel of trackingPixels) {
93
94
  pixel.remove();
94
95
  }
95
96
  trackingPixels.clear();
96
97
  renderIntersectionObserver == null ? void 0 : renderIntersectionObserver.disconnect();
97
98
  viewabilityTrackingIntersectionObserver.disconnect();
98
- options.containingElement.removeEventListener("click", onClick);
99
- logger.debug(`Disposing slot ${name$1}`, this);
100
- logger.resetLogs();
99
+ element.removeEventListener("click", onClick);
101
100
  }
102
101
  };
103
102
  let isClickTracked = false;
@@ -113,10 +112,10 @@ function createSlot(options) {
113
112
  const threshold = 0.2;
114
113
  if (ratio >= threshold && !timeoutId) {
115
114
  timeoutId = setTimeout(() => {
116
- var _a, _b;
115
+ var _a2, _b;
117
116
  timeoutId = null;
118
117
  viewabilityTrackingIntersectionObserver.disconnect();
119
- if ((_a = context.data) == null ? void 0 : _a.viewableImpressionCounter) {
118
+ if ((_a2 = context.data) == null ? void 0 : _a2.viewableImpressionCounter) {
120
119
  trackingPixels.add(sdkShared.addTrackingPixel((_b = context.data) == null ? void 0 : _b.viewableImpressionCounter));
121
120
  }
122
121
  }, 1e3);
@@ -127,12 +126,13 @@ function createSlot(options) {
127
126
  }
128
127
  function onRenderIntersection([entry]) {
129
128
  if (entry.isIntersecting) {
130
- context.render().catch(logger.error);
129
+ context.render().catch(console.error);
131
130
  renderIntersectionObserver == null ? void 0 : renderIntersectionObserver.disconnect();
132
131
  }
133
132
  }
134
- renderIntersectionObserver.observe(options.containingElement);
133
+ renderIntersectionObserver.observe(element);
135
134
  return context;
136
135
  }
137
136
  exports.createSlot = createSlot;
137
+ exports.version = version;
138
138
  //# sourceMappingURL=sdkLite.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"sdkLite.cjs","sources":["../../src/sdkLite.ts"],"sourcesContent":["import {\n type DefaultLogLevels,\n type Logger,\n type RenderOptions,\n addTrackingPixel,\n createLogger,\n generateName,\n renderIframe,\n renderInline,\n round,\n} from '@adhese/sdk-shared';\nimport { name as packageName, version } from '../package.json';\n\ntype RenderMode = 'iframe' | 'inline';\n\nexport type AdheseLiteSlotOptions = {\n containingElement: HTMLElement;\n format: string;\n account: string;\n location: string;\n host?: string;\n debug?: boolean;\n renderMode?: RenderMode;\n parameters?: Record<string, string | ReadonlyArray<string>>;\n slot?: string;\n consent?: boolean | string;\n clickTrackerUrl?: string | URL;\n onDispose?(slot: AdheseLiteSlot): void;\n onRender?(slot: AdheseLiteSlot): void;\n onRequest?(slot: AdheseLiteSlot): void;\n onEmpty?(slot: AdheseLiteSlot): void;\n};\n\nexport type AdheseLiteSlot = {\n options: AdheseLiteSlotOptions;\n name: string;\n data?: AdheseLiteAd;\n logger: Logger<DefaultLogLevels>;\n parameters: Record<string, string | ReadonlyArray<string>>;\n render(): Promise<HTMLElement>;\n request(): Promise<AdheseLiteAd | null>;\n dispose(): void;\n};\n\nexport type AdheseLiteAd = {\n tag: string;\n width?: string;\n height?: string;\n impressionCounter?: string;\n viewableImpressionCounter?: string;\n};\n\nconst renderFunctions: Record<RenderMode, (ad: RenderOptions, element: HTMLElement) => void> = {\n iframe: renderIframe,\n inline: renderInline,\n};\n\nexport function createSlot(options: AdheseLiteSlotOptions): AdheseLiteSlot {\n const logger = createLogger({\n scope: `${packageName}@${version}`,\n minLogLevelThreshold: options.debug ? 'debug' : 'info',\n });\n\n const name = generateName(options.location, options.format, options.slot);\n\n const trackingPixels = new Set<HTMLImageElement>();\n\n const renderIntersectionObserver = new IntersectionObserver(onRenderIntersection, {\n rootMargin: '200px',\n threshold: 0,\n });\n\n const viewabilityTrackingIntersectionObserver = new IntersectionObserver(onViewabilityIntersection, {\n rootMargin: '0px',\n threshold: Array.from({ length: 11 }, (_, i) => i * 0.1),\n });\n\n const consentParameters: {\n tl: 'all' | 'none';\n } | {\n xt: string;\n } = typeof options.consent === 'string'\n ? {\n xt: options.consent,\n }\n : {\n tl: options.consent ? 'all' : 'none',\n };\n\n const parameters = {\n ...options.parameters,\n ...consentParameters,\n };\n\n let isImpressionTracked = false;\n\n const context: AdheseLiteSlot = {\n options,\n name,\n logger,\n parameters,\n async request(): Promise<AdheseLiteAd | null> {\n logger.debug(`Requesting ad for slot ${name}`, this);\n\n const response = await fetch(`${options.host ?? `https://ads-${options.account}.adhese.com`}/json`, {\n method: 'POST',\n body: JSON.stringify({\n slots: [{\n slotname: name,\n }],\n parameters,\n }),\n headers: {\n // eslint-disable-next-line ts/naming-convention\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok)\n throw new Error(`Failed to request ad for slot ${name}. Status: ${response.status}`);\n\n const [data] = await response.json() as ReadonlyArray<AdheseLiteAd>;\n\n this.data = data;\n\n logger.debug(`Received ad data for slot ${name}`, this);\n options.onRequest?.(this);\n\n return data;\n },\n async render(): Promise<HTMLElement> {\n const data = this.data ?? (await this.request());\n options.containingElement.removeEventListener('click', onClick);\n\n if (!data) {\n options.onEmpty?.(this);\n logger.debug(`Slot ${name} is empty`, this);\n\n return options.containingElement;\n }\n\n if (typeof data.tag !== 'string')\n throw new Error('Received invalid ad data, tag is not a string');\n\n renderFunctions[options.renderMode ?? 'iframe'](data, options.containingElement);\n\n options.onRender?.(this);\n logger.debug(`Rendered slot ${name}`, this);\n\n if (data.impressionCounter && !isImpressionTracked) {\n trackingPixels.add(addTrackingPixel(data.impressionCounter));\n isImpressionTracked = true;\n }\n\n if (data.viewableImpressionCounter) {\n viewabilityTrackingIntersectionObserver.observe(options.containingElement);\n }\n\n options.containingElement.addEventListener('click', onClick);\n\n return options.containingElement;\n },\n dispose(): void {\n options.onDispose?.(this);\n\n options.containingElement.innerHTML = '';\n\n for (const pixel of trackingPixels) {\n pixel.remove();\n }\n trackingPixels.clear();\n\n renderIntersectionObserver?.disconnect();\n viewabilityTrackingIntersectionObserver.disconnect();\n\n options.containingElement.removeEventListener('click', onClick);\n\n logger.debug(`Disposing slot ${name}`, this);\n\n logger.resetLogs();\n },\n };\n\n let isClickTracked = false;\n function onClick(): void {\n if (options.clickTrackerUrl && !isClickTracked) {\n trackingPixels.add(addTrackingPixel(options.clickTrackerUrl));\n isClickTracked = true;\n }\n }\n\n let timeoutId: number | null = null;\n function onViewabilityIntersection([entry]: ReadonlyArray<IntersectionObserverEntry>): void {\n const ratio = round(entry.intersectionRatio, 1);\n const threshold = 0.2;\n\n if (ratio >= threshold && !timeoutId) {\n // @ts-expect-error The is misfiring to the Node type\n timeoutId = setTimeout(() => {\n timeoutId = null;\n viewabilityTrackingIntersectionObserver.disconnect();\n\n if (context.data?.viewableImpressionCounter) {\n trackingPixels.add(addTrackingPixel(context.data?.viewableImpressionCounter));\n }\n }, 1000);\n }\n else if (ratio < threshold && timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n }\n\n function onRenderIntersection([entry]: ReadonlyArray<IntersectionObserverEntry>): void {\n if (entry.isIntersecting) {\n context.render().catch(logger.error);\n renderIntersectionObserver?.disconnect();\n }\n }\n renderIntersectionObserver.observe(options.containingElement);\n return context;\n}\n"],"names":["renderIframe","renderInline","createLogger","packageName","name","generateName","addTrackingPixel","round"],"mappings":"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"}
1
+ {"version":3,"file":"sdkLite.cjs","sources":["../../src/sdkLite.ts"],"sourcesContent":["import {\n type RenderOptions,\n addTrackingPixel,\n generateName,\n renderIframe,\n renderInline,\n round,\n uniqueId,\n} from '@adhese/sdk-shared';\n\ntype RenderMode = 'iframe' | 'inline';\n\nexport type AdheseLiteSlotOptions = {\n containingElement?: HTMLElement;\n format: string;\n account: string;\n location: string;\n host?: string;\n renderMode?: RenderMode;\n parameters?: Record<string, string | ReadonlyArray<string>>;\n slot?: string;\n consent?: boolean | string;\n clickTrackerUrl?: string | URL;\n onDispose?(slot: AdheseLiteSlot): void;\n onRender?(slot: AdheseLiteSlot): void;\n onRequest?(slot: AdheseLiteSlot): void;\n onEmpty?(slot: AdheseLiteSlot): void;\n};\n\nexport type AdheseLiteSlot = {\n options: AdheseLiteSlotOptions;\n name: string;\n data?: AdheseLiteAd;\n parameters: Record<string, string | ReadonlyArray<string>>;\n element: HTMLElement;\n render(): Promise<HTMLElement>;\n request(): Promise<AdheseLiteAd | null>;\n dispose(): void;\n};\n\nexport type AdheseLiteAd = {\n tag: string;\n width?: string;\n height?: string;\n impressionCounter?: string;\n viewableImpressionCounter?: string;\n};\n\nconst renderFunctions: Record<RenderMode, (ad: RenderOptions, element: HTMLElement) => void> = {\n iframe: renderIframe,\n inline: renderInline,\n};\n\nexport function createSlot(options: AdheseLiteSlotOptions): AdheseLiteSlot {\n const name = generateName(options.location, options.format, options.slot);\n\n const trackingPixels = new Set<HTMLImageElement>();\n\n const renderIntersectionObserver = new IntersectionObserver(onRenderIntersection, {\n rootMargin: '200px',\n threshold: 0,\n });\n\n const viewabilityTrackingIntersectionObserver = new IntersectionObserver(onViewabilityIntersection, {\n rootMargin: '0px',\n threshold: Array.from({ length: 11 }, (_, i) => i * 0.1),\n });\n\n const consentParameters: {\n tl: 'all' | 'none';\n } | {\n xt: string;\n } = typeof options.consent === 'string'\n ? {\n xt: options.consent,\n }\n : {\n tl: options.consent ? 'all' : 'none',\n };\n\n const parameters = {\n ...options.parameters,\n ...consentParameters,\n };\n\n let isImpressionTracked = false;\n\n const element = options.containingElement ?? document.createElement('div');\n\n if (!options.containingElement) {\n element.id = `${name}:${uniqueId(3)}`;\n element.classList.add('adunit');\n element.dataset.format = options.format;\n element.dataset.slot = options.format;\n element.dataset.location = options.location;\n\n document.currentScript?.insertAdjacentElement('beforebegin', element);\n }\n\n const context: AdheseLiteSlot = {\n options,\n name,\n parameters,\n element,\n async request(): Promise<AdheseLiteAd | null> {\n const response = await fetch(`${options.host ?? `https://ads-${options.account}.adhese.com`}/json`, {\n method: 'POST',\n body: JSON.stringify({\n slots: [{\n slotname: name,\n }],\n parameters,\n }),\n headers: {\n // eslint-disable-next-line ts/naming-convention\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok)\n throw new Error(`Failed to request ad for slot ${name}. Status: ${response.status}`);\n\n const [data] = await response.json() as ReadonlyArray<AdheseLiteAd>;\n\n this.data = data;\n\n options.onRequest?.(this);\n\n return data;\n },\n async render(): Promise<HTMLElement> {\n const data = this.data ?? (await this.request());\n element.removeEventListener('click', onClick);\n\n if (!data) {\n options.onEmpty?.(this);\n\n return element;\n }\n\n if (typeof data.tag !== 'string')\n throw new Error('Received invalid ad data, tag is not a string');\n\n renderFunctions[options.renderMode ?? 'iframe'](data, element);\n\n options.onRender?.(this);\n\n if (data.impressionCounter && !isImpressionTracked) {\n trackingPixels.add(addTrackingPixel(data.impressionCounter));\n isImpressionTracked = true;\n }\n\n if (data.viewableImpressionCounter) {\n viewabilityTrackingIntersectionObserver.observe(element);\n }\n\n element.addEventListener('click', onClick);\n\n return element;\n },\n dispose(): void {\n options.onDispose?.(this);\n\n element.innerHTML = '';\n\n for (const pixel of trackingPixels) {\n pixel.remove();\n }\n trackingPixels.clear();\n\n renderIntersectionObserver?.disconnect();\n viewabilityTrackingIntersectionObserver.disconnect();\n\n element.removeEventListener('click', onClick);\n },\n };\n\n let isClickTracked = false;\n function onClick(): void {\n if (options.clickTrackerUrl && !isClickTracked) {\n trackingPixels.add(addTrackingPixel(options.clickTrackerUrl));\n isClickTracked = true;\n }\n }\n\n let timeoutId: number | null = null;\n function onViewabilityIntersection([entry]: ReadonlyArray<IntersectionObserverEntry>): void {\n const ratio = round(entry.intersectionRatio, 1);\n const threshold = 0.2;\n\n if (ratio >= threshold && !timeoutId) {\n // @ts-expect-error The is misfiring to the Node type\n timeoutId = setTimeout(() => {\n timeoutId = null;\n viewabilityTrackingIntersectionObserver.disconnect();\n\n if (context.data?.viewableImpressionCounter) {\n trackingPixels.add(addTrackingPixel(context.data?.viewableImpressionCounter));\n }\n }, 1000);\n }\n else if (ratio < threshold && timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n }\n\n function onRenderIntersection([entry]: ReadonlyArray<IntersectionObserverEntry>): void {\n if (entry.isIntersecting) {\n context.render().catch(console.error);\n renderIntersectionObserver?.disconnect();\n }\n }\n renderIntersectionObserver.observe(element);\n return context;\n}\n\nexport { version } from '../package.json';\n"],"names":["renderIframe","renderInline","generateName","uniqueId","_a","addTrackingPixel","round"],"mappings":"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"}
package/dist/sdkLite.d.ts CHANGED
@@ -1,13 +1,12 @@
1
- import { Logger, DefaultLogLevels } from '@adhese/sdk-shared';
1
+ var version = "1.1.1";
2
2
 
3
3
  type RenderMode = 'iframe' | 'inline';
4
4
  type AdheseLiteSlotOptions = {
5
- containingElement: HTMLElement;
5
+ containingElement?: HTMLElement;
6
6
  format: string;
7
7
  account: string;
8
8
  location: string;
9
9
  host?: string;
10
- debug?: boolean;
11
10
  renderMode?: RenderMode;
12
11
  parameters?: Record<string, string | ReadonlyArray<string>>;
13
12
  slot?: string;
@@ -22,8 +21,8 @@ type AdheseLiteSlot = {
22
21
  options: AdheseLiteSlotOptions;
23
22
  name: string;
24
23
  data?: AdheseLiteAd;
25
- logger: Logger<DefaultLogLevels>;
26
24
  parameters: Record<string, string | ReadonlyArray<string>>;
25
+ element: HTMLElement;
27
26
  render(): Promise<HTMLElement>;
28
27
  request(): Promise<AdheseLiteAd | null>;
29
28
  dispose(): void;
@@ -37,4 +36,4 @@ type AdheseLiteAd = {
37
36
  };
38
37
  declare function createSlot(options: AdheseLiteSlotOptions): AdheseLiteSlot;
39
38
 
40
- export { type AdheseLiteAd, type AdheseLiteSlot, type AdheseLiteSlotOptions, createSlot };
39
+ export { type AdheseLiteAd, type AdheseLiteSlot, type AdheseLiteSlotOptions, createSlot, version };
package/dist/sdkLite.js CHANGED
@@ -1,16 +1,12 @@
1
- import { createLogger, generateName, round, addTrackingPixel, renderIframe, renderInline } from "@adhese/sdk-shared";
2
- const name = "@adhese/sdk-lite";
3
- const version = "1.0.0";
1
+ import { generateName, uniqueId, round, addTrackingPixel, renderIframe, renderInline } from "@adhese/sdk-shared";
2
+ const version = "1.1.1";
4
3
  const renderFunctions = {
5
4
  iframe: renderIframe,
6
5
  inline: renderInline
7
6
  };
8
7
  function createSlot(options) {
9
- const logger = createLogger({
10
- scope: `${name}@${version}`,
11
- minLogLevelThreshold: options.debug ? "debug" : "info"
12
- });
13
- const name$1 = generateName(options.location, options.format, options.slot);
8
+ var _a;
9
+ const name = generateName(options.location, options.format, options.slot);
14
10
  const trackingPixels = /* @__PURE__ */ new Set();
15
11
  const renderIntersectionObserver = new IntersectionObserver(onRenderIntersection, {
16
12
  rootMargin: "200px",
@@ -30,19 +26,27 @@ function createSlot(options) {
30
26
  ...consentParameters
31
27
  };
32
28
  let isImpressionTracked = false;
29
+ const element = options.containingElement ?? document.createElement("div");
30
+ if (!options.containingElement) {
31
+ element.id = `${name}:${uniqueId(3)}`;
32
+ element.classList.add("adunit");
33
+ element.dataset.format = options.format;
34
+ element.dataset.slot = options.format;
35
+ element.dataset.location = options.location;
36
+ (_a = document.currentScript) == null ? void 0 : _a.insertAdjacentElement("beforebegin", element);
37
+ }
33
38
  const context = {
34
39
  options,
35
- name: name$1,
36
- logger,
40
+ name,
37
41
  parameters,
42
+ element,
38
43
  async request() {
39
- var _a;
40
- logger.debug(`Requesting ad for slot ${name$1}`, this);
44
+ var _a2;
41
45
  const response = await fetch(`${options.host ?? `https://ads-${options.account}.adhese.com`}/json`, {
42
46
  method: "POST",
43
47
  body: JSON.stringify({
44
48
  slots: [{
45
- slotname: name$1
49
+ slotname: name
46
50
  }],
47
51
  parameters
48
52
  }),
@@ -52,50 +56,45 @@ function createSlot(options) {
52
56
  }
53
57
  });
54
58
  if (!response.ok)
55
- throw new Error(`Failed to request ad for slot ${name$1}. Status: ${response.status}`);
59
+ throw new Error(`Failed to request ad for slot ${name}. Status: ${response.status}`);
56
60
  const [data] = await response.json();
57
61
  this.data = data;
58
- logger.debug(`Received ad data for slot ${name$1}`, this);
59
- (_a = options.onRequest) == null ? void 0 : _a.call(options, this);
62
+ (_a2 = options.onRequest) == null ? void 0 : _a2.call(options, this);
60
63
  return data;
61
64
  },
62
65
  async render() {
63
- var _a, _b;
66
+ var _a2, _b;
64
67
  const data = this.data ?? await this.request();
65
- options.containingElement.removeEventListener("click", onClick);
68
+ element.removeEventListener("click", onClick);
66
69
  if (!data) {
67
- (_a = options.onEmpty) == null ? void 0 : _a.call(options, this);
68
- logger.debug(`Slot ${name$1} is empty`, this);
69
- return options.containingElement;
70
+ (_a2 = options.onEmpty) == null ? void 0 : _a2.call(options, this);
71
+ return element;
70
72
  }
71
73
  if (typeof data.tag !== "string")
72
74
  throw new Error("Received invalid ad data, tag is not a string");
73
- renderFunctions[options.renderMode ?? "iframe"](data, options.containingElement);
75
+ renderFunctions[options.renderMode ?? "iframe"](data, element);
74
76
  (_b = options.onRender) == null ? void 0 : _b.call(options, this);
75
- logger.debug(`Rendered slot ${name$1}`, this);
76
77
  if (data.impressionCounter && !isImpressionTracked) {
77
78
  trackingPixels.add(addTrackingPixel(data.impressionCounter));
78
79
  isImpressionTracked = true;
79
80
  }
80
81
  if (data.viewableImpressionCounter) {
81
- viewabilityTrackingIntersectionObserver.observe(options.containingElement);
82
+ viewabilityTrackingIntersectionObserver.observe(element);
82
83
  }
83
- options.containingElement.addEventListener("click", onClick);
84
- return options.containingElement;
84
+ element.addEventListener("click", onClick);
85
+ return element;
85
86
  },
86
87
  dispose() {
87
- var _a;
88
- (_a = options.onDispose) == null ? void 0 : _a.call(options, this);
89
- options.containingElement.innerHTML = "";
88
+ var _a2;
89
+ (_a2 = options.onDispose) == null ? void 0 : _a2.call(options, this);
90
+ element.innerHTML = "";
90
91
  for (const pixel of trackingPixels) {
91
92
  pixel.remove();
92
93
  }
93
94
  trackingPixels.clear();
94
95
  renderIntersectionObserver == null ? void 0 : renderIntersectionObserver.disconnect();
95
96
  viewabilityTrackingIntersectionObserver.disconnect();
96
- options.containingElement.removeEventListener("click", onClick);
97
- logger.debug(`Disposing slot ${name$1}`, this);
98
- logger.resetLogs();
97
+ element.removeEventListener("click", onClick);
99
98
  }
100
99
  };
101
100
  let isClickTracked = false;
@@ -111,10 +110,10 @@ function createSlot(options) {
111
110
  const threshold = 0.2;
112
111
  if (ratio >= threshold && !timeoutId) {
113
112
  timeoutId = setTimeout(() => {
114
- var _a, _b;
113
+ var _a2, _b;
115
114
  timeoutId = null;
116
115
  viewabilityTrackingIntersectionObserver.disconnect();
117
- if ((_a = context.data) == null ? void 0 : _a.viewableImpressionCounter) {
116
+ if ((_a2 = context.data) == null ? void 0 : _a2.viewableImpressionCounter) {
118
117
  trackingPixels.add(addTrackingPixel((_b = context.data) == null ? void 0 : _b.viewableImpressionCounter));
119
118
  }
120
119
  }, 1e3);
@@ -125,14 +124,15 @@ function createSlot(options) {
125
124
  }
126
125
  function onRenderIntersection([entry]) {
127
126
  if (entry.isIntersecting) {
128
- context.render().catch(logger.error);
127
+ context.render().catch(console.error);
129
128
  renderIntersectionObserver == null ? void 0 : renderIntersectionObserver.disconnect();
130
129
  }
131
130
  }
132
- renderIntersectionObserver.observe(options.containingElement);
131
+ renderIntersectionObserver.observe(element);
133
132
  return context;
134
133
  }
135
134
  export {
136
- createSlot
135
+ createSlot,
136
+ version
137
137
  };
138
138
  //# sourceMappingURL=sdkLite.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sdkLite.js","sources":["../src/sdkLite.ts"],"sourcesContent":["import {\n type DefaultLogLevels,\n type Logger,\n type RenderOptions,\n addTrackingPixel,\n createLogger,\n generateName,\n renderIframe,\n renderInline,\n round,\n} from '@adhese/sdk-shared';\nimport { name as packageName, version } from '../package.json';\n\ntype RenderMode = 'iframe' | 'inline';\n\nexport type AdheseLiteSlotOptions = {\n containingElement: HTMLElement;\n format: string;\n account: string;\n location: string;\n host?: string;\n debug?: boolean;\n renderMode?: RenderMode;\n parameters?: Record<string, string | ReadonlyArray<string>>;\n slot?: string;\n consent?: boolean | string;\n clickTrackerUrl?: string | URL;\n onDispose?(slot: AdheseLiteSlot): void;\n onRender?(slot: AdheseLiteSlot): void;\n onRequest?(slot: AdheseLiteSlot): void;\n onEmpty?(slot: AdheseLiteSlot): void;\n};\n\nexport type AdheseLiteSlot = {\n options: AdheseLiteSlotOptions;\n name: string;\n data?: AdheseLiteAd;\n logger: Logger<DefaultLogLevels>;\n parameters: Record<string, string | ReadonlyArray<string>>;\n render(): Promise<HTMLElement>;\n request(): Promise<AdheseLiteAd | null>;\n dispose(): void;\n};\n\nexport type AdheseLiteAd = {\n tag: string;\n width?: string;\n height?: string;\n impressionCounter?: string;\n viewableImpressionCounter?: string;\n};\n\nconst renderFunctions: Record<RenderMode, (ad: RenderOptions, element: HTMLElement) => void> = {\n iframe: renderIframe,\n inline: renderInline,\n};\n\nexport function createSlot(options: AdheseLiteSlotOptions): AdheseLiteSlot {\n const logger = createLogger({\n scope: `${packageName}@${version}`,\n minLogLevelThreshold: options.debug ? 'debug' : 'info',\n });\n\n const name = generateName(options.location, options.format, options.slot);\n\n const trackingPixels = new Set<HTMLImageElement>();\n\n const renderIntersectionObserver = new IntersectionObserver(onRenderIntersection, {\n rootMargin: '200px',\n threshold: 0,\n });\n\n const viewabilityTrackingIntersectionObserver = new IntersectionObserver(onViewabilityIntersection, {\n rootMargin: '0px',\n threshold: Array.from({ length: 11 }, (_, i) => i * 0.1),\n });\n\n const consentParameters: {\n tl: 'all' | 'none';\n } | {\n xt: string;\n } = typeof options.consent === 'string'\n ? {\n xt: options.consent,\n }\n : {\n tl: options.consent ? 'all' : 'none',\n };\n\n const parameters = {\n ...options.parameters,\n ...consentParameters,\n };\n\n let isImpressionTracked = false;\n\n const context: AdheseLiteSlot = {\n options,\n name,\n logger,\n parameters,\n async request(): Promise<AdheseLiteAd | null> {\n logger.debug(`Requesting ad for slot ${name}`, this);\n\n const response = await fetch(`${options.host ?? `https://ads-${options.account}.adhese.com`}/json`, {\n method: 'POST',\n body: JSON.stringify({\n slots: [{\n slotname: name,\n }],\n parameters,\n }),\n headers: {\n // eslint-disable-next-line ts/naming-convention\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok)\n throw new Error(`Failed to request ad for slot ${name}. Status: ${response.status}`);\n\n const [data] = await response.json() as ReadonlyArray<AdheseLiteAd>;\n\n this.data = data;\n\n logger.debug(`Received ad data for slot ${name}`, this);\n options.onRequest?.(this);\n\n return data;\n },\n async render(): Promise<HTMLElement> {\n const data = this.data ?? (await this.request());\n options.containingElement.removeEventListener('click', onClick);\n\n if (!data) {\n options.onEmpty?.(this);\n logger.debug(`Slot ${name} is empty`, this);\n\n return options.containingElement;\n }\n\n if (typeof data.tag !== 'string')\n throw new Error('Received invalid ad data, tag is not a string');\n\n renderFunctions[options.renderMode ?? 'iframe'](data, options.containingElement);\n\n options.onRender?.(this);\n logger.debug(`Rendered slot ${name}`, this);\n\n if (data.impressionCounter && !isImpressionTracked) {\n trackingPixels.add(addTrackingPixel(data.impressionCounter));\n isImpressionTracked = true;\n }\n\n if (data.viewableImpressionCounter) {\n viewabilityTrackingIntersectionObserver.observe(options.containingElement);\n }\n\n options.containingElement.addEventListener('click', onClick);\n\n return options.containingElement;\n },\n dispose(): void {\n options.onDispose?.(this);\n\n options.containingElement.innerHTML = '';\n\n for (const pixel of trackingPixels) {\n pixel.remove();\n }\n trackingPixels.clear();\n\n renderIntersectionObserver?.disconnect();\n viewabilityTrackingIntersectionObserver.disconnect();\n\n options.containingElement.removeEventListener('click', onClick);\n\n logger.debug(`Disposing slot ${name}`, this);\n\n logger.resetLogs();\n },\n };\n\n let isClickTracked = false;\n function onClick(): void {\n if (options.clickTrackerUrl && !isClickTracked) {\n trackingPixels.add(addTrackingPixel(options.clickTrackerUrl));\n isClickTracked = true;\n }\n }\n\n let timeoutId: number | null = null;\n function onViewabilityIntersection([entry]: ReadonlyArray<IntersectionObserverEntry>): void {\n const ratio = round(entry.intersectionRatio, 1);\n const threshold = 0.2;\n\n if (ratio >= threshold && !timeoutId) {\n // @ts-expect-error The is misfiring to the Node type\n timeoutId = setTimeout(() => {\n timeoutId = null;\n viewabilityTrackingIntersectionObserver.disconnect();\n\n if (context.data?.viewableImpressionCounter) {\n trackingPixels.add(addTrackingPixel(context.data?.viewableImpressionCounter));\n }\n }, 1000);\n }\n else if (ratio < threshold && timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n }\n\n function onRenderIntersection([entry]: ReadonlyArray<IntersectionObserverEntry>): void {\n if (entry.isIntersecting) {\n context.render().catch(logger.error);\n renderIntersectionObserver?.disconnect();\n }\n }\n renderIntersectionObserver.observe(options.containingElement);\n return context;\n}\n"],"names":["packageName","name"],"mappings":"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"}
1
+ {"version":3,"file":"sdkLite.js","sources":["../src/sdkLite.ts"],"sourcesContent":["import {\n type RenderOptions,\n addTrackingPixel,\n generateName,\n renderIframe,\n renderInline,\n round,\n uniqueId,\n} from '@adhese/sdk-shared';\n\ntype RenderMode = 'iframe' | 'inline';\n\nexport type AdheseLiteSlotOptions = {\n containingElement?: HTMLElement;\n format: string;\n account: string;\n location: string;\n host?: string;\n renderMode?: RenderMode;\n parameters?: Record<string, string | ReadonlyArray<string>>;\n slot?: string;\n consent?: boolean | string;\n clickTrackerUrl?: string | URL;\n onDispose?(slot: AdheseLiteSlot): void;\n onRender?(slot: AdheseLiteSlot): void;\n onRequest?(slot: AdheseLiteSlot): void;\n onEmpty?(slot: AdheseLiteSlot): void;\n};\n\nexport type AdheseLiteSlot = {\n options: AdheseLiteSlotOptions;\n name: string;\n data?: AdheseLiteAd;\n parameters: Record<string, string | ReadonlyArray<string>>;\n element: HTMLElement;\n render(): Promise<HTMLElement>;\n request(): Promise<AdheseLiteAd | null>;\n dispose(): void;\n};\n\nexport type AdheseLiteAd = {\n tag: string;\n width?: string;\n height?: string;\n impressionCounter?: string;\n viewableImpressionCounter?: string;\n};\n\nconst renderFunctions: Record<RenderMode, (ad: RenderOptions, element: HTMLElement) => void> = {\n iframe: renderIframe,\n inline: renderInline,\n};\n\nexport function createSlot(options: AdheseLiteSlotOptions): AdheseLiteSlot {\n const name = generateName(options.location, options.format, options.slot);\n\n const trackingPixels = new Set<HTMLImageElement>();\n\n const renderIntersectionObserver = new IntersectionObserver(onRenderIntersection, {\n rootMargin: '200px',\n threshold: 0,\n });\n\n const viewabilityTrackingIntersectionObserver = new IntersectionObserver(onViewabilityIntersection, {\n rootMargin: '0px',\n threshold: Array.from({ length: 11 }, (_, i) => i * 0.1),\n });\n\n const consentParameters: {\n tl: 'all' | 'none';\n } | {\n xt: string;\n } = typeof options.consent === 'string'\n ? {\n xt: options.consent,\n }\n : {\n tl: options.consent ? 'all' : 'none',\n };\n\n const parameters = {\n ...options.parameters,\n ...consentParameters,\n };\n\n let isImpressionTracked = false;\n\n const element = options.containingElement ?? document.createElement('div');\n\n if (!options.containingElement) {\n element.id = `${name}:${uniqueId(3)}`;\n element.classList.add('adunit');\n element.dataset.format = options.format;\n element.dataset.slot = options.format;\n element.dataset.location = options.location;\n\n document.currentScript?.insertAdjacentElement('beforebegin', element);\n }\n\n const context: AdheseLiteSlot = {\n options,\n name,\n parameters,\n element,\n async request(): Promise<AdheseLiteAd | null> {\n const response = await fetch(`${options.host ?? `https://ads-${options.account}.adhese.com`}/json`, {\n method: 'POST',\n body: JSON.stringify({\n slots: [{\n slotname: name,\n }],\n parameters,\n }),\n headers: {\n // eslint-disable-next-line ts/naming-convention\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok)\n throw new Error(`Failed to request ad for slot ${name}. Status: ${response.status}`);\n\n const [data] = await response.json() as ReadonlyArray<AdheseLiteAd>;\n\n this.data = data;\n\n options.onRequest?.(this);\n\n return data;\n },\n async render(): Promise<HTMLElement> {\n const data = this.data ?? (await this.request());\n element.removeEventListener('click', onClick);\n\n if (!data) {\n options.onEmpty?.(this);\n\n return element;\n }\n\n if (typeof data.tag !== 'string')\n throw new Error('Received invalid ad data, tag is not a string');\n\n renderFunctions[options.renderMode ?? 'iframe'](data, element);\n\n options.onRender?.(this);\n\n if (data.impressionCounter && !isImpressionTracked) {\n trackingPixels.add(addTrackingPixel(data.impressionCounter));\n isImpressionTracked = true;\n }\n\n if (data.viewableImpressionCounter) {\n viewabilityTrackingIntersectionObserver.observe(element);\n }\n\n element.addEventListener('click', onClick);\n\n return element;\n },\n dispose(): void {\n options.onDispose?.(this);\n\n element.innerHTML = '';\n\n for (const pixel of trackingPixels) {\n pixel.remove();\n }\n trackingPixels.clear();\n\n renderIntersectionObserver?.disconnect();\n viewabilityTrackingIntersectionObserver.disconnect();\n\n element.removeEventListener('click', onClick);\n },\n };\n\n let isClickTracked = false;\n function onClick(): void {\n if (options.clickTrackerUrl && !isClickTracked) {\n trackingPixels.add(addTrackingPixel(options.clickTrackerUrl));\n isClickTracked = true;\n }\n }\n\n let timeoutId: number | null = null;\n function onViewabilityIntersection([entry]: ReadonlyArray<IntersectionObserverEntry>): void {\n const ratio = round(entry.intersectionRatio, 1);\n const threshold = 0.2;\n\n if (ratio >= threshold && !timeoutId) {\n // @ts-expect-error The is misfiring to the Node type\n timeoutId = setTimeout(() => {\n timeoutId = null;\n viewabilityTrackingIntersectionObserver.disconnect();\n\n if (context.data?.viewableImpressionCounter) {\n trackingPixels.add(addTrackingPixel(context.data?.viewableImpressionCounter));\n }\n }, 1000);\n }\n else if (ratio < threshold && timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n }\n\n function onRenderIntersection([entry]: ReadonlyArray<IntersectionObserverEntry>): void {\n if (entry.isIntersecting) {\n context.render().catch(console.error);\n renderIntersectionObserver?.disconnect();\n }\n }\n renderIntersectionObserver.observe(element);\n return context;\n}\n\nexport { version } from '../package.json';\n"],"names":["_a"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@adhese/sdk-lite",
3
3
  "type": "module",
4
- "version": "1.0.0",
4
+ "version": "1.1.1",
5
5
  "description": "Adhese SDK",
6
6
  "repository": {
7
7
  "type": "git",