@adhese/sdk-lite 1.1.0 → 1.2.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/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @adhese/sdk-lite
2
2
 
3
+ ## 1.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 112e224: Add `width` and `height` option to overwrite slot sizing
8
+
9
+ **NOTE**: Only applies when `renderMode` is `iframe` or `undefined`
10
+
11
+ ### Patch Changes
12
+
13
+ - Updated dependencies [112e224]
14
+ - @adhese/sdk-shared@1.1.0
15
+
16
+ ## 1.1.1
17
+
18
+ ### Patch Changes
19
+
20
+ - d29a909: Remove logger to optmize output js file
21
+
3
22
  ## 1.1.0
4
23
 
5
24
  ### Minor Changes
@@ -1,19 +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.1.0";
4
+ const version = "1.2.0";
6
5
  const renderFunctions = {
7
6
  iframe: sdkShared.renderIframe,
8
7
  inline: sdkShared.renderInline
9
8
  };
10
9
  function createSlot(options) {
11
10
  var _a;
12
- const logger = sdkShared.createLogger({
13
- scope: `${name}@${version}`,
14
- minLogLevelThreshold: options.debug ? "debug" : "info"
15
- });
16
- const name$1 = sdkShared.generateName(options.location, options.format, options.slot);
11
+ const name = sdkShared.generateName(options.location, options.format, options.slot);
17
12
  const trackingPixels = /* @__PURE__ */ new Set();
18
13
  const renderIntersectionObserver = new IntersectionObserver(onRenderIntersection, {
19
14
  rootMargin: "200px",
@@ -35,7 +30,7 @@ function createSlot(options) {
35
30
  let isImpressionTracked = false;
36
31
  const element = options.containingElement ?? document.createElement("div");
37
32
  if (!options.containingElement) {
38
- element.id = `${name$1}:${sdkShared.uniqueId(3)}`;
33
+ element.id = `${name}:${sdkShared.uniqueId(3)}`;
39
34
  element.classList.add("adunit");
40
35
  element.dataset.format = options.format;
41
36
  element.dataset.slot = options.format;
@@ -44,18 +39,16 @@ function createSlot(options) {
44
39
  }
45
40
  const context = {
46
41
  options,
47
- name: name$1,
48
- logger,
42
+ name,
49
43
  parameters,
50
44
  element,
51
45
  async request() {
52
46
  var _a2;
53
- logger.debug(`Requesting ad for slot ${name$1}`, this);
54
47
  const response = await fetch(`${options.host ?? `https://ads-${options.account}.adhese.com`}/json`, {
55
48
  method: "POST",
56
49
  body: JSON.stringify({
57
50
  slots: [{
58
- slotname: name$1
51
+ slotname: name
59
52
  }],
60
53
  parameters
61
54
  }),
@@ -65,10 +58,9 @@ function createSlot(options) {
65
58
  }
66
59
  });
67
60
  if (!response.ok)
68
- 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}`);
69
62
  const [data] = await response.json();
70
63
  this.data = data;
71
- logger.debug(`Received ad data for slot ${name$1}`, this);
72
64
  (_a2 = options.onRequest) == null ? void 0 : _a2.call(options, this);
73
65
  return data;
74
66
  },
@@ -78,14 +70,15 @@ function createSlot(options) {
78
70
  element.removeEventListener("click", onClick);
79
71
  if (!data) {
80
72
  (_a2 = options.onEmpty) == null ? void 0 : _a2.call(options, this);
81
- logger.debug(`Slot ${name$1} is empty`, this);
82
73
  return element;
83
74
  }
84
75
  if (typeof data.tag !== "string")
85
76
  throw new Error("Received invalid ad data, tag is not a string");
86
- renderFunctions[options.renderMode ?? "iframe"](data, element);
77
+ renderFunctions[options.renderMode ?? "iframe"]({
78
+ ...data,
79
+ ...sdkShared.pick(options, ["width", "height"])
80
+ }, element);
87
81
  (_b = options.onRender) == null ? void 0 : _b.call(options, this);
88
- logger.debug(`Rendered slot ${name$1}`, this);
89
82
  if (data.impressionCounter && !isImpressionTracked) {
90
83
  trackingPixels.add(sdkShared.addTrackingPixel(data.impressionCounter));
91
84
  isImpressionTracked = true;
@@ -107,8 +100,6 @@ function createSlot(options) {
107
100
  renderIntersectionObserver == null ? void 0 : renderIntersectionObserver.disconnect();
108
101
  viewabilityTrackingIntersectionObserver.disconnect();
109
102
  element.removeEventListener("click", onClick);
110
- logger.debug(`Disposing slot ${name$1}`, this);
111
- logger.resetLogs();
112
103
  }
113
104
  };
114
105
  let isClickTracked = false;
@@ -138,7 +129,7 @@ function createSlot(options) {
138
129
  }
139
130
  function onRenderIntersection([entry]) {
140
131
  if (entry.isIntersecting) {
141
- context.render().catch(logger.error);
132
+ context.render().catch(console.error);
142
133
  renderIntersectionObserver == null ? void 0 : renderIntersectionObserver.disconnect();
143
134
  }
144
135
  }
@@ -146,4 +137,5 @@ function createSlot(options) {
146
137
  return context;
147
138
  }
148
139
  exports.createSlot = createSlot;
140
+ exports.version = version;
149
141
  //# 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 uniqueId,\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 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 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 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 logger,\n parameters,\n element,\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 element.removeEventListener('click', onClick);\n\n if (!data) {\n options.onEmpty?.(this);\n logger.debug(`Slot ${name} is empty`, 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 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(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 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(element);\n return context;\n}\n"],"names":["renderIframe","renderInline","createLogger","packageName","name","generateName","uniqueId","_a","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 pick,\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 width?: string | number;\n height?: string | number;\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']({\n ...data,\n ...pick(options, ['width', 'height']),\n }, 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","pick","addTrackingPixel","round"],"mappings":"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"}
package/dist/sdkLite.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Logger, DefaultLogLevels } from '@adhese/sdk-shared';
1
+ var version = "1.2.0";
2
2
 
3
3
  type RenderMode = 'iframe' | 'inline';
4
4
  type AdheseLiteSlotOptions = {
@@ -7,8 +7,9 @@ type AdheseLiteSlotOptions = {
7
7
  account: string;
8
8
  location: string;
9
9
  host?: string;
10
- debug?: boolean;
11
10
  renderMode?: RenderMode;
11
+ width?: string | number;
12
+ height?: string | number;
12
13
  parameters?: Record<string, string | ReadonlyArray<string>>;
13
14
  slot?: string;
14
15
  consent?: boolean | string;
@@ -22,7 +23,6 @@ type AdheseLiteSlot = {
22
23
  options: AdheseLiteSlotOptions;
23
24
  name: string;
24
25
  data?: AdheseLiteAd;
25
- logger: Logger<DefaultLogLevels>;
26
26
  parameters: Record<string, string | ReadonlyArray<string>>;
27
27
  element: HTMLElement;
28
28
  render(): Promise<HTMLElement>;
@@ -38,4 +38,4 @@ type AdheseLiteAd = {
38
38
  };
39
39
  declare function createSlot(options: AdheseLiteSlotOptions): AdheseLiteSlot;
40
40
 
41
- export { type AdheseLiteAd, type AdheseLiteSlot, type AdheseLiteSlotOptions, createSlot };
41
+ export { type AdheseLiteAd, type AdheseLiteSlot, type AdheseLiteSlotOptions, createSlot, version };
package/dist/sdkLite.js CHANGED
@@ -1,17 +1,12 @@
1
- import { createLogger, generateName, uniqueId, round, addTrackingPixel, renderIframe, renderInline } from "@adhese/sdk-shared";
2
- const name = "@adhese/sdk-lite";
3
- const version = "1.1.0";
1
+ import { generateName, uniqueId, round, addTrackingPixel, pick, renderIframe, renderInline } from "@adhese/sdk-shared";
2
+ const version = "1.2.0";
4
3
  const renderFunctions = {
5
4
  iframe: renderIframe,
6
5
  inline: renderInline
7
6
  };
8
7
  function createSlot(options) {
9
8
  var _a;
10
- const logger = createLogger({
11
- scope: `${name}@${version}`,
12
- minLogLevelThreshold: options.debug ? "debug" : "info"
13
- });
14
- const name$1 = generateName(options.location, options.format, options.slot);
9
+ const name = generateName(options.location, options.format, options.slot);
15
10
  const trackingPixels = /* @__PURE__ */ new Set();
16
11
  const renderIntersectionObserver = new IntersectionObserver(onRenderIntersection, {
17
12
  rootMargin: "200px",
@@ -33,7 +28,7 @@ function createSlot(options) {
33
28
  let isImpressionTracked = false;
34
29
  const element = options.containingElement ?? document.createElement("div");
35
30
  if (!options.containingElement) {
36
- element.id = `${name$1}:${uniqueId(3)}`;
31
+ element.id = `${name}:${uniqueId(3)}`;
37
32
  element.classList.add("adunit");
38
33
  element.dataset.format = options.format;
39
34
  element.dataset.slot = options.format;
@@ -42,18 +37,16 @@ function createSlot(options) {
42
37
  }
43
38
  const context = {
44
39
  options,
45
- name: name$1,
46
- logger,
40
+ name,
47
41
  parameters,
48
42
  element,
49
43
  async request() {
50
44
  var _a2;
51
- logger.debug(`Requesting ad for slot ${name$1}`, this);
52
45
  const response = await fetch(`${options.host ?? `https://ads-${options.account}.adhese.com`}/json`, {
53
46
  method: "POST",
54
47
  body: JSON.stringify({
55
48
  slots: [{
56
- slotname: name$1
49
+ slotname: name
57
50
  }],
58
51
  parameters
59
52
  }),
@@ -63,10 +56,9 @@ function createSlot(options) {
63
56
  }
64
57
  });
65
58
  if (!response.ok)
66
- 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}`);
67
60
  const [data] = await response.json();
68
61
  this.data = data;
69
- logger.debug(`Received ad data for slot ${name$1}`, this);
70
62
  (_a2 = options.onRequest) == null ? void 0 : _a2.call(options, this);
71
63
  return data;
72
64
  },
@@ -76,14 +68,15 @@ function createSlot(options) {
76
68
  element.removeEventListener("click", onClick);
77
69
  if (!data) {
78
70
  (_a2 = options.onEmpty) == null ? void 0 : _a2.call(options, this);
79
- logger.debug(`Slot ${name$1} is empty`, this);
80
71
  return element;
81
72
  }
82
73
  if (typeof data.tag !== "string")
83
74
  throw new Error("Received invalid ad data, tag is not a string");
84
- renderFunctions[options.renderMode ?? "iframe"](data, element);
75
+ renderFunctions[options.renderMode ?? "iframe"]({
76
+ ...data,
77
+ ...pick(options, ["width", "height"])
78
+ }, element);
85
79
  (_b = options.onRender) == null ? void 0 : _b.call(options, this);
86
- logger.debug(`Rendered slot ${name$1}`, this);
87
80
  if (data.impressionCounter && !isImpressionTracked) {
88
81
  trackingPixels.add(addTrackingPixel(data.impressionCounter));
89
82
  isImpressionTracked = true;
@@ -105,8 +98,6 @@ function createSlot(options) {
105
98
  renderIntersectionObserver == null ? void 0 : renderIntersectionObserver.disconnect();
106
99
  viewabilityTrackingIntersectionObserver.disconnect();
107
100
  element.removeEventListener("click", onClick);
108
- logger.debug(`Disposing slot ${name$1}`, this);
109
- logger.resetLogs();
110
101
  }
111
102
  };
112
103
  let isClickTracked = false;
@@ -136,7 +127,7 @@ function createSlot(options) {
136
127
  }
137
128
  function onRenderIntersection([entry]) {
138
129
  if (entry.isIntersecting) {
139
- context.render().catch(logger.error);
130
+ context.render().catch(console.error);
140
131
  renderIntersectionObserver == null ? void 0 : renderIntersectionObserver.disconnect();
141
132
  }
142
133
  }
@@ -144,6 +135,7 @@ function createSlot(options) {
144
135
  return context;
145
136
  }
146
137
  export {
147
- createSlot
138
+ createSlot,
139
+ version
148
140
  };
149
141
  //# 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 uniqueId,\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 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 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 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 logger,\n parameters,\n element,\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 element.removeEventListener('click', onClick);\n\n if (!data) {\n options.onEmpty?.(this);\n logger.debug(`Slot ${name} is empty`, 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 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(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 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(element);\n return context;\n}\n"],"names":["packageName","name","_a"],"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 pick,\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 width?: string | number;\n height?: string | number;\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']({\n ...data,\n ...pick(options, ['width', 'height']),\n }, 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.1.0",
4
+ "version": "1.2.0",
5
5
  "description": "Adhese SDK",
6
6
  "repository": {
7
7
  "type": "git",
@@ -31,6 +31,6 @@
31
31
  "prepareRelease": "npm run build"
32
32
  },
33
33
  "dependencies": {
34
- "@adhese/sdk-shared": "^1.0.0"
34
+ "@adhese/sdk-shared": "^1.1.0"
35
35
  }
36
36
  }