@liiift-studio/sanity-visitor-insights 0.34.0 → 0.35.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/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as sanity from 'sanity';
2
2
  import React from 'react';
3
- import { R as ReportEnvelope, a as ReportName, b as RangeKey, M as MetricValue, A as AcquisitionData, c as MeasurementHealthData, D as DiagnosticReport, J as JourneyData, T as TypefaceInterestData } from './ranges-CebNbojW.mjs';
4
- export { C as CaptureBasis, d as CaptureEstimate, e as CaptureModel, f as CheckStatus, g as Coverage, h as CrossSourceDay, i as DailyPoint, j as DateRange, k as DiagnosticCheck, E as EmailCampaign, l as EventCutover, m as JourneyOutcome, n as JourneyStep, L as LandingPage, o as LicenceTierRow, P as PREEXISTING, p as REPORT_NAMES, q as ReportError, S as SiteAnalyticsConfig, r as SourceName, s as SourceRow, t as SourceStatus, u as TimelineEvent, v as TypefaceInterestRow, U as UnavailableReason, w as coverageForRange, x as estimated, y as isReportName, z as ok, B as partial, F as previousRange, G as resolveRange, H as unavailable, I as validateSiteConfig, K as valueOrNull } from './ranges-CebNbojW.mjs';
3
+ import { R as ReportEnvelope, a as ReportName, b as RangeKey, M as MetricValue, A as AcquisitionData, c as MeasurementHealthData, D as DiagnosticReport, J as JourneyData, T as TypefaceInterestData } from './ranges-Cc3Bv5-l.mjs';
4
+ export { C as CaptureBasis, d as CaptureEstimate, e as CaptureModel, f as CheckStatus, g as Coverage, h as CrossSourceDay, i as DailyPoint, j as DateRange, k as DiagnosticCheck, E as EmailCampaign, l as EventCutover, m as JourneyOutcome, n as JourneyStep, L as LandingPage, o as LicenceTierRow, P as PREEXISTING, p as REPORT_NAMES, q as ReportError, S as SiteAnalyticsConfig, r as SourceName, s as SourceRow, t as SourceStatus, u as TimelineEvent, v as TypefaceInterestRow, U as UnavailableReason, w as coverageForRange, x as estimated, y as isReportName, z as ok, B as partial, F as previousRange, G as resolveRange, H as unavailable, I as validateSiteConfig, K as valueOrNull } from './ranges-Cc3Bv5-l.mjs';
5
5
 
