@the-smithy/hearth 0.17.0 → 0.18.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.
@@ -0,0 +1,15 @@
1
+ import { SiteAnalytics } from '@the-smithy/hearth-schema';
2
+
3
+ /**
4
+ * Records a named event, such as a sign-up, booking or download, with up to 10 short values. Names are lowercase
5
+ * letters, digits and `_ . : -`. Does nothing until <HearthAnalytics /> has loaded, or when analytics is off.
6
+ */
7
+ declare function track(name: string, props?: Record<string, string | number | boolean>): void;
8
+ type HearthAnalyticsProps = {
9
+ /** `site.analytics` from `getSite()`: null when the site's analytics is off (then render nothing). */
10
+ config: SiteAnalytics;
11
+ };
12
+ /** Counts a page view on load and on every page change. Renders nothing. */
13
+ declare function HearthAnalytics({ config }: HearthAnalyticsProps): null;
14
+
15
+ export { HearthAnalytics, type HearthAnalyticsProps, track };
@@ -0,0 +1,51 @@
1
+ "use client";
2
+
3
+ // src/analytics.tsx
4
+ import { useEffect, useRef } from "react";
5
+ import { usePathname } from "next/navigation";
6
+ var current = null;
7
+ function optedOut() {
8
+ const nav = navigator;
9
+ return nav.webdriver || nav.globalPrivacyControl === true || nav.doNotTrack === "1" || nav.msDoNotTrack === "1" || /^(localhost|127\.|\[::1\])/.test(location.hostname);
10
+ }
11
+ function send(config, body) {
12
+ if (optedOut()) return;
13
+ const payload = JSON.stringify({
14
+ k: config.key,
15
+ u: location.href,
16
+ // Only the browser's time zone, for a country: no location or IP lookup.
17
+ z: Intl.DateTimeFormat().resolvedOptions().timeZone,
18
+ // iPads report themselves as Macs; a touch screen tells them apart.
19
+ m: navigator.maxTouchPoints > 1,
20
+ ...body
21
+ });
22
+ try {
23
+ if (navigator.sendBeacon?.(config.endpoint, payload)) return;
24
+ void fetch(config.endpoint, { method: "POST", body: payload, keepalive: true, mode: "no-cors" }).catch(() => {
25
+ });
26
+ } catch {
27
+ }
28
+ }
29
+ function track(name, props) {
30
+ if (!current || typeof window === "undefined") return;
31
+ send(current, { t: "event", n: name, ...props ? { p: props } : {} });
32
+ }
33
+ function HearthAnalytics({ config }) {
34
+ const pathname = usePathname();
35
+ const first = useRef(true);
36
+ useEffect(() => {
37
+ current = config;
38
+ return () => {
39
+ current = null;
40
+ };
41
+ }, [config]);
42
+ useEffect(() => {
43
+ send(config, first.current ? { r: document.referrer } : {});
44
+ first.current = false;
45
+ }, [config, pathname]);
46
+ return null;
47
+ }
48
+ export {
49
+ HearthAnalytics,
50
+ track
51
+ };
@@ -221,6 +221,19 @@ function createCore(options) {
221
221
  /** Every redirect on the site (old addresses and where they go now). Empty from Hearth versions without them. */
222
222
  list: async (o = {}) => await maybe("/redirects", { ...o, resource: "redirects.list" }) ?? []
223
223
  },
