@businessdash/sdk 0.9.60 → 0.9.80
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 +991 -295
- package/assets/biab-sw.js +92 -0
- package/dist/account-core/index.d.ts +126 -0
- package/dist/account-core/index.d.ts.map +1 -0
- package/dist/account-core/index.js +191 -0
- package/dist/account-core/index.js.map +1 -0
- package/dist/account.d.ts +11 -0
- package/dist/account.d.ts.map +1 -0
- package/dist/account.js +11 -0
- package/dist/account.js.map +1 -0
- package/dist/auth-handler.d.ts +1 -1
- package/dist/auth-links.d.ts +33 -0
- package/dist/auth-links.d.ts.map +1 -0
- package/dist/auth-links.js +64 -0
- package/dist/auth-links.js.map +1 -0
- package/dist/blog-core/index.d.ts +112 -0
- package/dist/blog-core/index.d.ts.map +1 -0
- package/dist/blog-core/index.js +330 -0
- package/dist/blog-core/index.js.map +1 -0
- package/dist/blog.d.ts +11 -0
- package/dist/blog.d.ts.map +1 -0
- package/dist/blog.js +11 -0
- package/dist/blog.js.map +1 -0
- package/dist/chat-core/index.d.ts +97 -0
- package/dist/chat-core/index.d.ts.map +1 -0
- package/dist/chat-core/index.js +237 -0
- package/dist/chat-core/index.js.map +1 -0
- package/dist/chat.d.ts +11 -0
- package/dist/chat.d.ts.map +1 -0
- package/dist/chat.js +11 -0
- package/dist/chat.js.map +1 -0
- package/dist/checkout-core/index.d.ts +65 -0
- package/dist/checkout-core/index.d.ts.map +1 -0
- package/dist/checkout-core/index.js +159 -0
- package/dist/checkout-core/index.js.map +1 -0
- package/dist/checkout.d.ts +10 -0
- package/dist/checkout.d.ts.map +1 -0
- package/dist/checkout.js +10 -0
- package/dist/checkout.js.map +1 -0
- package/dist/cli.js +133 -25
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +622 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +888 -1
- package/dist/client.js.map +1 -1
- package/dist/consent-core/index.cjs +107 -0
- package/dist/consent-core/index.d.ts +103 -0
- package/dist/consent-core/index.d.ts.map +1 -0
- package/dist/consent-core/index.js +157 -0
- package/dist/consent-core/index.js.map +1 -0
- package/dist/contracts.d.ts +3526 -767
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +571 -4
- package/dist/contracts.js.map +1 -1
- package/dist/data-model-schema.d.ts +1 -1
- package/dist/data-model-schema.d.ts.map +1 -1
- package/dist/element.d.ts +30 -0
- package/dist/element.d.ts.map +1 -1
- package/dist/element.js +56 -0
- package/dist/element.js.map +1 -1
- package/dist/embed-protocol.d.ts +86 -0
- package/dist/embed-protocol.d.ts.map +1 -0
- package/dist/embed-protocol.js +60 -0
- package/dist/embed-protocol.js.map +1 -0
- package/dist/framework-support.d.ts +122 -0
- package/dist/framework-support.d.ts.map +1 -0
- package/dist/framework-support.js +323 -0
- package/dist/framework-support.js.map +1 -0
- package/dist/index.cjs +1355 -24
- package/dist/legal-core/index.cjs +115 -0
- package/dist/legal-core/index.d.ts +160 -0
- package/dist/legal-core/index.d.ts.map +1 -0
- package/dist/legal-core/index.js +220 -0
- package/dist/legal-core/index.js.map +1 -0
- package/dist/marketing-core/index.d.ts +66 -0
- package/dist/marketing-core/index.d.ts.map +1 -0
- package/dist/marketing-core/index.js +154 -0
- package/dist/marketing-core/index.js.map +1 -0
- package/dist/marketing.d.ts +7 -0
- package/dist/marketing.d.ts.map +1 -0
- package/dist/marketing.js +7 -0
- package/dist/marketing.js.map +1 -0
- package/dist/mcp-adapters/index.d.ts +135 -0
- package/dist/mcp-adapters/index.d.ts.map +1 -0
- package/dist/mcp-adapters/index.js +187 -0
- package/dist/mcp-adapters/index.js.map +1 -0
- package/dist/mcp-adapters.d.ts +7 -0
- package/dist/mcp-adapters.d.ts.map +1 -0
- package/dist/mcp-adapters.js +7 -0
- package/dist/mcp-adapters.js.map +1 -0
- package/dist/model3d-core/index.cjs +95 -0
- package/dist/model3d-core/index.d.ts +167 -0
- package/dist/model3d-core/index.d.ts.map +1 -0
- package/dist/model3d-core/index.js +158 -0
- package/dist/model3d-core/index.js.map +1 -0
- package/dist/notifications-core/index.cjs +315 -0
- package/dist/notifications-core/index.d.ts +229 -0
- package/dist/notifications-core/index.d.ts.map +1 -0
- package/dist/notifications-core/index.js +445 -0
- package/dist/notifications-core/index.js.map +1 -0
- package/dist/portal-core/index.d.ts +451 -0
- package/dist/portal-core/index.d.ts.map +1 -0
- package/dist/portal-core/index.js +819 -0
- package/dist/portal-core/index.js.map +1 -0
- package/dist/portal.d.ts +7 -0
- package/dist/portal.d.ts.map +1 -0
- package/dist/portal.js +7 -0
- package/dist/portal.js.map +1 -0
- package/dist/push-core/index.cjs +171 -0
- package/dist/push-core/index.d.ts +149 -0
- package/dist/push-core/index.d.ts.map +1 -0
- package/dist/push-core/index.js +231 -0
- package/dist/push-core/index.js.map +1 -0
- package/dist/react-marketing.d.ts +1 -17
- package/dist/react-marketing.d.ts.map +1 -1
- package/dist/react-marketing.js +4 -0
- package/dist/react-marketing.js.map +1 -1
- package/dist/react.d.ts +294 -101
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +302 -246
- package/dist/react.js.map +1 -1
- package/dist/seed-core/index.d.ts +354 -0
- package/dist/seed-core/index.d.ts.map +1 -0
- package/dist/seed-core/index.js +420 -0
- package/dist/seed-core/index.js.map +1 -0
- package/dist/seed.d.ts +7 -0
- package/dist/seed.d.ts.map +1 -0
- package/dist/seed.js +7 -0
- package/dist/seed.js.map +1 -0
- package/dist/seo-core/blog.d.ts +94 -0
- package/dist/seo-core/blog.d.ts.map +1 -0
- package/dist/seo-core/blog.js +149 -0
- package/dist/seo-core/blog.js.map +1 -0
- package/dist/seo-core/commerce.d.ts +64 -0
- package/dist/seo-core/commerce.d.ts.map +1 -0
- package/dist/seo-core/commerce.js +87 -0
- package/dist/seo-core/commerce.js.map +1 -0
- package/dist/seo-core/index.cjs +751 -0
- package/dist/seo-core/index.d.ts +226 -0
- package/dist/seo-core/index.d.ts.map +1 -0
- package/dist/seo-core/index.js +455 -0
- package/dist/seo-core/index.js.map +1 -0
- package/dist/seo-core/local.d.ts +181 -0
- package/dist/seo-core/local.d.ts.map +1 -0
- package/dist/seo-core/local.js +193 -0
- package/dist/seo-core/local.js.map +1 -0
- package/dist/sitemap-core/index.cjs +167 -0
- package/dist/sitemap-core/index.d.ts +155 -0
- package/dist/sitemap-core/index.d.ts.map +1 -0
- package/dist/sitemap-core/index.js +195 -0
- package/dist/sitemap-core/index.js.map +1 -0
- package/dist/social-core/index.d.ts +74 -0
- package/dist/social-core/index.d.ts.map +1 -0
- package/dist/social-core/index.js +72 -0
- package/dist/social-core/index.js.map +1 -0
- package/dist/social.d.ts +7 -0
- package/dist/social.d.ts.map +1 -0
- package/dist/social.js +7 -0
- package/dist/social.js.map +1 -0
- package/dist/solid-compat.d.ts +204 -0
- package/dist/solid-compat.d.ts.map +1 -0
- package/dist/solid-compat.js +221 -0
- package/dist/solid-compat.js.map +1 -0
- package/dist/store-core/index.d.ts +141 -0
- package/dist/store-core/index.d.ts.map +1 -0
- package/dist/store-core/index.js +277 -0
- package/dist/store-core/index.js.map +1 -0
- package/dist/store.d.ts +12 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +12 -0
- package/dist/store.js.map +1 -0
- package/dist/vanilla.d.ts +111 -0
- package/dist/vanilla.d.ts.map +1 -1
- package/dist/vanilla.js +206 -0
- package/dist/vanilla.js.map +1 -1
- package/dist/verify-core/index.d.ts +98 -0
- package/dist/verify-core/index.d.ts.map +1 -0
- package/dist/verify-core/index.js +186 -0
- package/dist/verify-core/index.js.map +1 -0
- package/dist/verify.d.ts +8 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +8 -0
- package/dist/verify.js.map +1 -0
- package/openapi.json +4516 -1311
- package/package.json +128 -11
- package/src/account-core/index.ts +309 -0
- package/src/account.ts +11 -0
- package/src/angular/headless.ts +519 -0
- package/src/angular/index.ts +3 -0
- package/src/auth-links.ts +76 -0
- package/src/blog-core/index.ts +423 -0
- package/src/blog.ts +11 -0
- package/src/chat-core/index.ts +335 -0
- package/src/chat.ts +11 -0
- package/src/checkout-core/index.ts +225 -0
- package/src/checkout.ts +10 -0
- package/src/cli.ts +184 -28
- package/src/client.ts +1097 -0
- package/src/consent-core/index.ts +213 -0
- package/src/contracts.ts +768 -11
- package/src/data-model-schema.ts +1 -1
- package/src/element.ts +102 -0
- package/src/embed-protocol.ts +100 -0
- package/src/framework-support.ts +440 -0
- package/src/legal-core/index.ts +276 -0
- package/src/marketing-core/index.ts +209 -0
- package/src/marketing.ts +7 -0
- package/src/mcp-adapters/index.ts +264 -0
- package/src/mcp-adapters.ts +7 -0
- package/src/model3d-core/index.ts +248 -0
- package/src/notifications-core/index.ts +650 -0
- package/src/portal-core/index.ts +1564 -0
- package/src/portal.ts +7 -0
- package/src/push-core/index.ts +335 -0
- package/src/qwik.tsx +602 -2
- package/src/react-marketing.tsx +5 -0
- package/src/react.tsx +434 -319
- package/src/seed-core/index.ts +735 -0
- package/src/seed.ts +7 -0
- package/src/seo-core/blog.ts +216 -0
- package/src/seo-core/commerce.ts +138 -0
- package/src/seo-core/index.ts +605 -0
- package/src/seo-core/local.ts +333 -0
- package/src/sitemap-core/index.ts +296 -0
- package/src/social-core/index.ts +103 -0
- package/src/social.ts +7 -0
- package/src/solid-compat.tsx +347 -0
- package/src/solid-surfaces.tsx +1311 -0
- package/src/solid.tsx +82 -60
- package/src/store-core/index.ts +426 -0
- package/src/store.ts +12 -0
- package/src/svelte/SocialLinks.svelte +84 -0
- package/src/svelte/headless.ts +435 -0
- package/src/svelte/index.ts +9 -0
- package/src/vanilla.ts +367 -0
- package/src/verify-core/index.ts +288 -0
- package/src/verify.ts +8 -0
- package/src/vue/headless.ts +527 -0
- package/src/vue/index.ts +3 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/seo-core/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local SEO: the pages that win "plumber in Ashford" and "buy X near me".
|
|
3
|
+
*
|
|
4
|
+
* ## What this adds over the builders in `@businessdash/sdk/seo`
|
|
5
|
+
*
|
|
6
|
+
* Those are primitives — `service()`, `localBusiness()`, `product()`,
|
|
7
|
+
* `breadcrumb()` — each producing one JSON-LD node. Correct, and not the thing
|
|
8
|
+
* a consumer actually needs, because a local landing page is not one node. It
|
|
9
|
+
* is a `Service` scoped to an area, the `LocalBusiness` that provides it, and
|
|
10
|
+
* a `BreadcrumbList` placing it in the site, plus the meta tags that carry the
|
|
11
|
+
* place name into the title and description.
|
|
12
|
+
*
|
|
13
|
+
* Assembling that by hand for every service × area combination is where local
|
|
14
|
+
* SEO dies: someone ships 400 pages that all claim `areaServed: "Nationwide"`,
|
|
15
|
+
* or 400 identical titles, and the pages compete with each other instead of
|
|
16
|
+
* ranking.
|
|
17
|
+
*
|
|
18
|
+
* So these return a `SeoInput` — meta AND structured data together — that
|
|
19
|
+
* composes with `resolveSeo()` like any other layer.
|
|
20
|
+
*
|
|
21
|
+
* ## The multiplication is the point, and the risk
|
|
22
|
+
*
|
|
23
|
+
* `servicesTimesAreas()` exists because service × area is a Cartesian product
|
|
24
|
+
* and doing it by hand is how mistakes scale. It is also how thin content
|
|
25
|
+
* scales, so it takes a `describe` callback rather than templating a sentence
|
|
26
|
+
* for you: pages that differ only by a swapped town name are what "doorway
|
|
27
|
+
* pages" means, and Google has a specific penalty for them.
|
|
28
|
+
*
|
|
29
|
+
* @module
|
|
30
|
+
*/
|
|
31
|
+
import { type LocalBusinessInput } from "../seo.js";
|
|
32
|
+
import type { SeoInput } from "./index.js";
|
|
33
|
+
/** A place the org serves. */
|
|
34
|
+
export type ServiceArea = {
|
|
35
|
+
/** URL segment, e.g. `ashford`. */
|
|
36
|
+
slug: string;
|
|
37
|
+
/** Display name, e.g. `Ashford`. */
|
|
38
|
+
name: string;
|
|
39
|
+
/** Optional region for disambiguation — `Kent`, `WA`. */
|
|
40
|
+
region?: string;
|
|
41
|
+
};
|
|
42
|
+
/** One thing the org does. */
|
|
43
|
+
export type ServiceOffering = {
|
|
44
|
+
slug: string;
|
|
45
|
+
name: string;
|
|
46
|
+
description: string;
|
|
47
|
+
};
|
|
48
|
+
export type LocalServicePageInput = {
|
|
49
|
+
/** Absolute site origin, no trailing slash. */
|
|
50
|
+
siteUrl: string;
|
|
51
|
+
service: ServiceOffering;
|
|
52
|
+
area: ServiceArea;
|
|
53
|
+
/**
|
|
54
|
+
* Path of THIS page, e.g. `/services/drain-cleaning/ashford`.
|
|
55
|
+
*
|
|
56
|
+
* Required, and used as the canonical. A service-area page without its own
|
|
57
|
+
* canonical is the single most common way these get deduplicated away by
|
|
58
|
+
* search engines — they look near-identical, so one is picked and the rest
|
|
59
|
+
* are dropped.
|
|
60
|
+
*/
|
|
61
|
+
path: string;
|
|
62
|
+
/**
|
|
63
|
+
* The page's own copy.
|
|
64
|
+
*
|
|
65
|
+
* A callback rather than a template, deliberately. Generating 400 pages
|
|
66
|
+
* whose only difference is the town name produces doorway pages, which are
|
|
67
|
+
* penalised rather than ranked. Write something true about serving that
|
|
68
|
+
* place, or do not generate the page.
|
|
69
|
+
*/
|
|
70
|
+
describe?: (input: {
|
|
71
|
+
service: ServiceOffering;
|
|
72
|
+
area: ServiceArea;
|
|
73
|
+
}) => {
|
|
74
|
+
title?: string;
|
|
75
|
+
description?: string;
|
|
76
|
+
};
|
|
77
|
+
/** The org, for the `LocalBusiness` node the `Service` points at. */
|
|
78
|
+
business?: LocalBusinessInput;
|
|
79
|
+
/** Extra crumbs before this page. Home is added automatically. */
|
|
80
|
+
breadcrumbs?: Array<{
|
|
81
|
+
name: string;
|
|
82
|
+
url: string;
|
|
83
|
+
}>;
|
|
84
|
+
ogImage?: string;
|
|
85
|
+
noIndex?: boolean;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* SEO for one service in one place.
|
|
89
|
+
*
|
|
90
|
+
* ```ts
|
|
91
|
+
* const seo = resolveSeo(
|
|
92
|
+
* layoutDefaults,
|
|
93
|
+
* localServicePageSeo({ siteUrl, service, area, path }),
|
|
94
|
+
* )
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
export declare function localServicePageSeo(input: LocalServicePageInput): SeoInput;
|
|
98
|
+
export type LocalProductPageInput = {
|
|
99
|
+
siteUrl: string;
|
|
100
|
+
path: string;
|
|
101
|
+
product: {
|
|
102
|
+
name: string;
|
|
103
|
+
description?: string;
|
|
104
|
+
sku?: string;
|
|
105
|
+
brand?: string;
|
|
106
|
+
image?: string | string[];
|
|
107
|
+
/** Integer cents — the money rule everywhere in this codebase. */
|
|
108
|
+
priceCents?: number;
|
|
109
|
+
currency?: string;
|
|
110
|
+
availability?: "InStock" | "OutOfStock" | "PreOrder";
|
|
111
|
+
/**
|
|
112
|
+
* Average rating and how many reviews it came from.
|
|
113
|
+
*
|
|
114
|
+
* Both required together, and omitted entirely when `reviewCount` is 0.
|
|
115
|
+
* An `AggregateRating` with zero reviews is invalid structured data —
|
|
116
|
+
* Google rejects the whole Product node for it, so a product with no
|
|
117
|
+
* reviews yet would lose its price and availability too.
|
|
118
|
+
*/
|
|
119
|
+
avgRating?: number;
|
|
120
|
+
reviewCount?: number;
|
|
121
|
+
/**
|
|
122
|
+
* Cheapest and dearest variant, in cents.
|
|
123
|
+
*
|
|
124
|
+
* When a product has variants at different prices, a single `price` is
|
|
125
|
+
* a lie in one direction or the other. `AggregateOffer` states the
|
|
126
|
+
* range, which is what shopping surfaces display.
|
|
127
|
+
*/
|
|
128
|
+
priceRangeCents?: {
|
|
129
|
+
low: number;
|
|
130
|
+
high: number;
|
|
131
|
+
};
|
|
132
|
+
};
|
|
133
|
+
breadcrumbs?: Array<{
|
|
134
|
+
name: string;
|
|
135
|
+
url: string;
|
|
136
|
+
}>;
|
|
137
|
+
noIndex?: boolean;
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* SEO for a product page.
|
|
141
|
+
*
|
|
142
|
+
* Pairs with the AI Distribution product feed: the feed gets the product into
|
|
143
|
+
* the engines' catalogues, this markup is what their crawlers verify when they
|
|
144
|
+
* land on the page. One without the other is half the job — a feed entry with
|
|
145
|
+
* no matching page markup reads as unverified.
|
|
146
|
+
*/
|
|
147
|
+
export declare function productPageSeo(input: LocalProductPageInput): SeoInput;
|
|
148
|
+
export type ServicesTimesAreasInput = {
|
|
149
|
+
siteUrl: string;
|
|
150
|
+
services: readonly ServiceOffering[];
|
|
151
|
+
areas: readonly ServiceArea[];
|
|
152
|
+
/** Build the path for one combination. */
|
|
153
|
+
path: (service: ServiceOffering, area: ServiceArea) => string;
|
|
154
|
+
describe?: LocalServicePageInput["describe"];
|
|
155
|
+
business?: LocalBusinessInput;
|
|
156
|
+
/**
|
|
157
|
+
* Skip combinations the org does not actually serve.
|
|
158
|
+
*
|
|
159
|
+
* Worth using. A page for a service you do not offer in a place you do not
|
|
160
|
+
* cover is a page that ranks, gets clicked, and produces a call you have to
|
|
161
|
+
* turn down — which costs more than the traffic was worth.
|
|
162
|
+
*/
|
|
163
|
+
include?: (service: ServiceOffering, area: ServiceArea) => boolean;
|
|
164
|
+
};
|
|
165
|
+
/** One generated combination: where it lives, and its SEO. */
|
|
166
|
+
export type LocalPagePlan = {
|
|
167
|
+
path: string;
|
|
168
|
+
service: ServiceOffering;
|
|
169
|
+
area: ServiceArea;
|
|
170
|
+
seo: SeoInput;
|
|
171
|
+
};
|
|
172
|
+
/**
|
|
173
|
+
* Every service × area combination, as a list of pages to generate.
|
|
174
|
+
*
|
|
175
|
+
* Returns plans rather than rendering anything: which router builds them, and
|
|
176
|
+
* how, is the framework's business. Feed the result to Next's
|
|
177
|
+
* `generateStaticParams`, Astro's `getStaticPaths`, a SvelteKit `entries`
|
|
178
|
+
* export, or a loop in a build script.
|
|
179
|
+
*/
|
|
180
|
+
export declare function servicesTimesAreas(input: ServicesTimesAreasInput): LocalPagePlan[];
|
|
181
|
+
//# sourceMappingURL=local.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../src/seo-core/local.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local SEO: the pages that win "plumber in Ashford" and "buy X near me".
|
|
3
|
+
*
|
|
4
|
+
* ## What this adds over the builders in `@businessdash/sdk/seo`
|
|
5
|
+
*
|
|
6
|
+
* Those are primitives — `service()`, `localBusiness()`, `product()`,
|
|
7
|
+
* `breadcrumb()` — each producing one JSON-LD node. Correct, and not the thing
|
|
8
|
+
* a consumer actually needs, because a local landing page is not one node. It
|
|
9
|
+
* is a `Service` scoped to an area, the `LocalBusiness` that provides it, and
|
|
10
|
+
* a `BreadcrumbList` placing it in the site, plus the meta tags that carry the
|
|
11
|
+
* place name into the title and description.
|
|
12
|
+
*
|
|
13
|
+
* Assembling that by hand for every service × area combination is where local
|
|
14
|
+
* SEO dies: someone ships 400 pages that all claim `areaServed: "Nationwide"`,
|
|
15
|
+
* or 400 identical titles, and the pages compete with each other instead of
|
|
16
|
+
* ranking.
|
|
17
|
+
*
|
|
18
|
+
* So these return a `SeoInput` — meta AND structured data together — that
|
|
19
|
+
* composes with `resolveSeo()` like any other layer.
|
|
20
|
+
*
|
|
21
|
+
* ## The multiplication is the point, and the risk
|
|
22
|
+
*
|
|
23
|
+
* `servicesTimesAreas()` exists because service × area is a Cartesian product
|
|
24
|
+
* and doing it by hand is how mistakes scale. It is also how thin content
|
|
25
|
+
* scales, so it takes a `describe` callback rather than templating a sentence
|
|
26
|
+
* for you: pages that differ only by a swapped town name are what "doorway
|
|
27
|
+
* pages" means, and Google has a specific penalty for them.
|
|
28
|
+
*
|
|
29
|
+
* @module
|
|
30
|
+
*/
|
|
31
|
+
import { breadcrumb, localBusiness, product as productNode, service as serviceNode, } from "../seo.js";
|
|
32
|
+
function areaLabel(area) {
|
|
33
|
+
return area.region ? `${area.name}, ${area.region}` : area.name;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* SEO for one service in one place.
|
|
37
|
+
*
|
|
38
|
+
* ```ts
|
|
39
|
+
* const seo = resolveSeo(
|
|
40
|
+
* layoutDefaults,
|
|
41
|
+
* localServicePageSeo({ siteUrl, service, area, path }),
|
|
42
|
+
* )
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export function localServicePageSeo(input) {
|
|
46
|
+
const label = areaLabel(input.area);
|
|
47
|
+
const written = input.describe?.({
|
|
48
|
+
service: input.service,
|
|
49
|
+
area: input.area,
|
|
50
|
+
});
|
|
51
|
+
const title = written?.title ?? `${input.service.name} in ${label}`;
|
|
52
|
+
const description = written?.description ??
|
|
53
|
+
`${input.service.description} Serving ${label} and the surrounding area.`;
|
|
54
|
+
const canonical = `${input.siteUrl.replace(/\/+$/, "")}${input.path}`;
|
|
55
|
+
const jsonLd = [
|
|
56
|
+
serviceNode({
|
|
57
|
+
siteUrl: input.siteUrl,
|
|
58
|
+
slug: input.service.slug,
|
|
59
|
+
title: input.service.name,
|
|
60
|
+
description,
|
|
61
|
+
// The whole point of the page: this service, in THIS place. A node
|
|
62
|
+
// that omits it is indistinguishable from the generic service page.
|
|
63
|
+
areaServed: [label],
|
|
64
|
+
}),
|
|
65
|
+
];
|
|
66
|
+
if (input.business)
|
|
67
|
+
jsonLd.push(localBusiness(input.business));
|
|
68
|
+
jsonLd.push(breadcrumb({
|
|
69
|
+
siteUrl: input.siteUrl,
|
|
70
|
+
items: [
|
|
71
|
+
{ name: "Home", url: input.siteUrl },
|
|
72
|
+
...(input.breadcrumbs ?? []),
|
|
73
|
+
{ name: `${input.service.name} in ${label}`, url: canonical },
|
|
74
|
+
],
|
|
75
|
+
}));
|
|
76
|
+
return {
|
|
77
|
+
title,
|
|
78
|
+
description,
|
|
79
|
+
canonical,
|
|
80
|
+
...(input.ogImage ? { ogImage: input.ogImage } : {}),
|
|
81
|
+
...(input.noIndex === undefined ? {} : { noIndex: input.noIndex }),
|
|
82
|
+
jsonLd,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* SEO for a product page.
|
|
87
|
+
*
|
|
88
|
+
* Pairs with the AI Distribution product feed: the feed gets the product into
|
|
89
|
+
* the engines' catalogues, this markup is what their crawlers verify when they
|
|
90
|
+
* land on the page. One without the other is half the job — a feed entry with
|
|
91
|
+
* no matching page markup reads as unverified.
|
|
92
|
+
*/
|
|
93
|
+
export function productPageSeo(input) {
|
|
94
|
+
const canonical = `${input.siteUrl.replace(/\/+$/, "")}${input.path}`;
|
|
95
|
+
const p = input.product;
|
|
96
|
+
const jsonLd = [
|
|
97
|
+
productNode({
|
|
98
|
+
url: canonical,
|
|
99
|
+
name: p.name,
|
|
100
|
+
...(p.description ? { description: p.description } : {}),
|
|
101
|
+
...(p.image ? { image: p.image } : {}),
|
|
102
|
+
...(p.brand ? { brand: p.brand } : {}),
|
|
103
|
+
...(p.sku ? { sku: p.sku } : {}),
|
|
104
|
+
...(p.priceCents === undefined
|
|
105
|
+
? {}
|
|
106
|
+
: {
|
|
107
|
+
offer: {
|
|
108
|
+
priceCents: p.priceCents,
|
|
109
|
+
...(p.currency ? { currency: p.currency } : {}),
|
|
110
|
+
...(p.availability ? { availability: p.availability } : {}),
|
|
111
|
+
},
|
|
112
|
+
}),
|
|
113
|
+
}),
|
|
114
|
+
breadcrumb({
|
|
115
|
+
siteUrl: input.siteUrl,
|
|
116
|
+
items: [
|
|
117
|
+
{ name: "Home", url: input.siteUrl },
|
|
118
|
+
...(input.breadcrumbs ?? []),
|
|
119
|
+
{ name: p.name, url: canonical },
|
|
120
|
+
],
|
|
121
|
+
}),
|
|
122
|
+
];
|
|
123
|
+
// Ratings and price ranges are patched onto the Product node rather than
|
|
124
|
+
// passed to `product()`, whose input covers a single offer. Both are what
|
|
125
|
+
// turn a plain result into a rich one — stars and a price range are the
|
|
126
|
+
// whole visual difference in a shopping surface.
|
|
127
|
+
const productJson = jsonLd[0];
|
|
128
|
+
if (typeof p.avgRating === "number" &&
|
|
129
|
+
typeof p.reviewCount === "number" &&
|
|
130
|
+
p.reviewCount > 0) {
|
|
131
|
+
productJson["aggregateRating"] = {
|
|
132
|
+
"@type": "AggregateRating",
|
|
133
|
+
ratingValue: p.avgRating,
|
|
134
|
+
reviewCount: p.reviewCount,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
if (p.priceRangeCents && p.priceRangeCents.high > p.priceRangeCents.low) {
|
|
138
|
+
productJson["offers"] = {
|
|
139
|
+
"@type": "AggregateOffer",
|
|
140
|
+
priceCurrency: p.currency ?? "USD",
|
|
141
|
+
lowPrice: (p.priceRangeCents.low / 100).toFixed(2),
|
|
142
|
+
highPrice: (p.priceRangeCents.high / 100).toFixed(2),
|
|
143
|
+
...(p.availability
|
|
144
|
+
? { availability: `https://schema.org/${p.availability}` }
|
|
145
|
+
: {}),
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
title: p.name,
|
|
150
|
+
...(p.description ? { description: p.description } : {}),
|
|
151
|
+
canonical,
|
|
152
|
+
...(p.image
|
|
153
|
+
? { ogImage: Array.isArray(p.image) ? p.image[0] : p.image }
|
|
154
|
+
: {}),
|
|
155
|
+
// Products are things people buy, so the card should show the thing.
|
|
156
|
+
ogType: "product",
|
|
157
|
+
...(input.noIndex === undefined ? {} : { noIndex: input.noIndex }),
|
|
158
|
+
jsonLd,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Every service × area combination, as a list of pages to generate.
|
|
163
|
+
*
|
|
164
|
+
* Returns plans rather than rendering anything: which router builds them, and
|
|
165
|
+
* how, is the framework's business. Feed the result to Next's
|
|
166
|
+
* `generateStaticParams`, Astro's `getStaticPaths`, a SvelteKit `entries`
|
|
167
|
+
* export, or a loop in a build script.
|
|
168
|
+
*/
|
|
169
|
+
export function servicesTimesAreas(input) {
|
|
170
|
+
const plans = [];
|
|
171
|
+
for (const service of input.services) {
|
|
172
|
+
for (const area of input.areas) {
|
|
173
|
+
if (input.include && !input.include(service, area))
|
|
174
|
+
continue;
|
|
175
|
+
const path = input.path(service, area);
|
|
176
|
+
plans.push({
|
|
177
|
+
path,
|
|
178
|
+
service,
|
|
179
|
+
area,
|
|
180
|
+
seo: localServicePageSeo({
|
|
181
|
+
siteUrl: input.siteUrl,
|
|
182
|
+
service,
|
|
183
|
+
area,
|
|
184
|
+
path,
|
|
185
|
+
...(input.describe ? { describe: input.describe } : {}),
|
|
186
|
+
...(input.business ? { business: input.business } : {}),
|
|
187
|
+
}),
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return plans;
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=local.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local.js","sourceRoot":"","sources":["../../src/seo-core/local.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/sitemap-core/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
buildSitemap: () => buildSitemap,
|
|
24
|
+
collectSitemapEntries: () => collectSitemapEntries,
|
|
25
|
+
minimalSitemapXml: () => minimalSitemapXml,
|
|
26
|
+
renderSitemapXml: () => renderSitemapXml
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(index_exports);
|
|
29
|
+
|
|
30
|
+
// src/errors.ts
|
|
31
|
+
var BiabAccessRejectedError = class extends Error {
|
|
32
|
+
reason;
|
|
33
|
+
upgradeUrl;
|
|
34
|
+
featureMessage;
|
|
35
|
+
path;
|
|
36
|
+
status;
|
|
37
|
+
constructor(input) {
|
|
38
|
+
super(input.body.message);
|
|
39
|
+
this.name = "BiabAccessRejectedError";
|
|
40
|
+
this.reason = input.body.reason;
|
|
41
|
+
this.upgradeUrl = input.body.upgradeUrl;
|
|
42
|
+
this.featureMessage = input.body.message;
|
|
43
|
+
this.path = input.path;
|
|
44
|
+
this.status = input.status;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// src/reserved-paths.ts
|
|
49
|
+
var RESERVED_PAGE_PATHS = [
|
|
50
|
+
// Quote accept (public review/accept page from emailed quotes)
|
|
51
|
+
"quotes",
|
|
52
|
+
"quotes/accept",
|
|
53
|
+
// Contract signing (public signing page from emailed contracts)
|
|
54
|
+
"contracts",
|
|
55
|
+
"contracts/sign",
|
|
56
|
+
// Invoice payment (reserved for the upcoming public pay flow)
|
|
57
|
+
"invoices",
|
|
58
|
+
"invoices/pay",
|
|
59
|
+
// Customer portal (logged-in customer-facing surface)
|
|
60
|
+
"portal"
|
|
61
|
+
];
|
|
62
|
+
function normalize(input) {
|
|
63
|
+
return input.trim().toLowerCase().replace(/^\/+|\/+$/g, "").replace(/\/index$/, "");
|
|
64
|
+
}
|
|
65
|
+
function isReservedPagePath(input) {
|
|
66
|
+
const norm = normalize(input);
|
|
67
|
+
if (!norm) return false;
|
|
68
|
+
return RESERVED_PAGE_PATHS.some(
|
|
69
|
+
(reserved) => norm === reserved || norm.startsWith(`${reserved}/`)
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// src/sitemap-core/index.ts
|
|
74
|
+
function joinUrl(baseUrl, path) {
|
|
75
|
+
const base = baseUrl.replace(/\/+$/, "");
|
|
76
|
+
const suffix = path.startsWith("/") ? path : `/${path}`;
|
|
77
|
+
return `${base}${suffix === "/" ? "/" : suffix.replace(/\/+$/, "")}`;
|
|
78
|
+
}
|
|
79
|
+
function escapeXml(value) {
|
|
80
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
81
|
+
}
|
|
82
|
+
function isExpectedAbsence(cause) {
|
|
83
|
+
return cause instanceof BiabAccessRejectedError;
|
|
84
|
+
}
|
|
85
|
+
async function collectSitemapEntries(options) {
|
|
86
|
+
const { client, baseUrl, routes = {} } = options;
|
|
87
|
+
const seen = /* @__PURE__ */ new Map();
|
|
88
|
+
function add(path, lastmod) {
|
|
89
|
+
if (isReservedPagePath(path)) return;
|
|
90
|
+
const loc = joinUrl(baseUrl, path);
|
|
91
|
+
if (seen.has(loc)) return;
|
|
92
|
+
seen.set(loc, lastmod ? { loc, lastmod } : { loc });
|
|
93
|
+
}
|
|
94
|
+
for (const path of options.staticPaths ?? []) add(path);
|
|
95
|
+
try {
|
|
96
|
+
const { entries } = await client.site(options.siteId).sitemapEntries();
|
|
97
|
+
for (const entry of entries) {
|
|
98
|
+
const path = entry.loc.replace(/^https?:\/\/[^/]+/, "");
|
|
99
|
+
add(path || "/", entry.lastmod);
|
|
100
|
+
}
|
|
101
|
+
} catch (cause) {
|
|
102
|
+
options.onSkip?.(
|
|
103
|
+
"platform",
|
|
104
|
+
isExpectedAbsence(cause) ? "org is not entitled to programmatic pages" : "platform sitemap was unreachable"
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
if (routes.blog) {
|
|
108
|
+
try {
|
|
109
|
+
const { posts } = await client.blog.listPosts({
|
|
110
|
+
limit: options.blogLimit ?? 1e3
|
|
111
|
+
});
|
|
112
|
+
for (const post of posts) {
|
|
113
|
+
add(`${routes.blog}/${post.slug}`, post.updatedAt ?? null);
|
|
114
|
+
}
|
|
115
|
+
} catch (cause) {
|
|
116
|
+
options.onSkip?.(
|
|
117
|
+
"blog",
|
|
118
|
+
isExpectedAbsence(cause) ? "org has no blog.public entitlement" : "blog posts were unreachable"
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
} else {
|
|
122
|
+
options.onSkip?.("blog", "no routes.blog declared");
|
|
123
|
+
}
|
|
124
|
+
if (routes.product) {
|
|
125
|
+
try {
|
|
126
|
+
const { products } = await client.storefront.listProducts({
|
|
127
|
+
limit: options.productLimit ?? 1e3
|
|
128
|
+
});
|
|
129
|
+
for (const product of products) {
|
|
130
|
+
add(`${routes.product}/${product.id}`, product.updatedAt ?? null);
|
|
131
|
+
}
|
|
132
|
+
} catch (cause) {
|
|
133
|
+
options.onSkip?.(
|
|
134
|
+
"products",
|
|
135
|
+
isExpectedAbsence(cause) ? "org has no ecommerce.storefront entitlement" : "products were unreachable"
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
options.onSkip?.("products", "no routes.product declared");
|
|
140
|
+
}
|
|
141
|
+
return [...seen.values()];
|
|
142
|
+
}
|
|
143
|
+
function renderSitemapXml(entries) {
|
|
144
|
+
const body = entries.map((entry) => {
|
|
145
|
+
const lastmod = entry.lastmod ? `
|
|
146
|
+
<lastmod>${escapeXml(entry.lastmod)}</lastmod>` : "";
|
|
147
|
+
return ` <url>
|
|
148
|
+
<loc>${escapeXml(entry.loc)}</loc>${lastmod}
|
|
149
|
+
</url>`;
|
|
150
|
+
}).join("\n");
|
|
151
|
+
return '<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n' + (body ? `${body}
|
|
152
|
+
` : "") + "</urlset>\n";
|
|
153
|
+
}
|
|
154
|
+
async function buildSitemap(options) {
|
|
155
|
+
const entries = await collectSitemapEntries(options);
|
|
156
|
+
return renderSitemapXml(entries);
|
|
157
|
+
}
|
|
158
|
+
function minimalSitemapXml(baseUrl) {
|
|
159
|
+
return renderSitemapXml([{ loc: joinUrl(baseUrl, "/") }]);
|
|
160
|
+
}
|
|
161
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
162
|
+
0 && (module.exports = {
|
|
163
|
+
buildSitemap,
|
|
164
|
+
collectSitemapEntries,
|
|
165
|
+
minimalSitemapXml,
|
|
166
|
+
renderSitemapXml
|
|
167
|
+
});
|