@liiift-studio/sanity-visitor-insights 0.33.0 → 0.34.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/dist/server.js CHANGED
@@ -721,7 +721,9 @@ function dailyWindows(start, end) {
721
721
  const MAX_WINDOWS = 6;
722
722
  const first = Date.parse(`${start}T00:00:00Z`);
723
723
  const last = Date.parse(`${end}T00:00:00Z`);
724
- if (!Number.isFinite(first) || !Number.isFinite(last) || last < first) return [];
724
+ if (!Number.isFinite(first) || !Number.isFinite(last) || last < first) {
725
+ throw new RangeError(`Vercel series requested for an invalid range: ${start} to ${end}`);
726
+ }
725
727
  const days = Math.round((last - first) / 864e5) + 1;
726
728
  if (days > MAX_DAYS * MAX_WINDOWS) return [];
727
729
  const windows = [];
@@ -958,15 +960,11 @@ function money(value, minorUnits) {
958
960
  return minorUnits ? value / 100 : value;
959
961
  }
960
962
  function zonedDay(iso, timezone) {
963
+ if (typeof iso !== "string") return null;
961
964
  const parsed = new Date(iso);
962
- if (Number.isNaN(parsed.getTime())) return iso.slice(0, 10);
965
+ if (Number.isNaN(parsed.getTime())) return null;
963
966
  try {
964
- return new Intl.DateTimeFormat("en-CA", {
965
- timeZone: timezone,
966
- year: "numeric",
967
- month: "2-digit",
968
- day: "2-digit"
969
- }).format(parsed);
967
+ return formatInTimeZone(parsed, timezone);
970
968
  } catch {
971
969
  return parsed.toISOString().slice(0, 10);
972
970
  }
@@ -989,6 +987,12 @@ async function countOrders(client, options) {
989
987
  continue;
990
988
  }
991
989
  const date = zonedDay(order._createdAt, options.timezone);
990
+ if (date === null) {
991
+ total += 1;
992
+ const untimed = money(order.orderTotal, options.totalInMinorUnits);
993
+ if (untimed !== null) revenue = (revenue ?? 0) + untimed;
994
+ continue;
995
+ }
992
996
  byDate[date] = (byDate[date] ?? 0) + 1;
993
997
  total += 1;
994
998
  const value = money(order.orderTotal, options.totalInMinorUnits);
@@ -1130,7 +1134,7 @@ function samplingInterval(estimate) {
1130
1134
  if (!Number.isFinite(n) || n <= 0) return { low: estimate.rate, high: estimate.rate };
1131
1135
  const p = Math.min(1, Math.max(0, estimate.rate));
1132
1136
  const error = 2 * Math.sqrt(Math.max(p * (1 - p), 0.02) / n);
1133
- return { low: Math.max(0, p - error), high: Math.min(1, p + error) };
1137
+ return { low: Math.max(0, estimate.rate - error), high: estimate.rate + error };
1134
1138
  }
1135
1139
  var TRUST = ["orders", "email", "pageviews"];
1136
1140
  function captureModel(candidates) {
@@ -1382,14 +1386,21 @@ async function measurementHealth(input) {
1382
1386
  const vercelDates = Object.keys(vercelByDate);
1383
1387
  const vercelIsDaily = vercelDates.length > 0 && vercelIncompleteWindows === 0 && vercelDates.length > daysInRange(range) * 0.7;
1384
1388
  const unsettled = new Set(provisionalDates(range, input.now));
1385
- const settledGa4 = [...ga4ByDate.entries()].filter(([date]) => !unsettled.has(date));
1386
- const settledVercel = vercelIsDaily ? Object.entries(vercelByDate).filter(([date]) => !unsettled.has(date)) : [];
1389
+ const comparable = vercelIsDaily ? [...ga4ByDate.keys()].filter((date) => !unsettled.has(date) && typeof vercelByDate[date] === "number") : [];
1387
1390
  const settledShortfall = (() => {
1388
- if (settledGa4.length === 0 || settledVercel.length === 0) return null;
1389
- const ga4Total = settledGa4.reduce((sum, [, value]) => sum + value, 0);
1390
- const vercelTotal = settledVercel.reduce((sum, [, value]) => sum + (value ?? 0), 0);
1391
+ const MIN_COMPARABLE_DAYS = 3;
1392
+ if (comparable.length < MIN_COMPARABLE_DAYS) return null;
1393
+ let ga4Total = 0;
1394
+ let vercelTotal = 0;
1395
+ for (const date of comparable) {
1396
+ ga4Total += ga4ByDate.get(date) ?? 0;
1397
+ vercelTotal += vercelByDate[date] ?? 0;
1398
+ }
1391
1399
  return vercelTotal > 0 ? (vercelTotal - ga4Total) / vercelTotal : null;
1392
1400
  })();
1401
+ if (settledShortfall === null && vercelIsDaily && unsettled.size >= daysInRange(range)) {
1402
+ input.notices?.push("Every day in this range is still being processed by Google Analytics, so the comparison against Vercel reads far worse than it is. Choose a range that ends before yesterday.");
1403
+ }
1393
1404
  const shortfallRatio = settledShortfall !== null ? settledShortfall : ga4Pageviews.status !== "unavailable" && vercelPageviews.status !== "unavailable" && vercelPageviews.value > 0 ? (vercelPageviews.value - ga4Pageviews.value) / vercelPageviews.value : null;
1394
1405
  const seriesDates = vercelIsDaily ? Array.from(/* @__PURE__ */ new Set([...ga4ByDate.keys(), ...vercelDates])) : Array.from(ga4ByDate.keys());
1395
1406
  const daily = seriesDates.sort().map((date) => ({