@nosto/nosto-react 2.3.0 → 2.5.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 +2 -2
- package/dist/index.d.ts +5 -5
- package/dist/index.es.js +214 -226
- package/dist/index.umd.js +1 -1
- package/package.json +11 -8
- package/src/components/NostoProvider.tsx +2 -2
- package/src/hooks/useLoadClientScript.ts +5 -48
- package/src/hooks/useRenderCampaigns.tsx +8 -3
package/README.md
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Cart } from '@nosto/nosto-js/client';
|
|
2
2
|
import { Context } from 'react';
|
|
3
3
|
import { PushedCustomer as Customer } from '@nosto/nosto-js/client';
|
|
4
|
-
import { JSX
|
|
4
|
+
import { JSX } from 'react/jsx-runtime';
|
|
5
5
|
import { WebsiteOrder as Order } from '@nosto/nosto-js/client';
|
|
6
6
|
import { Product } from '@nosto/nosto-js/client';
|
|
7
7
|
import { PushedProduct } from '@nosto/nosto-js/client';
|
|
@@ -223,7 +223,7 @@ export declare type NostoOtherProps = {
|
|
|
223
223
|
*
|
|
224
224
|
* @group Components
|
|
225
225
|
*/
|
|
226
|
-
export declare function NostoPlacement({ id, pageType }: NostoPlacementProps):
|
|
226
|
+
export declare function NostoPlacement({ id, pageType }: NostoPlacementProps): JSX.Element;
|
|
227
227
|
|
|
228
228
|
/**
|
|
229
229
|
* @group Components
|
|
@@ -290,7 +290,7 @@ export declare type NostoProductProps = {
|
|
|
290
290
|
*
|
|
291
291
|
* @group Components
|
|
292
292
|
*/
|
|
293
|
-
export declare function NostoProvider(props: NostoProviderProps):
|
|
293
|
+
export declare function NostoProvider(props: NostoProviderProps): JSX.Element;
|
|
294
294
|
|
|
295
295
|
/**
|
|
296
296
|
* @group Components
|
|
@@ -324,8 +324,8 @@ export declare interface NostoProviderProps {
|
|
|
324
324
|
* Enables Shopify markets with language and market id
|
|
325
325
|
*/
|
|
326
326
|
shopifyMarkets?: {
|
|
327
|
-
language
|
|
328
|
-
marketId
|
|
327
|
+
language: string;
|
|
328
|
+
marketId: string | number;
|
|
329
329
|
};
|
|
330
330
|
/**
|
|
331
331
|
* Load nosto script (should be false if loading the script outside of nosto-react)
|
package/dist/index.es.js
CHANGED
|
@@ -1,351 +1,339 @@
|
|
|
1
|
-
import { createContext as
|
|
2
|
-
import { jsx as
|
|
3
|
-
import
|
|
4
|
-
const
|
|
1
|
+
import { createContext as k, useContext as x, useEffect as S, useRef as h, useMemo as I, cloneElement as _, useState as T, isValidElement as D } from "react";
|
|
2
|
+
import { jsx as v } from "react/jsx-runtime";
|
|
3
|
+
import { createRoot as M } from "react-dom/client";
|
|
4
|
+
const O = k({
|
|
5
5
|
account: "",
|
|
6
6
|
currentVariation: "",
|
|
7
7
|
responseMode: "HTML",
|
|
8
8
|
clientScriptLoaded: !1
|
|
9
9
|
});
|
|
10
|
-
function
|
|
11
|
-
return
|
|
10
|
+
function P() {
|
|
11
|
+
return x(O);
|
|
12
12
|
}
|
|
13
|
-
const
|
|
14
|
-
function
|
|
15
|
-
if (!
|
|
13
|
+
const N = (e) => String(e) === "[object Object]";
|
|
14
|
+
function L(e) {
|
|
15
|
+
if (!N(e)) return !1;
|
|
16
16
|
const t = e.constructor;
|
|
17
17
|
if (t === void 0) return !0;
|
|
18
18
|
const n = t.prototype;
|
|
19
|
-
return !(!
|
|
19
|
+
return !(!N(n) || !n.hasOwnProperty("isPrototypeOf"));
|
|
20
20
|
}
|
|
21
|
-
function
|
|
21
|
+
function y(e, t) {
|
|
22
22
|
if (e === t)
|
|
23
23
|
return !0;
|
|
24
24
|
if (e instanceof Date && t instanceof Date)
|
|
25
25
|
return e.getTime() === t.getTime();
|
|
26
26
|
if (e instanceof Array && t instanceof Array)
|
|
27
|
-
return e.length !== t.length ? !1 : e.every((n,
|
|
28
|
-
if (
|
|
27
|
+
return e.length !== t.length ? !1 : e.every((n, o) => y(n, t[o]));
|
|
28
|
+
if (L(e) && L(t)) {
|
|
29
29
|
const n = Object.entries(e);
|
|
30
|
-
return n.length !== Object.keys(t).length ? !1 : n.every(([
|
|
30
|
+
return n.length !== Object.keys(t).length ? !1 : n.every(([o, r]) => y(r, t[o]));
|
|
31
31
|
}
|
|
32
32
|
return !1;
|
|
33
33
|
}
|
|
34
|
-
function
|
|
35
|
-
return
|
|
34
|
+
function g(e, t) {
|
|
35
|
+
return S(e, V(t));
|
|
36
36
|
}
|
|
37
|
-
function
|
|
38
|
-
const t =
|
|
39
|
-
return
|
|
37
|
+
function V(e) {
|
|
38
|
+
const t = h(e), n = h(0);
|
|
39
|
+
return y(e, t.current) || (t.current = e, n.current += 1), I(() => t.current, [n.current]);
|
|
40
40
|
}
|
|
41
|
-
function
|
|
41
|
+
function j() {
|
|
42
42
|
window.nostojs = window.nostojs ?? function(e) {
|
|
43
43
|
(window.nostojs.q = window.nostojs.q ?? []).push(e);
|
|
44
44
|
};
|
|
45
45
|
}
|
|
46
|
-
function
|
|
46
|
+
function H() {
|
|
47
47
|
return typeof window.nosto < "u";
|
|
48
48
|
}
|
|
49
|
-
const
|
|
49
|
+
const q = {
|
|
50
50
|
production: "https://connect.nosto.com/",
|
|
51
51
|
staging: "https://connect.staging.nosto.com/",
|
|
52
52
|
local: "https://connect.nosto.com/"
|
|
53
53
|
};
|
|
54
|
-
function
|
|
55
|
-
return
|
|
56
|
-
}
|
|
57
|
-
function
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const
|
|
64
|
-
|
|
54
|
+
function R(e) {
|
|
55
|
+
return q[e ?? "production"];
|
|
56
|
+
}
|
|
57
|
+
function F({ merchantId: e, env: t, options: n, shopifyInternational: o, scriptLoader: r }) {
|
|
58
|
+
var c, a;
|
|
59
|
+
const s = document.querySelector("script[nosto-language], script[nosto-market-id]"), i = String((o == null ? void 0 : o.marketId) || ""), m = (o == null ? void 0 : o.language) || "", C = (s == null ? void 0 : s.getAttribute("nosto-language")) !== m || (s == null ? void 0 : s.getAttribute("nosto-market-id")) !== i;
|
|
60
|
+
if (!s || C) {
|
|
61
|
+
const l = document.querySelector("#nosto-sandbox");
|
|
62
|
+
(c = s == null ? void 0 : s.parentNode) == null || c.removeChild(s), (a = l == null ? void 0 : l.parentNode) == null || a.removeChild(l);
|
|
63
|
+
const f = new URL("/script/shopify/market/nosto.js", R(t));
|
|
64
|
+
f.searchParams.append("merchant", e), f.searchParams.append("market", i), f.searchParams.append("locale", m.toLowerCase());
|
|
65
|
+
const A = {
|
|
66
|
+
...n == null ? void 0 : n.attributes,
|
|
67
|
+
"nosto-language": m,
|
|
68
|
+
"nosto-market-id": i
|
|
69
|
+
};
|
|
70
|
+
return (r ?? E)(f.toString(), { ...n, attributes: A });
|
|
71
|
+
}
|
|
72
|
+
return Promise.resolve();
|
|
73
|
+
}
|
|
74
|
+
function z(e) {
|
|
75
|
+
if (e.shopifyInternational)
|
|
76
|
+
return F(e);
|
|
77
|
+
const { merchantId: t, env: n, options: o, scriptLoader: r } = e, c = r ?? E, a = new URL(`/include/${t}`, R(n));
|
|
78
|
+
return c(a.toString(), o);
|
|
79
|
+
}
|
|
80
|
+
function E(e, t) {
|
|
81
|
+
return new Promise((n, o) => {
|
|
82
|
+
const r = document.createElement("script");
|
|
83
|
+
r.src = e, r.async = !0, r.type = "text/javascript", r.onload = () => n(), r.onerror = () => o(), Object.entries((t == null ? void 0 : t.attributes) ?? {}).forEach(([c, a]) => r.setAttribute(c, a)), (t == null ? void 0 : t.position) === "head" ? document.head.appendChild(r) : document.body.appendChild(r);
|
|
65
84
|
});
|
|
66
85
|
}
|
|
67
86
|
async function w(e) {
|
|
68
87
|
return window.nostojs(e);
|
|
69
88
|
}
|
|
70
|
-
|
|
71
|
-
function
|
|
72
|
-
const { clientScriptLoaded:
|
|
73
|
-
(n != null && n.deep ?
|
|
74
|
-
|
|
75
|
-
}, [
|
|
76
|
-
}
|
|
77
|
-
var O, y = z;
|
|
78
|
-
if (process.env.NODE_ENV === "production")
|
|
79
|
-
O = y.createRoot, y.hydrateRoot;
|
|
80
|
-
else {
|
|
81
|
-
var I = y.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
|
|
82
|
-
O = function(e, t) {
|
|
83
|
-
I.usingClientEntryPoint = !0;
|
|
84
|
-
try {
|
|
85
|
-
return y.createRoot(e, t);
|
|
86
|
-
} finally {
|
|
87
|
-
I.usingClientEntryPoint = !1;
|
|
88
|
-
}
|
|
89
|
-
};
|
|
89
|
+
typeof window < "u" && j();
|
|
90
|
+
function u(e, t, n) {
|
|
91
|
+
const { clientScriptLoaded: o } = P();
|
|
92
|
+
(n != null && n.deep ? g : S)(() => {
|
|
93
|
+
o && w(e);
|
|
94
|
+
}, [o, ...t ?? []]);
|
|
90
95
|
}
|
|
91
|
-
function
|
|
92
|
-
return
|
|
96
|
+
function U(e) {
|
|
97
|
+
return _(e.recommendationComponent, {
|
|
93
98
|
// eslint-disable-next-line react/prop-types
|
|
94
99
|
nostoRecommendation: e.nostoRecommendation
|
|
95
100
|
});
|
|
96
101
|
}
|
|
97
|
-
function
|
|
102
|
+
function b(e) {
|
|
103
|
+
w((t) => t.placements.injectCampaigns(e));
|
|
104
|
+
}
|
|
105
|
+
function $(e) {
|
|
98
106
|
if (!window.nostojs)
|
|
99
107
|
throw new Error("Nosto has not yet been initialized");
|
|
100
|
-
|
|
101
|
-
t.placements.injectCampaigns(e.recommendations);
|
|
102
|
-
});
|
|
108
|
+
b(e.recommendations);
|
|
103
109
|
}
|
|
104
|
-
function
|
|
105
|
-
const { responseMode: e, recommendationComponent: t } =
|
|
110
|
+
function d() {
|
|
111
|
+
const { responseMode: e, recommendationComponent: t } = P(), n = h({});
|
|
106
112
|
if (e == "HTML")
|
|
107
|
-
return { renderCampaigns:
|
|
108
|
-
function r
|
|
109
|
-
var s;
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
113
|
+
return { renderCampaigns: $ };
|
|
114
|
+
function o(r) {
|
|
115
|
+
var a, s;
|
|
116
|
+
b(((a = r.campaigns) == null ? void 0 : a.content) ?? {});
|
|
117
|
+
const c = ((s = r.campaigns) == null ? void 0 : s.recommendations) ?? {};
|
|
118
|
+
for (const i in c) {
|
|
119
|
+
const m = c[i], C = "#" + i, l = document.querySelector(C);
|
|
120
|
+
l && (n.current[i] || (n.current[i] = M(l)), n.current[i].render(
|
|
121
|
+
/* @__PURE__ */ v(
|
|
122
|
+
U,
|
|
116
123
|
{
|
|
117
124
|
recommendationComponent: t,
|
|
118
|
-
nostoRecommendation:
|
|
125
|
+
nostoRecommendation: m
|
|
119
126
|
}
|
|
120
127
|
)
|
|
121
128
|
));
|
|
122
129
|
}
|
|
123
130
|
}
|
|
124
|
-
return { renderCampaigns:
|
|
131
|
+
return { renderCampaigns: o };
|
|
125
132
|
}
|
|
126
|
-
function
|
|
127
|
-
const { renderCampaigns: t } =
|
|
128
|
-
|
|
129
|
-
const
|
|
130
|
-
t(
|
|
133
|
+
function G(e) {
|
|
134
|
+
const { renderCampaigns: t } = d();
|
|
135
|
+
u(async (n) => {
|
|
136
|
+
const o = await n.defaultSession().viewNotFound().setPlacements((e == null ? void 0 : e.placements) || n.placements.getPlacements()).load();
|
|
137
|
+
t(o);
|
|
131
138
|
});
|
|
132
139
|
}
|
|
133
|
-
function
|
|
134
|
-
return
|
|
135
|
-
}
|
|
136
|
-
function
|
|
137
|
-
const { renderCampaigns: n } =
|
|
138
|
-
|
|
139
|
-
async (
|
|
140
|
-
const
|
|
141
|
-
n(
|
|
140
|
+
function ie(e) {
|
|
141
|
+
return G(e), null;
|
|
142
|
+
}
|
|
143
|
+
function J({ category: e, placements: t }) {
|
|
144
|
+
const { renderCampaigns: n } = d();
|
|
145
|
+
u(
|
|
146
|
+
async (o) => {
|
|
147
|
+
const r = await o.defaultSession().viewCategory(e).setPlacements(t || o.placements.getPlacements()).load();
|
|
148
|
+
n(r);
|
|
142
149
|
},
|
|
143
150
|
[e]
|
|
144
151
|
);
|
|
145
152
|
}
|
|
146
|
-
function
|
|
147
|
-
return
|
|
153
|
+
function ue(e) {
|
|
154
|
+
return J(e), null;
|
|
148
155
|
}
|
|
149
|
-
function
|
|
150
|
-
const { renderCampaigns: t } =
|
|
151
|
-
|
|
152
|
-
const
|
|
153
|
-
t(
|
|
156
|
+
function W(e) {
|
|
157
|
+
const { renderCampaigns: t } = d();
|
|
158
|
+
u(async (n) => {
|
|
159
|
+
const o = await n.defaultSession().viewCart().setPlacements((e == null ? void 0 : e.placements) || n.placements.getPlacements()).load();
|
|
160
|
+
t(o);
|
|
154
161
|
});
|
|
155
162
|
}
|
|
156
|
-
function
|
|
157
|
-
return
|
|
163
|
+
function de(e) {
|
|
164
|
+
return W(e), null;
|
|
158
165
|
}
|
|
159
|
-
function
|
|
160
|
-
const { renderCampaigns: t } =
|
|
161
|
-
|
|
162
|
-
const
|
|
163
|
-
t(
|
|
166
|
+
function Z(e) {
|
|
167
|
+
const { renderCampaigns: t } = d();
|
|
168
|
+
u(async (n) => {
|
|
169
|
+
const o = await n.defaultSession().viewFrontPage().setPlacements((e == null ? void 0 : e.placements) || n.placements.getPlacements()).load();
|
|
170
|
+
t(o);
|
|
164
171
|
});
|
|
165
172
|
}
|
|
166
|
-
function
|
|
167
|
-
return
|
|
173
|
+
function le(e) {
|
|
174
|
+
return Z(e), null;
|
|
168
175
|
}
|
|
169
176
|
function p(e) {
|
|
170
|
-
return !e || typeof e != "object" ||
|
|
171
|
-
const
|
|
172
|
-
return t[
|
|
177
|
+
return !e || typeof e != "object" || B(e) || K(e) ? e : Array.isArray(e) ? e.map(p) : Object.keys(e).reduce((t, n) => {
|
|
178
|
+
const o = n[0].toLowerCase() + n.slice(1).replace(/([A-Z]+)/g, (r, c) => "_" + c.toLowerCase());
|
|
179
|
+
return t[o] = p(e[n]), t;
|
|
173
180
|
}, {});
|
|
174
181
|
}
|
|
175
|
-
function
|
|
182
|
+
function B(e) {
|
|
176
183
|
return Object.prototype.toString.call(e) === "[object Date]";
|
|
177
184
|
}
|
|
178
|
-
function
|
|
185
|
+
function K(e) {
|
|
179
186
|
return Object.prototype.toString.call(e) === "[object RegExp]";
|
|
180
187
|
}
|
|
181
|
-
function
|
|
182
|
-
const { renderCampaigns: n } =
|
|
183
|
-
|
|
184
|
-
async (
|
|
185
|
-
const
|
|
186
|
-
n(
|
|
188
|
+
function Q({ order: e, placements: t }) {
|
|
189
|
+
const { renderCampaigns: n } = d();
|
|
190
|
+
u(
|
|
191
|
+
async (o) => {
|
|
192
|
+
const r = await o.defaultSession().addOrder(p(e)).setPlacements(t || o.placements.getPlacements()).load();
|
|
193
|
+
n(r);
|
|
187
194
|
},
|
|
188
195
|
[e],
|
|
189
196
|
{ deep: !0 }
|
|
190
197
|
);
|
|
191
198
|
}
|
|
192
|
-
function
|
|
193
|
-
return
|
|
199
|
+
function me(e) {
|
|
200
|
+
return Q(e), null;
|
|
194
201
|
}
|
|
195
|
-
function
|
|
196
|
-
const { renderCampaigns: t } =
|
|
197
|
-
|
|
198
|
-
const
|
|
199
|
-
t(
|
|
202
|
+
function X(e) {
|
|
203
|
+
const { renderCampaigns: t } = d();
|
|
204
|
+
u(async (n) => {
|
|
205
|
+
const o = await n.defaultSession().viewOther().setPlacements((e == null ? void 0 : e.placements) || n.placements.getPlacements()).load();
|
|
206
|
+
t(o);
|
|
200
207
|
});
|
|
201
208
|
}
|
|
202
|
-
function
|
|
203
|
-
return
|
|
209
|
+
function fe(e) {
|
|
210
|
+
return X(e), null;
|
|
204
211
|
}
|
|
205
|
-
function
|
|
206
|
-
return /* @__PURE__ */
|
|
212
|
+
function pe({ id: e, pageType: t }) {
|
|
213
|
+
return /* @__PURE__ */ v("div", { className: "nosto_element", id: e }, e + (t || ""));
|
|
207
214
|
}
|
|
208
|
-
function
|
|
209
|
-
const { renderCampaigns:
|
|
215
|
+
function Y({ product: e, tagging: t, placements: n, reference: o }) {
|
|
216
|
+
const { renderCampaigns: r } = d();
|
|
210
217
|
if (t && !t.product_id)
|
|
211
218
|
throw new Error("The product object must contain a product_id property");
|
|
212
219
|
const c = (t == null ? void 0 : t.product_id) ?? e;
|
|
213
|
-
|
|
214
|
-
async (
|
|
215
|
-
const
|
|
216
|
-
|
|
217
|
-
const
|
|
218
|
-
|
|
220
|
+
u(
|
|
221
|
+
async (a) => {
|
|
222
|
+
const s = a.defaultSession().viewProduct(t ?? e).setPlacements(n || a.placements.getPlacements());
|
|
223
|
+
o && s.setRef(c, o);
|
|
224
|
+
const i = await s.load();
|
|
225
|
+
r(i);
|
|
219
226
|
},
|
|
220
227
|
[c, t == null ? void 0 : t.selected_sku_id]
|
|
221
228
|
);
|
|
222
229
|
}
|
|
223
|
-
function
|
|
224
|
-
return
|
|
230
|
+
function we(e) {
|
|
231
|
+
return Y(e), null;
|
|
225
232
|
}
|
|
226
|
-
function
|
|
227
|
-
return new Promise((n,
|
|
228
|
-
const
|
|
229
|
-
|
|
233
|
+
function ee(e, t) {
|
|
234
|
+
return new Promise((n, o) => {
|
|
235
|
+
const r = document.createElement("script");
|
|
236
|
+
r.type = "text/javascript", r.src = e, r.async = !0, r.onload = () => n(), r.onerror = () => o(), Object.entries((t == null ? void 0 : t.attributes) ?? {}).forEach(([c, a]) => r.setAttribute(c, a)), (t == null ? void 0 : t.position) === "head" ? document.head.appendChild(r) : document.body.appendChild(r);
|
|
230
237
|
});
|
|
231
238
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
}
|
|
235
|
-
function ue(e) {
|
|
239
|
+
const te = { "nosto-client-script": "" };
|
|
240
|
+
function ne(e) {
|
|
236
241
|
const {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
account: r,
|
|
242
|
+
scriptLoader: t = ee,
|
|
243
|
+
account: n,
|
|
240
244
|
shopifyMarkets: o,
|
|
241
|
-
loadScript:
|
|
242
|
-
} = e, [
|
|
243
|
-
return
|
|
244
|
-
function
|
|
245
|
-
|
|
246
|
-
site: "localhost"
|
|
247
|
-
}), a(!0);
|
|
248
|
-
}
|
|
249
|
-
async function S(i, m = {}) {
|
|
250
|
-
const f = `//${t}${i}`, N = { "nosto-client-script": "", ...m };
|
|
251
|
-
await n(f, { attributes: N }), u();
|
|
245
|
+
loadScript: r = !0
|
|
246
|
+
} = e, [c, a] = T(!1);
|
|
247
|
+
return S(() => {
|
|
248
|
+
function s() {
|
|
249
|
+
a(!0);
|
|
252
250
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
const i = document.querySelector("[nosto-client-script]"), m = String((o == null ? void 0 : o.marketId) || ""), f = (o == null ? void 0 : o.language) || "", N = (i == null ? void 0 : i.getAttribute("nosto-language")) !== f || (i == null ? void 0 : i.getAttribute("nosto-market-id")) !== m;
|
|
256
|
-
if (!i || N) {
|
|
257
|
-
s && a(!1);
|
|
258
|
-
const h = document.querySelector("#nosto-sandbox");
|
|
259
|
-
(j = i == null ? void 0 : i.parentNode) == null || j.removeChild(i), (g = h == null ? void 0 : h.parentNode) == null || g.removeChild(h);
|
|
260
|
-
const k = `/script/shopify/market/nosto.js?merchant=${r}&market=${m}&locale=${f.toLowerCase()}`;
|
|
261
|
-
S(k, { "nosto-language": f, "nosto-market-id": m });
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
if (D(), !c) {
|
|
265
|
-
w(u);
|
|
251
|
+
if (j(), !r) {
|
|
252
|
+
w(s);
|
|
266
253
|
return;
|
|
267
254
|
}
|
|
268
|
-
async function
|
|
269
|
-
await
|
|
270
|
-
merchantId:
|
|
255
|
+
async function i() {
|
|
256
|
+
await z({
|
|
257
|
+
merchantId: n,
|
|
258
|
+
shopifyInternational: o,
|
|
271
259
|
options: {
|
|
272
|
-
attributes:
|
|
260
|
+
attributes: te
|
|
273
261
|
},
|
|
274
|
-
scriptLoader:
|
|
275
|
-
}),
|
|
262
|
+
scriptLoader: t
|
|
263
|
+
}), s();
|
|
276
264
|
}
|
|
277
|
-
!
|
|
278
|
-
}, [o == null ? void 0 : o.marketId, o == null ? void 0 : o.language]), { clientScriptLoaded:
|
|
265
|
+
(!H() || o) && i();
|
|
266
|
+
}, [o == null ? void 0 : o.marketId, o == null ? void 0 : o.language]), { clientScriptLoaded: c };
|
|
279
267
|
}
|
|
280
|
-
function
|
|
281
|
-
const { account: t, multiCurrency: n = !1, children:
|
|
282
|
-
if (
|
|
268
|
+
function Ce(e) {
|
|
269
|
+
const { account: t, multiCurrency: n = !1, children: o, recommendationComponent: r } = e, c = n ? e.currentVariation : "";
|
|
270
|
+
if (r && !D(r))
|
|
283
271
|
throw new Error(
|
|
284
272
|
"The recommendationComponent prop must be a valid React element. Please provide a valid React element."
|
|
285
273
|
);
|
|
286
|
-
const
|
|
287
|
-
return
|
|
288
|
-
|
|
289
|
-
}), /* @__PURE__ */
|
|
290
|
-
|
|
274
|
+
const a = r ? "JSON_ORIGINAL" : "HTML", { clientScriptLoaded: s } = ne(e);
|
|
275
|
+
return s && w((i) => {
|
|
276
|
+
i.defaultSession().setVariation(c).setResponseMode(a);
|
|
277
|
+
}), /* @__PURE__ */ v(
|
|
278
|
+
O.Provider,
|
|
291
279
|
{
|
|
292
280
|
value: {
|
|
293
281
|
account: t,
|
|
294
|
-
clientScriptLoaded:
|
|
282
|
+
clientScriptLoaded: s,
|
|
295
283
|
currentVariation: c,
|
|
296
|
-
responseMode:
|
|
297
|
-
recommendationComponent:
|
|
284
|
+
responseMode: a,
|
|
285
|
+
recommendationComponent: r
|
|
298
286
|
},
|
|
299
|
-
children:
|
|
287
|
+
children: o
|
|
300
288
|
}
|
|
301
289
|
);
|
|
302
290
|
}
|
|
303
|
-
function
|
|
304
|
-
const { renderCampaigns: n } =
|
|
305
|
-
|
|
306
|
-
async (
|
|
307
|
-
const
|
|
308
|
-
n(
|
|
291
|
+
function oe({ query: e, placements: t }) {
|
|
292
|
+
const { renderCampaigns: n } = d();
|
|
293
|
+
u(
|
|
294
|
+
async (o) => {
|
|
295
|
+
const r = await o.defaultSession().viewSearch(e).setPlacements(t || o.placements.getPlacements()).load();
|
|
296
|
+
n(r);
|
|
309
297
|
},
|
|
310
298
|
[e]
|
|
311
299
|
);
|
|
312
300
|
}
|
|
313
|
-
function
|
|
314
|
-
return
|
|
301
|
+
function he(e) {
|
|
302
|
+
return oe(e), null;
|
|
315
303
|
}
|
|
316
|
-
function
|
|
317
|
-
const { clientScriptLoaded: n } =
|
|
318
|
-
|
|
319
|
-
const
|
|
304
|
+
function re({ cart: e, customer: t } = {}) {
|
|
305
|
+
const { clientScriptLoaded: n } = P();
|
|
306
|
+
g(() => {
|
|
307
|
+
const o = e ? p(e) : void 0, r = t ? p(t) : void 0;
|
|
320
308
|
n && w((c) => {
|
|
321
|
-
c.defaultSession().setCart(
|
|
309
|
+
c.defaultSession().setCart(o).setCustomer(r).viewOther().load({ skipPageViews: !0 });
|
|
322
310
|
});
|
|
323
311
|
}, [n, e, t]);
|
|
324
312
|
}
|
|
325
|
-
function
|
|
326
|
-
return
|
|
313
|
+
function ye(e) {
|
|
314
|
+
return re(e), null;
|
|
327
315
|
}
|
|
328
316
|
export {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
317
|
+
ie as Nosto404,
|
|
318
|
+
ue as NostoCategory,
|
|
319
|
+
de as NostoCheckout,
|
|
320
|
+
O as NostoContext,
|
|
321
|
+
le as NostoHome,
|
|
322
|
+
me as NostoOrder,
|
|
323
|
+
fe as NostoOther,
|
|
324
|
+
pe as NostoPlacement,
|
|
325
|
+
we as NostoProduct,
|
|
326
|
+
Ce as NostoProvider,
|
|
327
|
+
he as NostoSearch,
|
|
328
|
+
ye as NostoSession,
|
|
329
|
+
G as useNosto404,
|
|
330
|
+
J as useNostoCategory,
|
|
331
|
+
W as useNostoCheckout,
|
|
332
|
+
P as useNostoContext,
|
|
333
|
+
Z as useNostoHome,
|
|
334
|
+
Q as useNostoOrder,
|
|
335
|
+
X as useNostoOther,
|
|
336
|
+
Y as useNostoProduct,
|
|
337
|
+
oe as useNostoSearch,
|
|
338
|
+
re as useNostoSession
|
|
351
339
|
};
|
package/dist/index.umd.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(r,
|
|
1
|
+
(function(r,u){typeof exports=="object"&&typeof module<"u"?u(exports,require("react"),require("react/jsx-runtime"),require("react-dom/client")):typeof define=="function"&&define.amd?define(["exports","react","react/jsx-runtime","react-dom/client"],u):(r=typeof globalThis<"u"?globalThis:r||self,u(r["@nosto/nosto-react"]={},r.React,r["react/jsx-runtime"],r.client))})(this,function(r,u,y,V){"use strict";const S=u.createContext({account:"",currentVariation:"",responseMode:"HTML",clientScriptLoaded:!1});function w(){return u.useContext(S)}const O=e=>String(e)==="[object Object]";function j(e){if(!O(e))return!1;const t=e.constructor;if(t===void 0)return!0;const n=t.prototype;return!(!O(n)||!n.hasOwnProperty("isPrototypeOf"))}function P(e,t){if(e===t)return!0;if(e instanceof Date&&t instanceof Date)return e.getTime()===t.getTime();if(e instanceof Array&&t instanceof Array)return e.length!==t.length?!1:e.every((n,o)=>P(n,t[o]));if(j(e)&&j(t)){const n=Object.entries(e);return n.length!==Object.keys(t).length?!1:n.every(([o,s])=>P(s,t[o]))}return!1}function L(e,t){return u.useEffect(e,F(t))}function F(e){const t=u.useRef(e),n=u.useRef(0);return P(e,t.current)||(t.current=e,n.current+=1),u.useMemo(()=>t.current,[n.current])}function g(){window.nostojs=window.nostojs??function(e){(window.nostojs.q=window.nostojs.q??[]).push(e)}}function z(){return typeof window.nosto<"u"}const U={production:"https://connect.nosto.com/",staging:"https://connect.staging.nosto.com/",local:"https://connect.nosto.com/"};function R(e){return U[e??"production"]}function $({merchantId:e,env:t,options:n,shopifyInternational:o,scriptLoader:s}){var c,a;const i=document.querySelector("script[nosto-language], script[nosto-market-id]"),d=String((o==null?void 0:o.marketId)||""),C=(o==null?void 0:o.language)||"",v=(i==null?void 0:i.getAttribute("nosto-language"))!==C||(i==null?void 0:i.getAttribute("nosto-market-id"))!==d;if(!i||v){const f=document.querySelector("#nosto-sandbox");(c=i==null?void 0:i.parentNode)==null||c.removeChild(i),(a=f==null?void 0:f.parentNode)==null||a.removeChild(f);const N=new URL("/script/shopify/market/nosto.js",R(t));N.searchParams.append("merchant",e),N.searchParams.append("market",d),N.searchParams.append("locale",C.toLowerCase());const ue={...n==null?void 0:n.attributes,"nosto-language":C,"nosto-market-id":d};return(s??E)(N.toString(),{...n,attributes:ue})}return Promise.resolve()}function G(e){if(e.shopifyInternational)return $(e);const{merchantId:t,env:n,options:o,scriptLoader:s}=e,c=s??E,a=new URL(`/include/${t}`,R(n));return c(a.toString(),o)}function E(e,t){return new Promise((n,o)=>{const s=document.createElement("script");s.src=e,s.async=!0,s.type="text/javascript",s.onload=()=>n(),s.onerror=()=>o(),Object.entries((t==null?void 0:t.attributes)??{}).forEach(([c,a])=>s.setAttribute(c,a)),(t==null?void 0:t.position)==="head"?document.head.appendChild(s):document.body.appendChild(s)})}async function p(e){return window.nostojs(e)}typeof window<"u"&&g();function l(e,t,n){const{clientScriptLoaded:o}=w();(n!=null&&n.deep?L:u.useEffect)(()=>{o&&p(e)},[o,...t??[]])}function J(e){return u.cloneElement(e.recommendationComponent,{nostoRecommendation:e.nostoRecommendation})}function b(e){p(t=>t.placements.injectCampaigns(e))}function W(e){if(!window.nostojs)throw new Error("Nosto has not yet been initialized");b(e.recommendations)}function m(){const{responseMode:e,recommendationComponent:t}=w(),n=u.useRef({});if(e=="HTML")return{renderCampaigns:W};function o(s){var a,i;b(((a=s.campaigns)==null?void 0:a.content)??{});const c=((i=s.campaigns)==null?void 0:i.recommendations)??{};for(const d in c){const C=c[d],v="#"+d,f=document.querySelector(v);f&&(n.current[d]||(n.current[d]=V.createRoot(f)),n.current[d].render(y.jsx(J,{recommendationComponent:t,nostoRecommendation:C})))}}return{renderCampaigns:o}}function k(e){const{renderCampaigns:t}=m();l(async n=>{const o=await n.defaultSession().viewNotFound().setPlacements((e==null?void 0:e.placements)||n.placements.getPlacements()).load();t(o)})}function Z(e){return k(e),null}function A({category:e,placements:t}){const{renderCampaigns:n}=m();l(async o=>{const s=await o.defaultSession().viewCategory(e).setPlacements(t||o.placements.getPlacements()).load();n(s)},[e])}function B(e){return A(e),null}function I(e){const{renderCampaigns:t}=m();l(async n=>{const o=await n.defaultSession().viewCart().setPlacements((e==null?void 0:e.placements)||n.placements.getPlacements()).load();t(o)})}function K(e){return I(e),null}function T(e){const{renderCampaigns:t}=m();l(async n=>{const o=await n.defaultSession().viewFrontPage().setPlacements((e==null?void 0:e.placements)||n.placements.getPlacements()).load();t(o)})}function Q(e){return T(e),null}function h(e){return!e||typeof e!="object"||X(e)||Y(e)?e:Array.isArray(e)?e.map(h):Object.keys(e).reduce((t,n)=>{const o=n[0].toLowerCase()+n.slice(1).replace(/([A-Z]+)/g,(s,c)=>"_"+c.toLowerCase());return t[o]=h(e[n]),t},{})}function X(e){return Object.prototype.toString.call(e)==="[object Date]"}function Y(e){return Object.prototype.toString.call(e)==="[object RegExp]"}function _({order:e,placements:t}){const{renderCampaigns:n}=m();l(async o=>{const s=await o.defaultSession().addOrder(h(e)).setPlacements(t||o.placements.getPlacements()).load();n(s)},[e],{deep:!0})}function x(e){return _(e),null}function q(e){const{renderCampaigns:t}=m();l(async n=>{const o=await n.defaultSession().viewOther().setPlacements((e==null?void 0:e.placements)||n.placements.getPlacements()).load();t(o)})}function ee(e){return q(e),null}function te({id:e,pageType:t}){return y.jsx("div",{className:"nosto_element",id:e},e+(t||""))}function H({product:e,tagging:t,placements:n,reference:o}){const{renderCampaigns:s}=m();if(t&&!t.product_id)throw new Error("The product object must contain a product_id property");const c=(t==null?void 0:t.product_id)??e;l(async a=>{const i=a.defaultSession().viewProduct(t??e).setPlacements(n||a.placements.getPlacements());o&&i.setRef(c,o);const d=await i.load();s(d)},[c,t==null?void 0:t.selected_sku_id])}function ne(e){return H(e),null}function oe(e,t){return new Promise((n,o)=>{const s=document.createElement("script");s.type="text/javascript",s.src=e,s.async=!0,s.onload=()=>n(),s.onerror=()=>o(),Object.entries((t==null?void 0:t.attributes)??{}).forEach(([c,a])=>s.setAttribute(c,a)),(t==null?void 0:t.position)==="head"?document.head.appendChild(s):document.body.appendChild(s)})}const se={"nosto-client-script":""};function re(e){const{scriptLoader:t=oe,account:n,shopifyMarkets:o,loadScript:s=!0}=e,[c,a]=u.useState(!1);return u.useEffect(()=>{function i(){a(!0)}if(g(),!s){p(i);return}async function d(){await G({merchantId:n,shopifyInternational:o,options:{attributes:se},scriptLoader:t}),i()}(!z()||o)&&d()},[o==null?void 0:o.marketId,o==null?void 0:o.language]),{clientScriptLoaded:c}}function ce(e){const{account:t,multiCurrency:n=!1,children:o,recommendationComponent:s}=e,c=n?e.currentVariation:"";if(s&&!u.isValidElement(s))throw new Error("The recommendationComponent prop must be a valid React element. Please provide a valid React element.");const a=s?"JSON_ORIGINAL":"HTML",{clientScriptLoaded:i}=re(e);return i&&p(d=>{d.defaultSession().setVariation(c).setResponseMode(a)}),y.jsx(S.Provider,{value:{account:t,clientScriptLoaded:i,currentVariation:c,responseMode:a,recommendationComponent:s},children:o})}function M({query:e,placements:t}){const{renderCampaigns:n}=m();l(async o=>{const s=await o.defaultSession().viewSearch(e).setPlacements(t||o.placements.getPlacements()).load();n(s)},[e])}function ie(e){return M(e),null}function D({cart:e,customer:t}={}){const{clientScriptLoaded:n}=w();L(()=>{const o=e?h(e):void 0,s=t?h(t):void 0;n&&p(c=>{c.defaultSession().setCart(o).setCustomer(s).viewOther().load({skipPageViews:!0})})},[n,e,t])}function ae(e){return D(e),null}r.Nosto404=Z,r.NostoCategory=B,r.NostoCheckout=K,r.NostoContext=S,r.NostoHome=Q,r.NostoOrder=x,r.NostoOther=ee,r.NostoPlacement=te,r.NostoProduct=ne,r.NostoProvider=ce,r.NostoSearch=ie,r.NostoSession=ae,r.useNosto404=k,r.useNostoCategory=A,r.useNostoCheckout=I,r.useNostoContext=w,r.useNostoHome=T,r.useNostoOrder=_,r.useNostoOther=q,r.useNostoProduct=H,r.useNostoSearch=M,r.useNostoSession=D,Object.defineProperty(r,Symbol.toStringTag,{value:"Module"})});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nosto/nosto-react",
|
|
3
3
|
"description": "Component library to simply implementing Nosto on React.",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.5.0",
|
|
5
5
|
"author": "Mridang Agarwalla, Dominik Gilg",
|
|
6
6
|
"license": "ISC",
|
|
7
7
|
"repository": {
|
|
@@ -30,30 +30,33 @@
|
|
|
30
30
|
"dist",
|
|
31
31
|
"src"
|
|
32
32
|
],
|
|
33
|
-
"
|
|
34
|
-
"react": "^18.3.1",
|
|
35
|
-
"react-dom": "^18.3.1"
|
|
36
|
-
"@nosto/nosto-js": "*"
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"react": "^18.3.1 || ^19.0.0",
|
|
35
|
+
"react-dom": "^18.3.1 || ^19.0.0"
|
|
37
36
|
},
|
|
38
37
|
"devDependencies": {
|
|
38
|
+
"@nosto/nosto-js": "^1.3.1",
|
|
39
39
|
"@testing-library/jest-dom": "^6.4.8",
|
|
40
40
|
"@testing-library/react": "^16.0.0",
|
|
41
41
|
"@testing-library/user-event": "^14.4.3",
|
|
42
|
-
"@types/react": "^
|
|
43
|
-
"@types/react-dom": "^
|
|
42
|
+
"@types/react": "^19.0.2",
|
|
43
|
+
"@types/react-dom": "^19.0.0",
|
|
44
44
|
"@types/user-event": "^4.1.1",
|
|
45
45
|
"@vitejs/plugin-react": "^4.3.1",
|
|
46
46
|
"eslint": "^9.13.0",
|
|
47
47
|
"eslint-plugin-promise": "^7.1.0",
|
|
48
48
|
"eslint-plugin-react": "^7.33.2",
|
|
49
49
|
"prettier": "^3.3.3",
|
|
50
|
+
"react": "^19.0.0",
|
|
51
|
+
"react-dom": "^19.0.0",
|
|
50
52
|
"react-router": "^7.0.1",
|
|
51
53
|
"react-router-dom": "^7.0.1",
|
|
52
54
|
"rimraf": "^6.0.1",
|
|
55
|
+
"rollup-plugin-visualizer": "^5.13.1",
|
|
53
56
|
"typedoc": "^0.27.2",
|
|
54
57
|
"typescript": "^5.6.3",
|
|
55
58
|
"typescript-eslint": "^8.13.0",
|
|
56
|
-
"vite": "^
|
|
59
|
+
"vite": "^6.0.3",
|
|
57
60
|
"vite-plugin-dts": "^4.2.2",
|
|
58
61
|
"vitest": "^2.0.5"
|
|
59
62
|
},
|
|
@@ -37,8 +37,8 @@ export interface NostoProviderProps {
|
|
|
37
37
|
* Enables Shopify markets with language and market id
|
|
38
38
|
*/
|
|
39
39
|
shopifyMarkets?: {
|
|
40
|
-
language
|
|
41
|
-
marketId
|
|
40
|
+
language: string
|
|
41
|
+
marketId: string | number
|
|
42
42
|
}
|
|
43
43
|
/**
|
|
44
44
|
* Load nosto script (should be false if loading the script outside of nosto-react)
|
|
@@ -2,13 +2,13 @@ import { useState, useEffect } from "react"
|
|
|
2
2
|
import type { NostoProviderProps } from "../components/NostoProvider"
|
|
3
3
|
import scriptLoaderFn from "./scriptLoader"
|
|
4
4
|
import { init, initNostoStub, isNostoLoaded, nostojs } from "@nosto/nosto-js"
|
|
5
|
-
import { reloadNosto } from "@nosto/nosto-js/testing"
|
|
6
5
|
|
|
7
6
|
type NostoScriptProps = Pick<NostoProviderProps, "account" | "host" | "shopifyMarkets" | "loadScript" | "scriptLoader">
|
|
8
7
|
|
|
8
|
+
const defaultAttributes = { "nosto-client-script": "" }
|
|
9
|
+
|
|
9
10
|
export function useLoadClientScript(props: NostoScriptProps) {
|
|
10
11
|
const {
|
|
11
|
-
host = "connect.nosto.com",
|
|
12
12
|
scriptLoader = scriptLoaderFn,
|
|
13
13
|
account,
|
|
14
14
|
shopifyMarkets,
|
|
@@ -18,48 +18,9 @@ export function useLoadClientScript(props: NostoScriptProps) {
|
|
|
18
18
|
|
|
19
19
|
useEffect(() => {
|
|
20
20
|
function scriptOnload() {
|
|
21
|
-
// Override for production scripts to work in unit tests
|
|
22
|
-
if ("nostoReactTest" in window) {
|
|
23
|
-
reloadNosto({
|
|
24
|
-
site: "localhost"
|
|
25
|
-
})
|
|
26
|
-
}
|
|
27
21
|
setClientScriptLoaded(true)
|
|
28
22
|
}
|
|
29
23
|
|
|
30
|
-
// Create and append script element
|
|
31
|
-
async function injectScriptElement(urlPartial: string, extraAttributes: Record<string, string> = {}) {
|
|
32
|
-
const scriptSrc = `//${host}${urlPartial}`
|
|
33
|
-
const attributes = { "nosto-client-script": "", ...extraAttributes }
|
|
34
|
-
await scriptLoader(scriptSrc, { attributes })
|
|
35
|
-
scriptOnload()
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function prepareShopifyMarketsScript() {
|
|
39
|
-
const existingScript = document.querySelector("[nosto-client-script]")
|
|
40
|
-
|
|
41
|
-
const marketId = String(shopifyMarkets?.marketId || "")
|
|
42
|
-
const language = shopifyMarkets?.language || ""
|
|
43
|
-
|
|
44
|
-
const attributeMismatch =
|
|
45
|
-
existingScript?.getAttribute("nosto-language") !== language ||
|
|
46
|
-
existingScript?.getAttribute("nosto-market-id") !== marketId
|
|
47
|
-
|
|
48
|
-
if (!existingScript || attributeMismatch) {
|
|
49
|
-
if (clientScriptLoaded) {
|
|
50
|
-
setClientScriptLoaded(false)
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const nostoSandbox = document.querySelector("#nosto-sandbox")
|
|
54
|
-
|
|
55
|
-
existingScript?.parentNode?.removeChild(existingScript)
|
|
56
|
-
nostoSandbox?.parentNode?.removeChild(nostoSandbox)
|
|
57
|
-
|
|
58
|
-
const urlPartial = `/script/shopify/market/nosto.js?merchant=${account}&market=${marketId}&locale=${language.toLowerCase()}`
|
|
59
|
-
injectScriptElement(urlPartial, { "nosto-language": language, "nosto-market-id": marketId })
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
24
|
initNostoStub()
|
|
64
25
|
|
|
65
26
|
if (!loadScript) {
|
|
@@ -70,8 +31,9 @@ export function useLoadClientScript(props: NostoScriptProps) {
|
|
|
70
31
|
async function initClientScript() {
|
|
71
32
|
await init({
|
|
72
33
|
merchantId: account,
|
|
34
|
+
shopifyInternational: shopifyMarkets,
|
|
73
35
|
options: {
|
|
74
|
-
attributes:
|
|
36
|
+
attributes: defaultAttributes
|
|
75
37
|
},
|
|
76
38
|
scriptLoader
|
|
77
39
|
})
|
|
@@ -79,14 +41,9 @@ export function useLoadClientScript(props: NostoScriptProps) {
|
|
|
79
41
|
}
|
|
80
42
|
|
|
81
43
|
// Load Nosto client script if not already loaded externally
|
|
82
|
-
if (!isNostoLoaded()
|
|
44
|
+
if (!isNostoLoaded() || shopifyMarkets) {
|
|
83
45
|
initClientScript()
|
|
84
46
|
}
|
|
85
|
-
|
|
86
|
-
// Load Shopify Markets scripts
|
|
87
|
-
if (shopifyMarkets) {
|
|
88
|
-
prepareShopifyMarketsScript()
|
|
89
|
-
}
|
|
90
47
|
}, [shopifyMarkets?.marketId, shopifyMarkets?.language])
|
|
91
48
|
|
|
92
49
|
return { clientScriptLoaded }
|
|
@@ -19,14 +19,16 @@ function RecommendationComponentWrapper(props: {
|
|
|
19
19
|
})
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
function injectPlacements(data: Record<string, unknown>) {
|
|
23
|
+
nostojs(api => api.placements.injectCampaigns(data as Parameters<API['placements']['injectCampaigns']>[0]))
|
|
24
|
+
}
|
|
25
|
+
|
|
22
26
|
function injectCampaigns(data: CampaignData) {
|
|
23
27
|
// @ts-expect-error not defined
|
|
24
28
|
if (!window.nostojs) {
|
|
25
29
|
throw new Error("Nosto has not yet been initialized")
|
|
26
30
|
}
|
|
27
|
-
|
|
28
|
-
api.placements.injectCampaigns(data.recommendations as Parameters<API['placements']['injectCampaigns']>[0])
|
|
29
|
-
})
|
|
31
|
+
injectPlacements(data.recommendations)
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
export function useRenderCampaigns() {
|
|
@@ -38,6 +40,9 @@ export function useRenderCampaigns() {
|
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
function renderCampaigns(data: CampaignData) {
|
|
43
|
+
// inject Onsite content campaigns directly
|
|
44
|
+
injectPlacements(data.campaigns?.content ?? {})
|
|
45
|
+
|
|
41
46
|
// render recommendation component into placements:
|
|
42
47
|
const recommendations = data.campaigns?.recommendations ?? {}
|
|
43
48
|
for (const key in recommendations) {
|