@adviverse/react 1.0.1 → 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
@@ -50,6 +50,18 @@ img-src https://cdn.adviverse.com https://serve.adviverse.com data:
50
50
  connect-src https://serve.adviverse.com
51
51
  ```
52
52
 
53
+ ## Versioning
54
+
55
+ By default the components load the **pinned** `/sdk/v1.js`, so a breaking SDK change can never silently alter your integration — the package major tracks the SDK major (`@adviverse/react@2` → `v2`). Escape hatches:
56
+
57
+ ```tsx
58
+ <AdSlot tag="tk_…" version="v2" /> // canary a newer line
59
+ <AdSlot tag="tk_…" src="https://serve.adviverse.com/sdk/1.2.3.js" /> // exact pin / self-host
60
+ <AdScript version="" /> // unversioned latest
61
+ ```
62
+
63
+ `loadSdk()` also accepts `{ endpoint, version, src }` (the string form `loadSdk("https://…")` still works).
64
+
53
65
  ## Debugging
54
66
 
55
67
  Add `?adviverse_debug=1` to the URL (or set `window.ADVIVERSE_DEBUG = true`) to console-log each request, the resolved size, and any no-fill reason. Use the reserved tag `tk_test` to render a labeled test ad that always fills — verify your integration before a campaign is live.
package/dist/index.cjs CHANGED
@@ -4,12 +4,19 @@ var react = require('react');
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
5
 
6
6
  var DEFAULT_ENDPOINT = "https://serve.adviverse.com";
7
+ var DEFAULT_VERSION = "v1";
8
+ function sdkUrl(opts) {
9
+ if (opts.src) return opts.src;
10
+ const base = (opts.endpoint || window.ADVIVERSE_ENDPOINT || DEFAULT_ENDPOINT).replace(/\/$/, "");
11
+ const version = opts.version ?? DEFAULT_VERSION;
12
+ return version ? `${base}/sdk/${version}.js` : `${base}/sdk.js`;
13
+ }
7
14
  var loadPromise = null;
8
- function loadSdk(endpoint) {
15
+ function loadSdk(arg) {
9
16
  if (typeof window === "undefined" || typeof document === "undefined") return Promise.resolve();
10
17
  if (window.adviverse && window.adviverse.render) return Promise.resolve();
11
18
  if (loadPromise) return loadPromise;
12
- const base = (endpoint || window.ADVIVERSE_ENDPOINT || DEFAULT_ENDPOINT).replace(/\/$/, "");
19
+ const opts = typeof arg === "string" ? { endpoint: arg } : arg ?? {};
13
20
  loadPromise = new Promise((resolve, reject) => {
14
21
  const existing = document.querySelector("script[data-adviverse-sdk]");
15
22
  if (existing) {
@@ -20,7 +27,7 @@ function loadSdk(endpoint) {
20
27
  }
21
28
  const s = document.createElement("script");
22
29
  s.async = true;
23
- s.src = base + "/sdk.js";
30
+ s.src = sdkUrl(opts);
24
31
  s.crossOrigin = "anonymous";
25
32
  s.setAttribute("data-adviverse-sdk", "1");
26
33
  s.onload = () => resolve();
@@ -29,12 +36,12 @@ function loadSdk(endpoint) {
29
36
  });
30
37
  return loadPromise;
31
38
  }
32
- function AdSlot({ tag, sizes, endpoint, ...rest }) {
39
+ function AdSlot({ tag, sizes, endpoint, version, src, ...rest }) {
33
40
  const ref = react.useRef(null);
34
41
  react.useEffect(() => {
35
42
  let dead = false;
36
43
  const el = ref.current;
37
- loadSdk(endpoint).then(() => {
44
+ loadSdk({ endpoint, version, src }).then(() => {
38
45
  if (dead || !el) return;
39
46
  window.adviverse?.render?.(el, { tag, sizes });
40
47
  }).catch(() => {
@@ -43,14 +50,14 @@ function AdSlot({ tag, sizes, endpoint, ...rest }) {
43
50
  dead = true;
44
51
  if (el) window.adviverse?.destroy?.(el);
45
52
  };
46
- }, [tag, sizes, endpoint]);
53
+ }, [tag, sizes, endpoint, version, src]);
47
54
  return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, "data-tag": tag, "data-sizes": sizes, ...rest });
48
55
  }
49
- function AdScript({ endpoint }) {
56
+ function AdScript({ endpoint, version, src }) {
50
57
  react.useEffect(() => {
51
- loadSdk(endpoint).catch(() => {
58
+ loadSdk({ endpoint, version, src }).catch(() => {
52
59
  });
53
- }, [endpoint]);
60
+ }, [endpoint, version, src]);
54
61
  return null;
55
62
  }
56
63
  function AdRefresh({ routeKey }) {
package/dist/index.d.cts CHANGED
@@ -32,8 +32,17 @@ declare global {
32
32
  ADVIVERSE_DEBUG?: boolean;
33
33
  }
34
34
  }
35
- /** Load the Adviverse SDK once (idempotent). Resolves when it's ready. */
36
- declare function loadSdk(endpoint?: string): Promise<void>;
35
+ interface LoadOptions {
36
+ /** Ad-server origin. Default https://serve.adviverse.com (or window.ADVIVERSE_ENDPOINT). */
37
+ endpoint?: string;
38
+ /** SDK major line, e.g. "v1". Defaults to the line this package targets; pass "" for unversioned latest. */
39
+ version?: string;
40
+ /** Full SDK URL override (wins over endpoint/version) — exact pin or self-host. */
41
+ src?: string;
42
+ }
43
+ /** Load the Adviverse SDK once (idempotent). Resolves when it's ready. Accepts an
44
+ * endpoint string (back-compat) or {endpoint, version, src}. */
45
+ declare function loadSdk(arg?: string | LoadOptions): Promise<void>;
37
46
  interface AdSlotProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
38
47
  /** Placement tag key, e.g. "tk_80f77ad8d23bdbd927". */
39
48
  tag: string;
@@ -45,20 +54,23 @@ interface AdSlotProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
45
54
  sizes?: string;
46
55
  /** Size the box here (or via className) — the ad matches it. */
47
56
  style?: CSSProperties;
57
+ /** Ad-server origin override. */
48
58
  endpoint?: string;
59
+ /** SDK major line, e.g. "v1" (default) or "v2"; "" for unversioned latest. */
60
+ version?: string;
61
+ /** Full SDK URL override (exact pin / self-host). */
62
+ src?: string;
49
63
  }
50
64
  /**
51
65
  * A single ad slot. Size it with `style`/`className` (or pass `sizes`); the SDK
52
66
  * fills the box and tears down on unmount.
53
67
  */
54
- declare function AdSlot({ tag, sizes, endpoint, ...rest }: AdSlotProps): react.JSX.Element;
68
+ declare function AdSlot({ tag, sizes, endpoint, version, src, ...rest }: AdSlotProps): react.JSX.Element;
55
69
  /**
56
70
  * Loads the SDK once, explicitly (optional — <AdSlot> loads it lazily too). Handy
57
- * in a root layout if you prefer the loader mounted up front.
71
+ * in a root layout, or to canary a version: `<AdScript version="v2" />`.
58
72
  */
59
- declare function AdScript({ endpoint }: {
60
- endpoint?: string;
61
- }): null;
73
+ declare function AdScript({ endpoint, version, src }: LoadOptions): null;
62
74
  /**
63
75
  * Refill ad slots after a client-side route change (SPA). Pass a value that
64
76
  * changes per route — e.g. Next.js App Router: `<AdRefresh routeKey={usePathname()} />`.
@@ -68,4 +80,4 @@ declare function AdRefresh({ routeKey }: {
68
80
  routeKey?: string | number;
69
81
  }): null;
70
82
 
71
- export { AdRefresh, AdScript, AdSlot, type AdSlotProps, loadSdk };
83
+ export { AdRefresh, AdScript, AdSlot, type AdSlotProps, type LoadOptions, loadSdk };
package/dist/index.d.ts CHANGED
@@ -32,8 +32,17 @@ declare global {
32
32
  ADVIVERSE_DEBUG?: boolean;
33
33
  }
34
34
  }
35
- /** Load the Adviverse SDK once (idempotent). Resolves when it's ready. */
36
- declare function loadSdk(endpoint?: string): Promise<void>;
35
+ interface LoadOptions {
36
+ /** Ad-server origin. Default https://serve.adviverse.com (or window.ADVIVERSE_ENDPOINT). */
37
+ endpoint?: string;
38
+ /** SDK major line, e.g. "v1". Defaults to the line this package targets; pass "" for unversioned latest. */
39
+ version?: string;
40
+ /** Full SDK URL override (wins over endpoint/version) — exact pin or self-host. */
41
+ src?: string;
42
+ }
43
+ /** Load the Adviverse SDK once (idempotent). Resolves when it's ready. Accepts an
44
+ * endpoint string (back-compat) or {endpoint, version, src}. */
45
+ declare function loadSdk(arg?: string | LoadOptions): Promise<void>;
37
46
  interface AdSlotProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
38
47
  /** Placement tag key, e.g. "tk_80f77ad8d23bdbd927". */
39
48
  tag: string;
@@ -45,20 +54,23 @@ interface AdSlotProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
45
54
  sizes?: string;
46
55
  /** Size the box here (or via className) — the ad matches it. */
47
56
  style?: CSSProperties;
57
+ /** Ad-server origin override. */
48
58
  endpoint?: string;
59
+ /** SDK major line, e.g. "v1" (default) or "v2"; "" for unversioned latest. */
60
+ version?: string;
61
+ /** Full SDK URL override (exact pin / self-host). */
62
+ src?: string;
49
63
  }
50
64
  /**
51
65
  * A single ad slot. Size it with `style`/`className` (or pass `sizes`); the SDK
52
66
  * fills the box and tears down on unmount.
53
67
  */
54
- declare function AdSlot({ tag, sizes, endpoint, ...rest }: AdSlotProps): react.JSX.Element;
68
+ declare function AdSlot({ tag, sizes, endpoint, version, src, ...rest }: AdSlotProps): react.JSX.Element;
55
69
  /**
56
70
  * Loads the SDK once, explicitly (optional — <AdSlot> loads it lazily too). Handy
57
- * in a root layout if you prefer the loader mounted up front.
71
+ * in a root layout, or to canary a version: `<AdScript version="v2" />`.
58
72
  */
59
- declare function AdScript({ endpoint }: {
60
- endpoint?: string;
61
- }): null;
73
+ declare function AdScript({ endpoint, version, src }: LoadOptions): null;
62
74
  /**
63
75
  * Refill ad slots after a client-side route change (SPA). Pass a value that
64
76
  * changes per route — e.g. Next.js App Router: `<AdRefresh routeKey={usePathname()} />`.
@@ -68,4 +80,4 @@ declare function AdRefresh({ routeKey }: {
68
80
  routeKey?: string | number;
69
81
  }): null;
70
82
 
71
- export { AdRefresh, AdScript, AdSlot, type AdSlotProps, loadSdk };
83
+ export { AdRefresh, AdScript, AdSlot, type AdSlotProps, type LoadOptions, loadSdk };
package/dist/index.js CHANGED
@@ -2,12 +2,19 @@ import { useRef, useEffect } from 'react';
2
2
  import { jsx } from 'react/jsx-runtime';
3
3
 
4
4
  var DEFAULT_ENDPOINT = "https://serve.adviverse.com";
5
+ var DEFAULT_VERSION = "v1";
6
+ function sdkUrl(opts) {
7
+ if (opts.src) return opts.src;
8
+ const base = (opts.endpoint || window.ADVIVERSE_ENDPOINT || DEFAULT_ENDPOINT).replace(/\/$/, "");
9
+ const version = opts.version ?? DEFAULT_VERSION;
10
+ return version ? `${base}/sdk/${version}.js` : `${base}/sdk.js`;
11
+ }
5
12
  var loadPromise = null;
6
- function loadSdk(endpoint) {
13
+ function loadSdk(arg) {
7
14
  if (typeof window === "undefined" || typeof document === "undefined") return Promise.resolve();
8
15
  if (window.adviverse && window.adviverse.render) return Promise.resolve();
9
16
  if (loadPromise) return loadPromise;
10
- const base = (endpoint || window.ADVIVERSE_ENDPOINT || DEFAULT_ENDPOINT).replace(/\/$/, "");
17
+ const opts = typeof arg === "string" ? { endpoint: arg } : arg ?? {};
11
18
  loadPromise = new Promise((resolve, reject) => {
12
19
  const existing = document.querySelector("script[data-adviverse-sdk]");
13
20
  if (existing) {
@@ -18,7 +25,7 @@ function loadSdk(endpoint) {
18
25
  }
19
26
  const s = document.createElement("script");
20
27
  s.async = true;
21
- s.src = base + "/sdk.js";
28
+ s.src = sdkUrl(opts);
22
29
  s.crossOrigin = "anonymous";
23
30
  s.setAttribute("data-adviverse-sdk", "1");
24
31
  s.onload = () => resolve();
@@ -27,12 +34,12 @@ function loadSdk(endpoint) {
27
34
  });
28
35
  return loadPromise;
29
36
  }
30
- function AdSlot({ tag, sizes, endpoint, ...rest }) {
37
+ function AdSlot({ tag, sizes, endpoint, version, src, ...rest }) {
31
38
  const ref = useRef(null);
32
39
  useEffect(() => {
33
40
  let dead = false;
34
41
  const el = ref.current;
35
- loadSdk(endpoint).then(() => {
42
+ loadSdk({ endpoint, version, src }).then(() => {
36
43
  if (dead || !el) return;
37
44
  window.adviverse?.render?.(el, { tag, sizes });
38
45
  }).catch(() => {
@@ -41,14 +48,14 @@ function AdSlot({ tag, sizes, endpoint, ...rest }) {
41
48
  dead = true;
42
49
  if (el) window.adviverse?.destroy?.(el);
43
50
  };
44
- }, [tag, sizes, endpoint]);
51
+ }, [tag, sizes, endpoint, version, src]);
45
52
  return /* @__PURE__ */ jsx("div", { ref, "data-tag": tag, "data-sizes": sizes, ...rest });
46
53
  }
47
- function AdScript({ endpoint }) {
54
+ function AdScript({ endpoint, version, src }) {
48
55
  useEffect(() => {
49
- loadSdk(endpoint).catch(() => {
56
+ loadSdk({ endpoint, version, src }).catch(() => {
50
57
  });
51
- }, [endpoint]);
58
+ }, [endpoint, version, src]);
52
59
  return null;
53
60
  }
54
61
  function AdRefresh({ routeKey }) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@adviverse/react",
3
- "version": "1.0.1",
4
- "description": "React components for Adviverse ad slots <AdSlot />, <AdScript />, <AdRefresh />. One import, no dangerouslySetInnerHTML, no currentScript workarounds.",
3
+ "version": "1.1.0",
4
+ "description": "React components for Adviverse ad slots \u2014 <AdSlot />, <AdScript />, <AdRefresh />. One import, no dangerouslySetInnerHTML, no currentScript workarounds.",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -23,12 +23,21 @@
23
23
  }
24
24
  },
25
25
  "sideEffects": false,
26
- "files": ["dist", "README.md"],
26
+ "files": [
27
+ "dist",
28
+ "README.md"
29
+ ],
27
30
  "scripts": {
28
31
  "typecheck": "tsc --noEmit",
29
32
  "build": "tsup"
30
33
  },
31
- "keywords": ["adviverse", "ads", "react", "nextjs", "adslot"],
34
+ "keywords": [
35
+ "adviverse",
36
+ "ads",
37
+ "react",
38
+ "nextjs",
39
+ "adslot"
40
+ ],
32
41
  "peerDependencies": {
33
42
  "react": ">=17"
34
43
  },