224
+ analytics: {
225
+ /**
226
+ * Visitor analytics between two days (inclusive, `YYYY-MM-DD`; default the last 30 days): daily numbers, totals
227
+ * and the top pages, sources, campaigns, devices and countries. `null` from Hearth versions without analytics.
228
+ */
229
+ get: (query = {}, o = {}) => {
230
+ const q = new URLSearchParams();
231
+ if (query.from) q.set("from", query.from);
232
+ if (query.to) q.set("to", query.to);
233
+ if (query.limit !== void 0) q.set("limit", String(query.limit));
234
+ return maybe(`/analytics${q.size ? `?${q}` : ""}`, { ...o, resource: "analytics.get" });
235
+ }
236
+ },
224
237
  fundraisers: {
225
238
  /** Fundraisers with progress (sites with Giving). `category` is "group/category". */
226
239
  list: (opts = {}, o = {}) => {
@@ -1,4 +1,4 @@
1
- import { Collection, CollectionEntry, HearthEvent, Site, PageSummary, Page, HearthEventDetail, RegistrationInput, RegistrationResult, CategoryGroup, SitemapEntry, Redirect, Fundraiser, FundraiserDetail, DonationInput, DonationCheckout, HearthForm } from '@the-smithy/hearth-schema';
1
+ import { Collection, CollectionEntry, HearthEvent, Site, PageSummary, Page, HearthEventDetail, RegistrationInput, RegistrationResult, CategoryGroup, SitemapEntry, Redirect, AnalyticsReport, Fundraiser, FundraiserDetail, DonationInput, DonationCheckout, HearthForm } from '@the-smithy/hearth-schema';
2
2
 
3
3
  type HearthErrorCode = "unauthorized" | "not_found" | "bad_request" | "feature_disabled" | "rate_limited" | "server_error" | "network" | "timeout" | "invalid_response";
4
4
  /** Any failure talking to Hearth. Messages never contain the API key. */
@@ -167,6 +167,17 @@ declare function createCore(options: HearthClientOptions): {
167
167
  /** Every redirect on the site (old addresses and where they go now). Empty from Hearth versions without them. */
168
168
  list: (o?: CallOptions) => Promise<Redirect[]>;
169
169
  };
170
+ analytics: {
171
+ /**
172
+ * Visitor analytics between two days (inclusive, `YYYY-MM-DD`; default the last 30 days): daily numbers, totals
173
+ * and the top pages, sources, campaigns, devices and countries. `null` from Hearth versions without analytics.
174
+ */
175
+ get: (query?: {
176
+ from?: string;
177
+ to?: string;
178
+ limit?: number;
179
+ }, o?: CallOptions) => Promise<AnalyticsReport | null>;
180
+ };
170
181
  fundraisers: {
171
182
  /** Fundraisers with progress (sites with Giving). `category` is "group/category". */
172
183
  list: (opts?: {
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { H as HearthCore, a as HearthClientOptions } from './client-CnIniG4N.js';
2
- export { C as CallOptions, b as CollectionPage, D as DEFAULT_BASE_URL, E as EventCollectionPage, F as FormResult, c as FormValues, d as HearthError, e as HearthErrorCode, f as HearthHooks, N as NextFetchOptions, P as PreviewSession, R as RequestContext, g as RequestOptions, h as findRedirect, i as isHearthError, n as normalizeSlug } from './client-CnIniG4N.js';
3
- export { Block, BlockOf, CategoryGroup, CategoryRef, Collection, CollectionEntry, CollectionRef, DonationCheckout, DonationInput, EntryDetails, EventCustomFields, EventRegistration, EventTicket, Fundraiser, FundraiserDetail, HearthEvent, HearthEventDetail, KnownBlock, Page, PageMeta, PageSummary, Redirect, RegistrationInput, RegistrationResult, ResolvedBlock, Site, SiteSettings, SitemapEntry, UnknownBlock, WebhookPayload, videoEmbedUrl } from '@the-smithy/hearth-schema';
1
+ import { H as HearthCore, a as HearthClientOptions } from './client-B3n7p9lK.js';
2
+ export { C as CallOptions, b as CollectionPage, D as DEFAULT_BASE_URL, E as EventCollectionPage, F as FormResult, c as FormValues, d as HearthError, e as HearthErrorCode, f as HearthHooks, N as NextFetchOptions, P as PreviewSession, R as RequestContext, g as RequestOptions, h as findRedirect, i as isHearthError, n as normalizeSlug } from './client-B3n7p9lK.js';
3
+ export { AnalyticsReport, AnalyticsRow, Block, BlockOf, CategoryGroup, CategoryRef, Collection, CollectionEntry, CollectionRef, DonationCheckout, DonationInput, EntryDetails, EventCustomFields, EventRegistration, EventTicket, Fundraiser, FundraiserDetail, HearthEvent, HearthEventDetail, KnownBlock, Page, PageMeta, PageSummary, Redirect, RegistrationInput, RegistrationResult, ResolvedBlock, Site, SiteAnalytics, SiteSettings, SitemapEntry, UnknownBlock, WebhookPayload, videoEmbedUrl } from '@the-smithy/hearth-schema';
4
4
 
5
5
  /** A plugin adds resources (and can use the core's `request`) under its own names. */
6
6
  type HearthPlugin<T extends object = object> = {
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  findRedirect,
6
6
  isHearthError,
7
7
  normalizeSlug
8
- } from "./chunk-RYCXMQM2.js";
8
+ } from "./chunk-62OMCVBE.js";
9
9
 
10
10
  // src/index.ts
11
11
  import { videoEmbedUrl } from "@the-smithy/hearth-schema";
package/dist/next.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { H as HearthCore, b as CollectionPage, E as EventCollectionPage, F as FormResult, c as FormValues } from './client-CnIniG4N.js';
1
+ import { H as HearthCore, b as CollectionPage, E as EventCollectionPage, F as FormResult, c as FormValues } from './client-B3n7p9lK.js';
2
2
  import * as _the_smithy_hearth_schema from '@the-smithy/hearth-schema';
3
3
  import { Site, PageMeta } from '@the-smithy/hearth-schema';
4
4
  import { Metadata, MetadataRoute } from 'next';
package/dist/next.js CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  findRedirect,
3
3
  isHearthError,
4
4
  normalizeSlug
5
- } from "./chunk-RYCXMQM2.js";
5
+ } from "./chunk-62OMCVBE.js";
6
6
  import {
7
7
  parseWebhook,
8
8
  tagsForWebhook
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@the-smithy/hearth",
3
- "version": "0.17.0",
3
+ "version": "0.18.0",
4
4
  "description": "Typed client for the Hearth Delivery API: content, SEO, forms and publish webhooks.",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -30,6 +30,10 @@
30
30
  "types": "./dist/preview.d.ts",
31
31
  "import": "./dist/preview.js"
32
32
  },
33
+ "./analytics": {
34
+ "types": "./dist/analytics.d.ts",
35
+ "import": "./dist/analytics.js"
36
+ },
33
37
  "./webhooks": {
34
38
  "types": "./dist/webhooks.d.ts",
35
39
  "import": "./dist/webhooks.js"
@@ -45,7 +49,7 @@
45
49
  "llms.md"
46
50
  ],
47
51
  "dependencies": {
48
- "@the-smithy/hearth-schema": "^0.17.0"
52
+ "@the-smithy/hearth-schema": "^0.18.0"
49
53
  },
50
54
  "peerDependencies": {
51
55
  "next": ">=15",