6
6
  /**
7
7
  * Data hook for the Studio panels.
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as sanity from 'sanity';
2
2
  import React from 'react';
3
- import { R as ReportEnvelope, a as ReportName, b as RangeKey, M as MetricValue, A as AcquisitionData, c as MeasurementHealthData, D as DiagnosticReport, J as JourneyData, T as TypefaceInterestData } from './ranges-CebNbojW.js';
4
- export { C as CaptureBasis, d as CaptureEstimate, e as CaptureModel, f as CheckStatus, g as Coverage, h as CrossSourceDay, i as DailyPoint, j as DateRange, k as DiagnosticCheck, E as EmailCampaign, l as EventCutover, m as JourneyOutcome, n as JourneyStep, L as LandingPage, o as LicenceTierRow, P as PREEXISTING, p as REPORT_NAMES, q as ReportError, S as SiteAnalyticsConfig, r as SourceName, s as SourceRow, t as SourceStatus, u as TimelineEvent, v as TypefaceInterestRow, U as UnavailableReason, w as coverageForRange, x as estimated, y as isReportName, z as ok, B as partial, F as previousRange, G as resolveRange, H as unavailable, I as validateSiteConfig, K as valueOrNull } from './ranges-CebNbojW.js';
3
+ import { R as ReportEnvelope, a as ReportName, b as RangeKey, M as MetricValue, A as AcquisitionData, c as MeasurementHealthData, D as DiagnosticReport, J as JourneyData, T as TypefaceInterestData } from './ranges-Cc3Bv5-l.js';
4
+ export { C as CaptureBasis, d as CaptureEstimate, e as CaptureModel, f as CheckStatus, g as Coverage, h as CrossSourceDay, i as DailyPoint, j as DateRange, k as DiagnosticCheck, E as EmailCampaign, l as EventCutover, m as JourneyOutcome, n as JourneyStep, L as LandingPage, o as LicenceTierRow, P as PREEXISTING, p as REPORT_NAMES, q as ReportError, S as SiteAnalyticsConfig, r as SourceName, s as SourceRow, t as SourceStatus, u as TimelineEvent, v as TypefaceInterestRow, U as UnavailableReason, w as coverageForRange, x as estimated, y as isReportName, z as ok, B as partial, F as previousRange, G as resolveRange, H as unavailable, I as validateSiteConfig, K as valueOrNull } from './ranges-Cc3Bv5-l.js';
5
5
 
6
6
  /**
7
7
  * Data hook for the Studio panels.
package/dist/index.js CHANGED
@@ -263,7 +263,12 @@ var REASON_TEXT = {
263
263
  suppressed: "Withheld by GA4 for privacy",
264
264
  outage: "Not recorded during part of this period",
265
265
  source_error: "Source did not respond",
266
- not_applicable: "Does not apply to this site"
266
+ not_applicable: "Does not apply to this site",
267
+ // Its own reason, because it was borrowing not_applicable — so a figure that is temporarily
268
+ // missing rendered "Does not apply to this site. This site's API route predates this figure."
269
+ // Two flatly contradictory sentences, and a hurried reader takes the first: this foundry has no
270
+ // revenue. That is the mistake the top of this file exists to forbid, one layer up.
271
+ route_outdated: "Not available from this site yet"
267
272
  };
268
273
  var LOCALE = "en-GB";
269
274
  function formatCount(value) {
@@ -1131,6 +1136,7 @@ function CrossSourceTimeline({ series, markers = [], currency, onBrush }) {
1131
1136
  });
1132
1137
  const summary = `${dates.length} days from ${tickLabel(/* @__PURE__ */ new Date(`${dates[0]}T00:00:00Z`))} to ${tickLabel(/* @__PURE__ */ new Date(`${dates[dates.length - 1]}T00:00:00Z`))}. ` + series.map(shapeOf).join(". ") + ". " + missed.join(" ") + (markers.length > 0 ? ` ${markers.length} campaign send${markers.length === 1 ? "" : "s"} marked.` : "");
1133
1138
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_sanity_ui_compat2.Stack, { space: 3, children: [
1139
+ missed.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_sanity_ui_compat2.Card, { padding: 3, radius: 2, tone: "caution", border: true, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_sanity_ui_compat2.Stack, { space: 2, children: missed.map((sentence) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_sanity_ui_compat2.Text, { size: 1, children: sentence }, sentence)) }) }),
1134
1140
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: frameStyle, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1135
1141
  "svg",
1136
1142
  {
@@ -1422,12 +1428,6 @@ function CrossSourceTimeline({ series, markers = [], currency, onBrush }) {
1422
1428
  row.source,
1423
1429
  ")"
1424
1430
  ] }, row.key)),
1425
- missed.map((sentence) => (
1426
- // The region's argument, stated as a number. It was drawn to scale and described
1427
- // in the abstract, so the two facts it exists to convey — how much was missed and
1428
- // when it was worst — were available only by looking hard at a pale fill.
1429
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_sanity_ui_compat2.Text, { size: 0, muted: true, children: sentence }, sentence)
1430
- )),
1431
1431
  series.some((row) => row.shortfall) && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_sanity_ui_compat2.Text, { size: 0, muted: true, children: "Shaded: what your analytics did not see." }),
1432
1432
  markers.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_sanity_ui_compat2.Text, { size: 0, muted: true, children: "Vertical rules mark campaign sends." }),
1433
1433
  onBrush && // The refusal replaces the instruction rather than sitting beside it, and it is a
@@ -1472,9 +1472,9 @@ function metricSortValue(metric) {
1472
1472
  }
1473
1473
  function metricOr(metric, detail) {
1474
1474
  if (metric) return metric;
1475
- return { status: "unavailable", reason: "not_applicable", detail };
1475
+ return { status: "unavailable", reason: "route_outdated", detail };
1476
1476
  }
1477
- var OLDER_ROUTE = "This site\u2019s API route predates this figure. Redeploy the site to see it.";
1477
+ var OLDER_ROUTE = "This site\u2019s analytics route is older than this figure \u2014 it will appear after the site is next deployed.";
1478
1478
  function maxOf(metrics) {
1479
1479
  return metrics.reduce((max, metric) => metric.status === "unavailable" ? max : Math.max(max, metric.value), 0);
1480
1480
  }
@@ -1789,7 +1789,6 @@ function Verdict({ data, previous }) {
1789
1789
  say("Revenue", data.revenue, previous?.revenue, "money");
1790
1790
  say("Traffic", data.vercelPageviews, previous?.vercelPageviews, "count");
1791
1791
  const sends = data.campaigns?.length ?? 0;
1792
- if (sends > 0) parts.push(`${sends} campaign${sends === 1 ? "" : "s"} sent`);
1793
1792
  const shortfall = data.shortfallRatio;
1794
1793
  const seeing = shortfall !== null && shortfall !== void 0 ? `GA4 is seeing ${formatPercent(1 - shortfall, 0)} of your traffic` : null;
1795
1794
  const broken = shortfall === null || shortfall === void 0 ? data.capture?.discrepancy ? "measurement disagrees between sources" : null : shortfall > 0.6 ? `${seeing} \u2014 treat its figures as broken` : shortfall > 0.35 ? `${seeing} \u2014 its figures are undercounts, not what happened` : data.capture?.discrepancy ? "measurement disagrees between sources" : null;
@@ -1871,7 +1870,7 @@ function DataHealthPanel({ data, diagnostics }) {
1871
1870
  ] }) }),
1872
1871
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_sanity_ui_compat3.Card, { padding: 3, radius: 2, tone: "transparent", border: true, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_sanity_ui_compat3.Stack, { space: 3, children: [
1873
1872
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_sanity_ui_compat3.Label, { size: 1, muted: true, children: "Consent granted" }),
1874
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MetricFigure, { metric: data.consentRate, label: "Consent granted, percent of sessions", unit: "percent" })
1873
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MetricFigure, { metric: data.consentRate, label: "Consent granted, share of visitors GA4 saw", unit: "percent" })
1875
1874
  ] }) })
1876
1875
  ] })
1877
1876
  ] }),
@@ -2428,7 +2427,7 @@ var PANELS = [
2428
2427
  { id: "acquisition", report: "acquisition", label: "Acquisition", blurb: "Where visitors come from" },
2429
2428
  { id: "journey", report: "journey", label: "Journey", blurb: "How far visitors get" },
2430
2429
  { id: "typeface-interest", report: "typeface-interest", label: "Typeface interest", blurb: "Viewed, tested and bought, by family" },
2431
- { id: "data-health", report: "measurement-health", label: "Data health", blurb: "Whether the numbers above can be trusted" }
2430
+ { id: "data-health", report: "measurement-health", label: "Data health", blurb: "Whether to trust what the other tabs are telling you" }
2432
2431
  ];
2433
2432
  function RangeSelector({
2434
2433
  value,
@@ -2615,14 +2614,14 @@ function CoverageRibbon({ ratio }) {
2615
2614
  const seen = Math.round((1 - ratio) * 100);
2616
2615
  const multiplier = seen > 0 ? Math.round(100 / seen) : null;
2617
2616
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_sanity_ui_compat4.Card, { padding: 3, radius: 2, tone: ratio > 0.6 ? "critical" : "caution", border: true, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_sanity_ui_compat4.Text, { size: 1, children: [
2618
- "Every figure on this tab comes from Google Analytics, which is seeing roughly ",
2617
+ "Most figures on this tab come from Google Analytics, which is seeing roughly ",
2619
2618
  seen,
2620
2619
  "% of this site\u2019s traffic in this window \u2014 so the real numbers are",
2621
2620
  " ",
2622
2621
  multiplier === null ? "many times" : `several times`,
2623
2622
  " these",
2624
2623
  multiplier !== null && multiplier > 1 ? ` (very roughly ${multiplier}\xD7)` : "",
2625
- ". Data health explains why, and how uncertain that is."
2624
+ ". Figures drawn from your orders \u2014 anything labelled as coming from Sanity \u2014 are exact and must not be scaled up. Data health explains the rest, and how uncertain it is."
2626
2625
  ] }) });
2627
2626
  }
2628
2627
  function ReadyReport({
@@ -2777,8 +2776,8 @@ function VisitorInsightsTool(props) {
2777
2776
  const [linked] = (0, import_react4.useState)(() => typeof window === "undefined" ? {} : decodeView(window.location.hash));
2778
2777
  const linkedRange = RANGES.some((r) => r.key === linked.range) ? linked.range : null;
2779
2778
  const linkedTab = PANELS.some((p) => p.id === linked.tab) ? linked.tab : null;
2780
- const [range, setRange] = (0, import_react4.useState)(linkedRange ?? "week");
2781
- const [rangeBeforeBrush, setRangeBeforeBrush] = (0, import_react4.useState)(linkedRange ?? "week");
2779
+ const [range, setRange] = (0, import_react4.useState)(linkedRange ?? "month");
2780
+ const [rangeBeforeBrush, setRangeBeforeBrush] = (0, import_react4.useState)(linkedRange ?? "month");
2782
2781
  const [custom, setCustom] = (0, import_react4.useState)(() => linked.from && linked.to ? { start: linked.from, end: linked.to } : { start: isoDaysAgo(30), end: isoDaysAgo(0) });
2783
2782
  const atPresent = custom.end >= isoDaysAgo(0);
2784
2783
  const [activePanel, setActivePanel] = (0, import_react4.useState)(linkedTab ?? "overview");