@amplifyup/sdk 0.1.74 → 0.1.76

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/dist/react.mjs CHANGED
@@ -11,7 +11,121 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
11
11
  throw Error('Dynamic require of "' + x + '" is not supported');
12
12
  });
13
13
 
14
+ // src/storage.ts
15
+ var INSTANCE_ID_KEY = "amplifyup_instance_id";
16
+ var USER_ID_KEY = "amplifyup_user_id";
17
+ var SESSION_ID_KEY = "amplifyup_session_id";
18
+ var SESSION_ACTIVITY_KEY = "amplifyup_session_activity";
19
+ var VISITOR_FIRST_SEEN_KEY = "amplifyup_visitor_first_seen";
20
+ var ANON_COOKIE_NAME = "amplifyup_anon_id";
21
+ var SESSION_COOKIE_NAME = "amplifyup_session_id";
22
+ var SESSION_IDLE_GAP_MS = 30 * 60 * 1e3;
23
+ function generateGuid() {
24
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
25
+ return crypto.randomUUID();
26
+ }
27
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
28
+ const r = Math.random() * 16 | 0;
29
+ const v = c === "x" ? r : r & 3 | 8;
30
+ return v.toString(16);
31
+ });
32
+ }
33
+ function readCookie(name) {
34
+ if (typeof document === "undefined") return null;
35
+ const parts = document.cookie.split(";");
36
+ for (const part of parts) {
37
+ const idx = part.indexOf("=");
38
+ if (idx === -1) continue;
39
+ if (part.slice(0, idx).trim() !== name) continue;
40
+ const value = part.slice(idx + 1).trim();
41
+ try {
42
+ return value ? decodeURIComponent(value) : null;
43
+ } catch {
44
+ return value || null;
45
+ }
46
+ }
47
+ return null;
48
+ }
49
+ function writeCookie(name, value, maxAgeSeconds = 31536e3) {
50
+ if (typeof document === "undefined") return;
51
+ document.cookie = `${name}=${encodeURIComponent(value)}; Path=/; Max-Age=${maxAgeSeconds}; SameSite=Lax`;
52
+ }
53
+ function getInstanceId() {
54
+ if (typeof window === "undefined") {
55
+ return "";
56
+ }
57
+ const fromCookie = readCookie(ANON_COOKIE_NAME);
58
+ const fromLs = localStorage.getItem(INSTANCE_ID_KEY);
59
+ const instanceId = fromLs || fromCookie || `browser_${generateGuid()}`;
60
+ if (fromLs !== instanceId) {
61
+ localStorage.setItem(INSTANCE_ID_KEY, instanceId);
62
+ }
63
+ if (fromCookie !== instanceId) {
64
+ writeCookie(ANON_COOKIE_NAME, instanceId);
65
+ }
66
+ return instanceId;
67
+ }
68
+ function getUserId() {
69
+ if (typeof window === "undefined") {
70
+ return null;
71
+ }
72
+ return localStorage.getItem(USER_ID_KEY);
73
+ }
74
+ function getSessionId() {
75
+ if (typeof window === "undefined") {
76
+ return "";
77
+ }
78
+ const now = Date.now();
79
+ const lastActivity = Number(localStorage.getItem(SESSION_ACTIVITY_KEY) || 0);
80
+ const fromCookie = readCookie(SESSION_COOKIE_NAME);
81
+ const fromLs = localStorage.getItem(SESSION_ID_KEY);
82
+ let sessionId = fromLs || fromCookie || "";
83
+ if (!sessionId || lastActivity > 0 && now - lastActivity >= SESSION_IDLE_GAP_MS) {
84
+ sessionId = generateGuid();
85
+ }
86
+ localStorage.setItem(SESSION_ID_KEY, sessionId);
87
+ localStorage.setItem(SESSION_ACTIVITY_KEY, String(now));
88
+ writeCookie(SESSION_COOKIE_NAME, sessionId, Math.floor(SESSION_IDLE_GAP_MS / 1e3));
89
+ return sessionId;
90
+ }
91
+ function getVisitorFirstSeenAt() {
92
+ if (typeof window === "undefined") {
93
+ return null;
94
+ }
95
+ try {
96
+ const existing = localStorage.getItem(VISITOR_FIRST_SEEN_KEY);
97
+ if (existing) return existing;
98
+ const firstSeenAt = (/* @__PURE__ */ new Date()).toISOString();
99
+ localStorage.setItem(VISITOR_FIRST_SEEN_KEY, firstSeenAt);
100
+ return firstSeenAt;
101
+ } catch {
102
+ return null;
103
+ }
104
+ }
105
+ function setUserId(userId) {
106
+ if (typeof window === "undefined") {
107
+ return;
108
+ }
109
+ localStorage.setItem(USER_ID_KEY, userId);
110
+ }
111
+ function clearIds() {
112
+ if (typeof window === "undefined") {
113
+ return;
114
+ }
115
+ localStorage.removeItem(INSTANCE_ID_KEY);
116
+ localStorage.removeItem(USER_ID_KEY);
117
+ localStorage.removeItem(SESSION_ID_KEY);
118
+ localStorage.removeItem(SESSION_ACTIVITY_KEY);
119
+ localStorage.removeItem(VISITOR_FIRST_SEEN_KEY);
120
+ document.cookie = `${ANON_COOKIE_NAME}=; Path=/; Max-Age=0; SameSite=Lax`;
121
+ document.cookie = `${SESSION_COOKIE_NAME}=; Path=/; Max-Age=0; SameSite=Lax`;
122
+ }
123
+
14
124
  // src/adapters/aws.ts
125
+ function visitorContext() {
126
+ const firstSeenAt = getVisitorFirstSeenAt();
127
+ return firstSeenAt ? { firstSeenAt } : void 0;
128
+ }
15
129
  var AWSAdapter = class {
16
130
  constructor() {
17
131
  this.initialized = false;
@@ -51,7 +165,9 @@ var AWSAdapter = class {
51
165
  console.warn("AmplifyUp SDK: AWS configuration missing");
52
166
  return;
53
167
  }
54
- const url = `${this.apiGatewayUrl}${endpoint}`;
168
+ const trackingId = eventData?.trackingId || this.config?.trackingId;
169
+ const query = trackingId ? `?tid=${encodeURIComponent(trackingId)}` : "";
170
+ const url = `${this.apiGatewayUrl}${endpoint}${query}`;
55
171
  try {
56
172
  const response = await fetch(url, {
57
173
  method: "POST",
@@ -113,7 +229,8 @@ var AWSAdapter = class {
113
229
  page: {
114
230
  path: properties.path || properties.url,
115
231
  referrer: properties.referrer
116
- }
232
+ },
233
+ visitor: visitorContext()
117
234
  },
118
235
  timestamp: properties.timestamp || (/* @__PURE__ */ new Date()).toISOString()
119
236
  };
@@ -151,7 +268,8 @@ var AWSAdapter = class {
151
268
  ...properties
152
269
  },
153
270
  context: {
154
- url: properties.url || (typeof window !== "undefined" ? window.location.href : "")
271
+ url: properties.url || (typeof window !== "undefined" ? window.location.href : ""),
272
+ visitor: visitorContext()
155
273
  },
156
274
  timestamp: properties.timestamp || (/* @__PURE__ */ new Date()).toISOString()
157
275
  };
@@ -207,100 +325,6 @@ var AWSAdapter = class {
207
325
  }
208
326
  };
209
327
 
210
- // src/storage.ts
211
- var INSTANCE_ID_KEY = "amplifyup_instance_id";
212
- var USER_ID_KEY = "amplifyup_user_id";
213
- var SESSION_ID_KEY = "amplifyup_session_id";
214
- var SESSION_ACTIVITY_KEY = "amplifyup_session_activity";
215
- var ANON_COOKIE_NAME = "amplifyup_anon_id";
216
- var SESSION_COOKIE_NAME = "amplifyup_session_id";
217
- var SESSION_IDLE_GAP_MS = 30 * 60 * 1e3;
218
- function generateGuid() {
219
- if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
220
- return crypto.randomUUID();
221
- }
222
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
223
- const r = Math.random() * 16 | 0;
224
- const v = c === "x" ? r : r & 3 | 8;
225
- return v.toString(16);
226
- });
227
- }
228
- function readCookie(name) {
229
- if (typeof document === "undefined") return null;
230
- const parts = document.cookie.split(";");
231
- for (const part of parts) {
232
- const idx = part.indexOf("=");
233
- if (idx === -1) continue;
234
- if (part.slice(0, idx).trim() !== name) continue;
235
- const value = part.slice(idx + 1).trim();
236
- try {
237
- return value ? decodeURIComponent(value) : null;
238
- } catch {
239
- return value || null;
240
- }
241
- }
242
- return null;
243
- }
244
- function writeCookie(name, value, maxAgeSeconds = 31536e3) {
245
- if (typeof document === "undefined") return;
246
- document.cookie = `${name}=${encodeURIComponent(value)}; Path=/; Max-Age=${maxAgeSeconds}; SameSite=Lax`;
247
- }
248
- function getInstanceId() {
249
- if (typeof window === "undefined") {
250
- return "";
251
- }
252
- const fromCookie = readCookie(ANON_COOKIE_NAME);
253
- const fromLs = localStorage.getItem(INSTANCE_ID_KEY);
254
- const instanceId = fromLs || fromCookie || `browser_${generateGuid()}`;
255
- if (fromLs !== instanceId) {
256
- localStorage.setItem(INSTANCE_ID_KEY, instanceId);
257
- }
258
- if (fromCookie !== instanceId) {
259
- writeCookie(ANON_COOKIE_NAME, instanceId);
260
- }
261
- return instanceId;
262
- }
263
- function getUserId() {
264
- if (typeof window === "undefined") {
265
- return null;
266
- }
267
- return localStorage.getItem(USER_ID_KEY);
268
- }
269
- function getSessionId() {
270
- if (typeof window === "undefined") {
271
- return "";
272
- }
273
- const now = Date.now();
274
- const lastActivity = Number(localStorage.getItem(SESSION_ACTIVITY_KEY) || 0);
275
- const fromCookie = readCookie(SESSION_COOKIE_NAME);
276
- const fromLs = localStorage.getItem(SESSION_ID_KEY);
277
- let sessionId = fromLs || fromCookie || "";
278
- if (!sessionId || lastActivity > 0 && now - lastActivity >= SESSION_IDLE_GAP_MS) {
279
- sessionId = generateGuid();
280
- }
281
- localStorage.setItem(SESSION_ID_KEY, sessionId);
282
- localStorage.setItem(SESSION_ACTIVITY_KEY, String(now));
283
- writeCookie(SESSION_COOKIE_NAME, sessionId, Math.floor(SESSION_IDLE_GAP_MS / 1e3));
284
- return sessionId;
285
- }
286
- function setUserId(userId) {
287
- if (typeof window === "undefined") {
288
- return;
289
- }
290
- localStorage.setItem(USER_ID_KEY, userId);
291
- }
292
- function clearIds() {
293
- if (typeof window === "undefined") {
294
- return;
295
- }
296
- localStorage.removeItem(INSTANCE_ID_KEY);
297
- localStorage.removeItem(USER_ID_KEY);
298
- localStorage.removeItem(SESSION_ID_KEY);
299
- localStorage.removeItem(SESSION_ACTIVITY_KEY);
300
- document.cookie = `${ANON_COOKIE_NAME}=; Path=/; Max-Age=0; SameSite=Lax`;
301
- document.cookie = `${SESSION_COOKIE_NAME}=; Path=/; Max-Age=0; SameSite=Lax`;
302
- }
303
-
304
328
  // src/targets.ts
305
329
  var AWS_DEV_API = "https://api-dev.amplifyup.ai";
306
330
  var AWS_PROD_API = "https://api.amplifyup.ai";
@@ -837,6 +861,7 @@ function applyPageContext(input, opts) {
837
861
  }
838
862
  const pageFields = {};
839
863
  for (const pf of opts.pageData?.pageFields || []) {
864
+ if (pf.dataType === "taxonomy") continue;
840
865
  if (pf.source === "static") {
841
866
  if (pf.value !== void 0) pageFields[pf.key] = pf.value;
842
867
  continue;
@@ -859,6 +884,7 @@ function applyPageContext(input, opts) {
859
884
  function staticPageFieldsFromSnapshot(pageData) {
860
885
  const pageFields = {};
861
886
  for (const pf of pageData?.pageFields || []) {
887
+ if (pf.dataType === "taxonomy") continue;
862
888
  if (pf.source === "static" && pf.value !== void 0) {
863
889
  pageFields[pf.key] = pf.value;
864
890
  }
@@ -876,6 +902,11 @@ function attachStaticPageContext(pageData, pageRoute) {
876
902
  pageRoute: pageRoute || ""
877
903
  };
878
904
  }
905
+ function withPageTaxonomies(properties, taxonomies) {
906
+ if (!taxonomies || Object.keys(taxonomies).length === 0) return properties;
907
+ const page = properties.page && typeof properties.page === "object" && !Array.isArray(properties.page) ? properties.page : { fields: {} };
908
+ return { ...properties, page: { ...page, taxonomies } };
909
+ }
879
910
  function mergeEventContext(properties, attached) {
880
911
  if (!attached) return properties;
881
912
  return {
@@ -945,6 +976,27 @@ function hydratePageResourceProps(props, fields) {
945
976
  return out;
946
977
  }
947
978
 
979
+ // src/edge/normalizeRoute.ts
980
+ function normalizeRoute(route) {
981
+ let path = String(route || "").trim();
982
+ if (!path) return "/";
983
+ try {
984
+ if (/^https?:\/\//i.test(path)) {
985
+ path = new URL(path).pathname;
986
+ }
987
+ } catch {
988
+ }
989
+ const q = path.indexOf("?");
990
+ if (q >= 0) path = path.slice(0, q);
991
+ const h = path.indexOf("#");
992
+ if (h >= 0) path = path.slice(0, h);
993
+ if (!path.startsWith("/")) path = `/${path}`;
994
+ if (path.length > 1 && path.endsWith("/")) {
995
+ path = path.replace(/\/+$/, "");
996
+ }
997
+ return path || "/";
998
+ }
999
+
948
1000
  // src/page-resource-runtime.ts
949
1001
  var pageResourceFields = null;
950
1002
  function setPageResourceFields(fields) {
@@ -1042,27 +1094,6 @@ function previewLayoutReady(opts) {
1042
1094
  return true;
1043
1095
  }
1044
1096
 
1045
- // src/edge/normalizeRoute.ts
1046
- function normalizeRoute(route) {
1047
- let path = String(route || "").trim();
1048
- if (!path) return "/";
1049
- try {
1050
- if (/^https?:\/\//i.test(path)) {
1051
- path = new URL(path).pathname;
1052
- }
1053
- } catch {
1054
- }
1055
- const q = path.indexOf("?");
1056
- if (q >= 0) path = path.slice(0, q);
1057
- const h = path.indexOf("#");
1058
- if (h >= 0) path = path.slice(0, h);
1059
- if (!path.startsWith("/")) path = `/${path}`;
1060
- if (path.length > 1 && path.endsWith("/")) {
1061
- path = path.replace(/\/+$/, "");
1062
- }
1063
- return path || "/";
1064
- }
1065
-
1066
1097
  // src/edge/variantKeys.ts
1067
1098
  function serializeVariantKeys(keys) {
1068
1099
  if (!keys) return "";
@@ -1184,7 +1215,8 @@ function mapResolvedToPageConfig(payload) {
1184
1215
  },
1185
1216
  ...payload.eventTracking && payload.eventTracking.length > 0 ? { eventTracking: payload.eventTracking } : {},
1186
1217
  ...payload.pageData ? { pageData: payload.pageData } : {},
1187
- ...payload.pageResources ? { pageResources: payload.pageResources } : {}
1218
+ ...payload.pageResources ? { pageResources: payload.pageResources } : {},
1219
+ ...payload.pageTaxonomies ? { pageTaxonomies: payload.pageTaxonomies } : {}
1188
1220
  };
1189
1221
  }
1190
1222
  function collectDegraded(payload) {
@@ -1416,6 +1448,7 @@ function searchSpec(pagination, field, term) {
1416
1448
  }
1417
1449
 
1418
1450
  // src/index.ts
1451
+ var PAGE_VIEW_HOLD_MS = 1500;
1419
1452
  var DWELL_ACTIVITY_IDLE_MS = 2 * 60 * 1e3;
1420
1453
  var DWELL_POLL_MS = 5e3;
1421
1454
  function readPreviewQueryOverrides() {
@@ -1489,6 +1522,12 @@ var AmplifyUpSDK = class {
1489
1522
  this.resolvedPageResource = null;
1490
1523
  this.resolvedPageRoute = "";
1491
1524
  this.resolvedRouteParams = {};
1525
+ /** Path whose delivery response is in flight; page_view for it is held. */
1526
+ this.pendingResolvePath = null;
1527
+ this.heldPageView = null;
1528
+ this.resolvedPageTaxonomies = null;
1529
+ /** Path the taxonomies above were resolved for. */
1530
+ this.resolvedTaxonomiesPath = null;
1492
1531
  this.historyHooksInstalled = false;
1493
1532
  this.pageEngagementState = {
1494
1533
  reached: /* @__PURE__ */ new Set(),
@@ -2019,8 +2058,10 @@ var AmplifyUpSDK = class {
2019
2058
  * Apply published pageData (from /v1/resolve) so field validation and
2020
2059
  * mapped page fields can run.
2021
2060
  */
2022
- applyResolvedPageData(pageData, pageRoute, routeParams, pageResources) {
2061
+ applyResolvedPageData(pageData, pageRoute, routeParams, pageResources, pageTaxonomies) {
2023
2062
  this.resolvedPageData = pageData || null;
2063
+ this.resolvedPageTaxonomies = pageTaxonomies || null;
2064
+ this.resolvedTaxonomiesPath = this.pendingResolvePath;
2024
2065
  if (pageRoute) this.resolvedPageRoute = pageRoute;
2025
2066
  if (routeParams) this.resolvedRouteParams = routeParams;
2026
2067
  const firstResourceName = pageData?.resources?.[0]?.name;
@@ -2054,6 +2095,28 @@ var AmplifyUpSDK = class {
2054
2095
  getAttachedPageContext() {
2055
2096
  return this.attachedPageContext;
2056
2097
  }
2098
+ /**
2099
+ * The page's delivery response for `path` is on its way. A page_view for the
2100
+ * same path waits for it (up to PAGE_VIEW_HOLD_MS) so it carries the page's
2101
+ * taxonomies.
2102
+ */
2103
+ beginPageResolve(path) {
2104
+ this.pendingResolvePath = normalizeRoute(path);
2105
+ this.resolvedPageTaxonomies = null;
2106
+ this.resolvedTaxonomiesPath = null;
2107
+ }
2108
+ endPageResolve(path) {
2109
+ if (this.pendingResolvePath !== normalizeRoute(path)) return;
2110
+ this.pendingResolvePath = null;
2111
+ this.flushHeldPageView();
2112
+ }
2113
+ flushHeldPageView() {
2114
+ const held = this.heldPageView;
2115
+ if (!held) return;
2116
+ clearTimeout(held.timer);
2117
+ this.heldPageView = null;
2118
+ this.sendPageView(held.url, held.properties);
2119
+ }
2057
2120
  /**
2058
2121
  * Track a page view
2059
2122
  */
@@ -2064,6 +2127,21 @@ var AmplifyUpSDK = class {
2064
2127
  if (!this.isInitialized()) {
2065
2128
  return;
2066
2129
  }
2130
+ this.lastTrackedPath = url;
2131
+ if (this.pendingResolvePath && this.pendingResolvePath === normalizeRoute(url)) {
2132
+ this.flushHeldPageView();
2133
+ this.heldPageView = {
2134
+ url,
2135
+ properties,
2136
+ timer: setTimeout(() => this.flushHeldPageView(), PAGE_VIEW_HOLD_MS)
2137
+ };
2138
+ return;
2139
+ }
2140
+ this.flushHeldPageView();
2141
+ this.sendPageView(url, properties);
2142
+ }
2143
+ sendPageView(url, properties) {
2144
+ const taxonomies = this.resolvedTaxonomiesPath && this.resolvedTaxonomiesPath === normalizeRoute(url) ? this.resolvedPageTaxonomies : null;
2067
2145
  const instanceId = getInstanceId();
2068
2146
  const sessionId = getSessionId();
2069
2147
  const pageProperties = {
@@ -2075,10 +2153,9 @@ var AmplifyUpSDK = class {
2075
2153
  sessionId,
2076
2154
  trackingId: this.config?.trackingId,
2077
2155
  // Timestamp is included in event payload
2078
- ...mergeEventContext(properties || {}, this.attachedPageContext)
2156
+ ...withPageTaxonomies(mergeEventContext(properties || {}, this.attachedPageContext), taxonomies)
2079
2157
  };
2080
2158
  this.adapter.page(pageProperties);
2081
- this.lastTrackedPath = url;
2082
2159
  }
2083
2160
  /**
2084
2161
  * Track an event
@@ -5525,6 +5602,8 @@ function AmplifyUpProvider({
5525
5602
  useEffect(() => {
5526
5603
  let cancelled = false;
5527
5604
  const sdk = getSDK();
5605
+ const heldRoute = isComposerPreview() || config.clientPersonalization !== false ? getActualRoute() : null;
5606
+ if (heldRoute) sdk.beginPageResolve(heldRoute);
5528
5607
  const run = async () => {
5529
5608
  try {
5530
5609
  await sdk.init({
@@ -5604,7 +5683,8 @@ function AmplifyUpProvider({
5604
5683
  result.pageConfig.pageData || null,
5605
5684
  result.pageConfig.route,
5606
5685
  extractRouteParams(result.pageConfig.route, actualRoute),
5607
- result.pageConfig.pageResources || null
5686
+ result.pageConfig.pageResources || null,
5687
+ result.pageConfig.pageTaxonomies || null
5608
5688
  );
5609
5689
  }
5610
5690
  setInitialized(true);
@@ -5628,6 +5708,7 @@ function AmplifyUpProvider({
5628
5708
  setSource(null);
5629
5709
  setMeta(null);
5630
5710
  } finally {
5711
+ if (heldRoute) sdk.endPageResolve(heldRoute);
5631
5712
  if (!cancelled) setLoading(false);
5632
5713
  }
5633
5714
  };