@sonordev/site-kit 1.2.7
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 +376 -0
- package/dist/SetupWizard-Cki06kB0.d.mts +12 -0
- package/dist/SetupWizard-Cki06kB0.d.ts +12 -0
- package/dist/analytics/index.d.mts +93 -0
- package/dist/analytics/index.d.ts +93 -0
- package/dist/analytics/index.js +89 -0
- package/dist/analytics/index.js.map +1 -0
- package/dist/analytics/index.mjs +71 -0
- package/dist/analytics/index.mjs.map +1 -0
- package/dist/api-CWtoFJCO.d.mts +137 -0
- package/dist/api-CWtoFJCO.d.ts +137 -0
- package/dist/blog/index.d.mts +305 -0
- package/dist/blog/index.d.ts +305 -0
- package/dist/blog/index.js +1578 -0
- package/dist/blog/index.js.map +1 -0
- package/dist/blog/index.mjs +1562 -0
- package/dist/blog/index.mjs.map +1 -0
- package/dist/blog/server.d.mts +229 -0
- package/dist/blog/server.d.ts +229 -0
- package/dist/blog/server.js +692 -0
- package/dist/blog/server.js.map +1 -0
- package/dist/blog/server.mjs +666 -0
- package/dist/blog/server.mjs.map +1 -0
- package/dist/chunk-24277A3Q.mjs +968 -0
- package/dist/chunk-24277A3Q.mjs.map +1 -0
- package/dist/chunk-373TK6TZ.js +321 -0
- package/dist/chunk-373TK6TZ.js.map +1 -0
- package/dist/chunk-3MYZS6PD.js +30 -0
- package/dist/chunk-3MYZS6PD.js.map +1 -0
- package/dist/chunk-43GBM4SX.js +283 -0
- package/dist/chunk-43GBM4SX.js.map +1 -0
- package/dist/chunk-4XPGGLVP.mjs +53 -0
- package/dist/chunk-4XPGGLVP.mjs.map +1 -0
- package/dist/chunk-622GAQP5.js +2008 -0
- package/dist/chunk-622GAQP5.js.map +1 -0
- package/dist/chunk-6BIPAKL4.mjs +28 -0
- package/dist/chunk-6BIPAKL4.mjs.map +1 -0
- package/dist/chunk-6ZCISNAB.mjs +343 -0
- package/dist/chunk-6ZCISNAB.mjs.map +1 -0
- package/dist/chunk-72MQFHYJ.js +1429 -0
- package/dist/chunk-72MQFHYJ.js.map +1 -0
- package/dist/chunk-7557OTHW.js +62 -0
- package/dist/chunk-7557OTHW.js.map +1 -0
- package/dist/chunk-7FUV73JZ.js +981 -0
- package/dist/chunk-7FUV73JZ.js.map +1 -0
- package/dist/chunk-7RF6PVHA.mjs +324 -0
- package/dist/chunk-7RF6PVHA.mjs.map +1 -0
- package/dist/chunk-7RYCHO6D.mjs +134 -0
- package/dist/chunk-7RYCHO6D.mjs.map +1 -0
- package/dist/chunk-7UKPRW25.mjs +1999 -0
- package/dist/chunk-7UKPRW25.mjs.map +1 -0
- package/dist/chunk-7URAOG2M.js +14864 -0
- package/dist/chunk-7URAOG2M.js.map +1 -0
- package/dist/chunk-AFAO3TGS.mjs +810 -0
- package/dist/chunk-AFAO3TGS.mjs.map +1 -0
- package/dist/chunk-BYLIU6XG.js +343 -0
- package/dist/chunk-BYLIU6XG.js.map +1 -0
- package/dist/chunk-D63MUKZ6.mjs +4423 -0
- package/dist/chunk-D63MUKZ6.mjs.map +1 -0
- package/dist/chunk-DDKW2FNA.js +390 -0
- package/dist/chunk-DDKW2FNA.js.map +1 -0
- package/dist/chunk-DQYMKR27.mjs +341 -0
- package/dist/chunk-DQYMKR27.mjs.map +1 -0
- package/dist/chunk-DW5UJKHH.js +221 -0
- package/dist/chunk-DW5UJKHH.js.map +1 -0
- package/dist/chunk-EEZCR6E6.js +50 -0
- package/dist/chunk-EEZCR6E6.js.map +1 -0
- package/dist/chunk-GCJXQ4AG.mjs +59 -0
- package/dist/chunk-GCJXQ4AG.mjs.map +1 -0
- package/dist/chunk-JGNQK2G6.mjs +14845 -0
- package/dist/chunk-JGNQK2G6.mjs.map +1 -0
- package/dist/chunk-JTLOJLWQ.mjs +563 -0
- package/dist/chunk-JTLOJLWQ.mjs.map +1 -0
- package/dist/chunk-K23A4G76.mjs +202 -0
- package/dist/chunk-K23A4G76.mjs.map +1 -0
- package/dist/chunk-KKU3K7RG.js +336 -0
- package/dist/chunk-KKU3K7RG.js.map +1 -0
- package/dist/chunk-KUGMH4ZF.js +571 -0
- package/dist/chunk-KUGMH4ZF.js.map +1 -0
- package/dist/chunk-LBVWVP72.js +110 -0
- package/dist/chunk-LBVWVP72.js.map +1 -0
- package/dist/chunk-LIVWLY2P.js +138 -0
- package/dist/chunk-LIVWLY2P.js.map +1 -0
- package/dist/chunk-M2T6R7BA.mjs +1003 -0
- package/dist/chunk-M2T6R7BA.mjs.map +1 -0
- package/dist/chunk-MV3QN7PW.mjs +47 -0
- package/dist/chunk-MV3QN7PW.mjs.map +1 -0
- package/dist/chunk-OB7E654K.js +72 -0
- package/dist/chunk-OB7E654K.js.map +1 -0
- package/dist/chunk-OIIKTGRL.mjs +380 -0
- package/dist/chunk-OIIKTGRL.mjs.map +1 -0
- package/dist/chunk-P3UWIUJS.mjs +1427 -0
- package/dist/chunk-P3UWIUJS.mjs.map +1 -0
- package/dist/chunk-PKN27UMH.mjs +136 -0
- package/dist/chunk-PKN27UMH.mjs.map +1 -0
- package/dist/chunk-QXV4667R.mjs +105 -0
- package/dist/chunk-QXV4667R.mjs.map +1 -0
- package/dist/chunk-S7FRYNSU.mjs +315 -0
- package/dist/chunk-S7FRYNSU.mjs.map +1 -0
- package/dist/chunk-TFLQX7K7.mjs +68 -0
- package/dist/chunk-TFLQX7K7.mjs.map +1 -0
- package/dist/chunk-UWE5PCYJ.mjs +279 -0
- package/dist/chunk-UWE5PCYJ.mjs.map +1 -0
- package/dist/chunk-UYFDNX2F.js +4469 -0
- package/dist/chunk-UYFDNX2F.js.map +1 -0
- package/dist/chunk-W4PALSGM.js +350 -0
- package/dist/chunk-W4PALSGM.js.map +1 -0
- package/dist/chunk-WECQ6KOB.js +1008 -0
- package/dist/chunk-WECQ6KOB.js.map +1 -0
- package/dist/chunk-XQQWI6WB.js +814 -0
- package/dist/chunk-XQQWI6WB.js.map +1 -0
- package/dist/chunk-XZJOZJB6.js +140 -0
- package/dist/chunk-XZJOZJB6.js.map +1 -0
- package/dist/chunk-ZSMWDLMK.js +63 -0
- package/dist/chunk-ZSMWDLMK.js.map +1 -0
- package/dist/cli/index.js +37243 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/index.mjs +37209 -0
- package/dist/cli/index.mjs.map +1 -0
- package/dist/commerce/index.d.mts +170 -0
- package/dist/commerce/index.d.ts +170 -0
- package/dist/commerce/index.js +174 -0
- package/dist/commerce/index.js.map +1 -0
- package/dist/commerce/index.mjs +5 -0
- package/dist/commerce/index.mjs.map +1 -0
- package/dist/commerce/server.d.mts +107 -0
- package/dist/commerce/server.d.ts +107 -0
- package/dist/commerce/server.js +187 -0
- package/dist/commerce/server.js.map +1 -0
- package/dist/commerce/server.mjs +177 -0
- package/dist/commerce/server.mjs.map +1 -0
- package/dist/config/index.d.mts +43 -0
- package/dist/config/index.d.ts +43 -0
- package/dist/config/index.js +66 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/index.mjs +64 -0
- package/dist/config/index.mjs.map +1 -0
- package/dist/engage/index.d.mts +33 -0
- package/dist/engage/index.d.ts +33 -0
- package/dist/engage/index.js +22 -0
- package/dist/engage/index.js.map +1 -0
- package/dist/engage/index.mjs +5 -0
- package/dist/engage/index.mjs.map +1 -0
- package/dist/forms/index.d.mts +437 -0
- package/dist/forms/index.d.ts +437 -0
- package/dist/forms/index.js +1168 -0
- package/dist/forms/index.js.map +1 -0
- package/dist/forms/index.mjs +1142 -0
- package/dist/forms/index.mjs.map +1 -0
- package/dist/generators-2XKQMPKH.mjs +4 -0
- package/dist/generators-2XKQMPKH.mjs.map +1 -0
- package/dist/generators-DTMO36DV.js +33 -0
- package/dist/generators-DTMO36DV.js.map +1 -0
- package/dist/images/index.d.mts +4 -0
- package/dist/images/index.d.ts +4 -0
- package/dist/images/index.js +46 -0
- package/dist/images/index.js.map +1 -0
- package/dist/images/index.mjs +5 -0
- package/dist/images/index.mjs.map +1 -0
- package/dist/images/server.d.mts +69 -0
- package/dist/images/server.d.ts +69 -0
- package/dist/images/server.js +21 -0
- package/dist/images/server.js.map +1 -0
- package/dist/images/server.mjs +4 -0
- package/dist/images/server.mjs.map +1 -0
- package/dist/index.d.mts +846 -0
- package/dist/index.d.ts +846 -0
- package/dist/index.js +2623 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2416 -0
- package/dist/index.mjs.map +1 -0
- package/dist/layout/index.d.mts +53 -0
- package/dist/layout/index.d.ts +53 -0
- package/dist/layout/index.js +187 -0
- package/dist/layout/index.js.map +1 -0
- package/dist/layout/index.mjs +185 -0
- package/dist/layout/index.mjs.map +1 -0
- package/dist/llms/index.d.mts +448 -0
- package/dist/llms/index.d.ts +448 -0
- package/dist/llms/index.js +581 -0
- package/dist/llms/index.js.map +1 -0
- package/dist/llms/index.mjs +529 -0
- package/dist/llms/index.mjs.map +1 -0
- package/dist/manifest/index.d.mts +62 -0
- package/dist/manifest/index.d.ts +62 -0
- package/dist/manifest/index.js +85 -0
- package/dist/manifest/index.js.map +1 -0
- package/dist/manifest/index.mjs +83 -0
- package/dist/manifest/index.mjs.map +1 -0
- package/dist/middleware/index.d.mts +63 -0
- package/dist/middleware/index.d.ts +63 -0
- package/dist/middleware/index.js +54 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/index.mjs +51 -0
- package/dist/middleware/index.mjs.map +1 -0
- package/dist/migrator-2MQHOFDQ.mjs +4 -0
- package/dist/migrator-2MQHOFDQ.mjs.map +1 -0
- package/dist/migrator-THJCF6MZ.js +37 -0
- package/dist/migrator-THJCF6MZ.js.map +1 -0
- package/dist/redirects/index.d.mts +78 -0
- package/dist/redirects/index.d.ts +78 -0
- package/dist/redirects/index.js +26 -0
- package/dist/redirects/index.js.map +1 -0
- package/dist/redirects/index.mjs +5 -0
- package/dist/redirects/index.mjs.map +1 -0
- package/dist/reputation/index.d.mts +57 -0
- package/dist/reputation/index.d.ts +57 -0
- package/dist/reputation/index.js +21 -0
- package/dist/reputation/index.js.map +1 -0
- package/dist/reputation/index.mjs +4 -0
- package/dist/reputation/index.mjs.map +1 -0
- package/dist/robots/index.d.mts +38 -0
- package/dist/robots/index.d.ts +38 -0
- package/dist/robots/index.js +52 -0
- package/dist/robots/index.js.map +1 -0
- package/dist/robots/index.mjs +50 -0
- package/dist/robots/index.mjs.map +1 -0
- package/dist/routing-B5XS-6_W.d.mts +118 -0
- package/dist/routing-DZYzyDHw.d.ts +118 -0
- package/dist/scanner-GAF5PO5F.js +53 -0
- package/dist/scanner-GAF5PO5F.js.map +1 -0
- package/dist/scanner-LKJKW7IT.mjs +4 -0
- package/dist/scanner-LKJKW7IT.mjs.map +1 -0
- package/dist/securityHeaders-nwZ6nP4g.d.mts +24 -0
- package/dist/securityHeaders-nwZ6nP4g.d.ts +24 -0
- package/dist/seo/index.d.mts +600 -0
- package/dist/seo/index.d.ts +600 -0
- package/dist/seo/index.js +883 -0
- package/dist/seo/index.js.map +1 -0
- package/dist/seo/index.mjs +773 -0
- package/dist/seo/index.mjs.map +1 -0
- package/dist/seo/register-sitemap-cli.js +151 -0
- package/dist/seo/register-sitemap-cli.js.map +1 -0
- package/dist/seo/register-sitemap-cli.mjs +144 -0
- package/dist/seo/register-sitemap-cli.mjs.map +1 -0
- package/dist/seo/server.d.mts +107 -0
- package/dist/seo/server.d.ts +107 -0
- package/dist/seo/server.js +207 -0
- package/dist/seo/server.js.map +1 -0
- package/dist/seo/server.mjs +186 -0
- package/dist/seo/server.mjs.map +1 -0
- package/dist/server-api-EWXKOQZA.mjs +4 -0
- package/dist/server-api-EWXKOQZA.mjs.map +1 -0
- package/dist/server-api-GJPNRYUP.js +81 -0
- package/dist/server-api-GJPNRYUP.js.map +1 -0
- package/dist/setup/client.d.mts +60 -0
- package/dist/setup/client.d.ts +60 -0
- package/dist/setup/client.js +31 -0
- package/dist/setup/client.js.map +1 -0
- package/dist/setup/client.mjs +6 -0
- package/dist/setup/client.mjs.map +1 -0
- package/dist/setup/index.d.mts +5 -0
- package/dist/setup/index.d.ts +5 -0
- package/dist/setup/index.js +35 -0
- package/dist/setup/index.js.map +1 -0
- package/dist/setup/index.mjs +6 -0
- package/dist/setup/index.mjs.map +1 -0
- package/dist/setup/server.d.mts +14 -0
- package/dist/setup/server.d.ts +14 -0
- package/dist/setup/server.js +13 -0
- package/dist/setup/server.js.map +1 -0
- package/dist/setup/server.mjs +4 -0
- package/dist/setup/server.mjs.map +1 -0
- package/dist/site-config/index.d.mts +24 -0
- package/dist/site-config/index.d.ts +24 -0
- package/dist/site-config/index.js +17 -0
- package/dist/site-config/index.js.map +1 -0
- package/dist/site-config/index.mjs +4 -0
- package/dist/site-config/index.mjs.map +1 -0
- package/dist/sitemap/index.d.mts +96 -0
- package/dist/sitemap/index.d.ts +96 -0
- package/dist/sitemap/index.js +288 -0
- package/dist/sitemap/index.js.map +1 -0
- package/dist/sitemap/index.mjs +285 -0
- package/dist/sitemap/index.mjs.map +1 -0
- package/dist/socket-loader-J26QHHOB.js +16 -0
- package/dist/socket-loader-J26QHHOB.js.map +1 -0
- package/dist/socket-loader-R7S2YJ2J.mjs +14 -0
- package/dist/socket-loader-R7S2YJ2J.mjs.map +1 -0
- package/dist/types-0dmq3k20.d.mts +168 -0
- package/dist/types-0dmq3k20.d.ts +168 -0
- package/dist/types-Blb2QNkV.d.mts +263 -0
- package/dist/types-Blb2QNkV.d.ts +263 -0
- package/dist/types-BnCwwUX3.d.mts +250 -0
- package/dist/types-BnCwwUX3.d.ts +250 -0
- package/dist/types-CGlnp43R.d.mts +312 -0
- package/dist/types-CGlnp43R.d.ts +312 -0
- package/dist/types-D08004rU.d.mts +179 -0
- package/dist/types-D08004rU.d.ts +179 -0
- package/dist/types-DNSYU7qI.d.mts +127 -0
- package/dist/types-DNSYU7qI.d.ts +127 -0
- package/dist/types-KZP_VWZp.d.mts +266 -0
- package/dist/types-KZP_VWZp.d.ts +266 -0
- package/dist/useEventModal-BVTx69XE.d.mts +274 -0
- package/dist/useEventModal-Dx1dItTJ.d.ts +274 -0
- package/dist/web-vitals-444RLW3B.js +252 -0
- package/dist/web-vitals-444RLW3B.js.map +1 -0
- package/dist/web-vitals-KPICZIEF.mjs +241 -0
- package/dist/web-vitals-KPICZIEF.mjs.map +1 -0
- package/package.json +192 -0
package/README.md
ADDED
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
# @sonordev/site-kit
|
|
2
|
+
|
|
3
|
+
Complete client-side integration kit for Sonor. One package for SEO, Analytics, Engage widgets, Forms, and Blog - all managed from your Sonor dashboard.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @sonordev/site-kit
|
|
9
|
+
# or
|
|
10
|
+
pnpm add @sonordev/site-kit
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
Wrap your app with `SiteKitProvider` in your root layout:
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
// app/layout.tsx
|
|
19
|
+
import { SiteKitProvider } from '@sonordev/site-kit'
|
|
20
|
+
|
|
21
|
+
export default function RootLayout({ children }) {
|
|
22
|
+
return (
|
|
23
|
+
<html>
|
|
24
|
+
<body>
|
|
25
|
+
<SiteKitProvider
|
|
26
|
+
projectId={process.env.UPTRADE_PROJECT_ID!}
|
|
27
|
+
supabaseUrl={process.env.NEXT_PUBLIC_SUPABASE_URL!}
|
|
28
|
+
supabaseAnonKey={process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!}
|
|
29
|
+
analytics={{ enabled: true }}
|
|
30
|
+
engage={{ enabled: true }}
|
|
31
|
+
>
|
|
32
|
+
{children}
|
|
33
|
+
</SiteKitProvider>
|
|
34
|
+
</body>
|
|
35
|
+
</html>
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Modules
|
|
41
|
+
|
|
42
|
+
### SEO (`@sonordev/site-kit/seo`)
|
|
43
|
+
|
|
44
|
+
Managed SEO components that automatically inject structured data, FAQs, internal links, and more based on your Portal configuration.
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
import { ManagedSchema, ManagedFAQ, ManagedInternalLinks } from '@sonordev/site-kit/seo'
|
|
48
|
+
import { getManagedMetadata, generateSitemap, generateRobots } from '@sonordev/site-kit/seo/server'
|
|
49
|
+
|
|
50
|
+
// In a page component
|
|
51
|
+
export async function generateMetadata({ params }) {
|
|
52
|
+
return getManagedMetadata('your-project-id', `/blog/${params.slug}`)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export default async function BlogPost({ params }) {
|
|
56
|
+
return (
|
|
57
|
+
<article>
|
|
58
|
+
<h1>My Blog Post</h1>
|
|
59
|
+
<p>Content...</p>
|
|
60
|
+
|
|
61
|
+
{/* Managed structured data */}
|
|
62
|
+
<ManagedSchema projectId="..." path="/blog/my-post" />
|
|
63
|
+
|
|
64
|
+
{/* Managed FAQ section */}
|
|
65
|
+
<ManagedFAQ projectId="..." path="/blog/my-post" />
|
|
66
|
+
|
|
67
|
+
{/* Managed internal links */}
|
|
68
|
+
<ManagedInternalLinks projectId="..." path="/blog/my-post" />
|
|
69
|
+
</article>
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Analytics (`@sonordev/site-kit/analytics`)
|
|
75
|
+
|
|
76
|
+
Automatic page view tracking, custom events, and Core Web Vitals reporting.
|
|
77
|
+
|
|
78
|
+
```tsx
|
|
79
|
+
import { useAnalytics, WebVitals } from '@sonordev/site-kit/analytics'
|
|
80
|
+
|
|
81
|
+
export default function MyComponent() {
|
|
82
|
+
const { trackEvent, trackConversion } = useAnalytics()
|
|
83
|
+
|
|
84
|
+
const handleClick = () => {
|
|
85
|
+
trackEvent('button_click', { button: 'cta' })
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const handlePurchase = () => {
|
|
89
|
+
trackConversion('purchase', 99.99)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<>
|
|
94
|
+
<button onClick={handleClick}>CTA Button</button>
|
|
95
|
+
<WebVitals /> {/* Reports LCP, CLS, FID, etc. */}
|
|
96
|
+
</>
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Engage (`@sonordev/site-kit/engage`)
|
|
102
|
+
|
|
103
|
+
Popups, nudges, banners, and chat widgets configured from Portal.
|
|
104
|
+
|
|
105
|
+
```tsx
|
|
106
|
+
import { EngageWidget, ChatWidget } from '@sonordev/site-kit/engage'
|
|
107
|
+
|
|
108
|
+
// Automatically included when engage.enabled = true in SiteKitProvider
|
|
109
|
+
// Or add manually:
|
|
110
|
+
|
|
111
|
+
export default function Layout({ children }) {
|
|
112
|
+
return (
|
|
113
|
+
<>
|
|
114
|
+
{children}
|
|
115
|
+
<EngageWidget projectId="..." />
|
|
116
|
+
<ChatWidget projectId="..." />
|
|
117
|
+
</>
|
|
118
|
+
)
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Forms (`@sonordev/site-kit/forms`)
|
|
123
|
+
|
|
124
|
+
Managed forms with automatic routing to CRM, Support, or other destinations.
|
|
125
|
+
|
|
126
|
+
```tsx
|
|
127
|
+
import { ManagedForm } from '@sonordev/site-kit/forms'
|
|
128
|
+
|
|
129
|
+
// Basic usage - fetches form config from Portal
|
|
130
|
+
export default function ContactPage() {
|
|
131
|
+
return (
|
|
132
|
+
<ManagedForm
|
|
133
|
+
projectId="..."
|
|
134
|
+
formSlug="contact-form"
|
|
135
|
+
onSuccess={(data) => console.log('Submitted:', data)}
|
|
136
|
+
/>
|
|
137
|
+
)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Custom rendering
|
|
141
|
+
export default function CustomContactPage() {
|
|
142
|
+
return (
|
|
143
|
+
<ManagedForm
|
|
144
|
+
projectId="..."
|
|
145
|
+
formSlug="contact-form"
|
|
146
|
+
render={({ fields, step, totalSteps, values, errors, handleSubmit, isSubmitting }) => (
|
|
147
|
+
<form onSubmit={handleSubmit}>
|
|
148
|
+
{fields.map(field => (
|
|
149
|
+
<CustomField key={field.slug} {...field} />
|
|
150
|
+
))}
|
|
151
|
+
<button disabled={isSubmitting}>Submit</button>
|
|
152
|
+
</form>
|
|
153
|
+
)}
|
|
154
|
+
/>
|
|
155
|
+
)
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Blog (`@sonordev/site-kit/blog`)
|
|
160
|
+
|
|
161
|
+
Complete Portal-managed blog system with beautiful layouts, dynamic routing, categories, and SEO.
|
|
162
|
+
|
|
163
|
+
**Create posts in Portal → Automatically appear on your site.**
|
|
164
|
+
|
|
165
|
+
```tsx
|
|
166
|
+
// app/blog/page.tsx - Blog Index
|
|
167
|
+
import { BlogList, BlogLayout } from '@sonordev/site-kit/blog'
|
|
168
|
+
import { generateBlogIndexMetadata } from '@sonordev/site-kit/blog/server'
|
|
169
|
+
|
|
170
|
+
export const metadata = generateBlogIndexMetadata({
|
|
171
|
+
title: 'Blog',
|
|
172
|
+
siteName: 'My Company',
|
|
173
|
+
siteUrl: 'https://example.com',
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
export default function BlogPage({ searchParams }) {
|
|
177
|
+
return (
|
|
178
|
+
<BlogLayout
|
|
179
|
+
hero={{ title: 'Blog', subtitle: 'Latest insights and articles' }}
|
|
180
|
+
layout="sidebar-right"
|
|
181
|
+
>
|
|
182
|
+
<BlogList
|
|
183
|
+
category={searchParams.category}
|
|
184
|
+
page={parseInt(searchParams.page || '1')}
|
|
185
|
+
showCategoryFilter
|
|
186
|
+
showPagination
|
|
187
|
+
/>
|
|
188
|
+
</BlogLayout>
|
|
189
|
+
)
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
```tsx
|
|
194
|
+
// app/blog/[slug]/page.tsx - Individual Post
|
|
195
|
+
import { BlogPost } from '@sonordev/site-kit/blog'
|
|
196
|
+
import {
|
|
197
|
+
generateBlogPostMetadata,
|
|
198
|
+
generateBlogStaticParams,
|
|
199
|
+
getBlogPost,
|
|
200
|
+
generateBlogPostSchema
|
|
201
|
+
} from '@sonordev/site-kit/blog/server'
|
|
202
|
+
|
|
203
|
+
// Pre-generate all post pages at build time
|
|
204
|
+
export const generateStaticParams = generateBlogStaticParams
|
|
205
|
+
|
|
206
|
+
// Dynamic metadata for SEO
|
|
207
|
+
export async function generateMetadata({ params }) {
|
|
208
|
+
return generateBlogPostMetadata(params.slug, {
|
|
209
|
+
siteName: 'My Company',
|
|
210
|
+
siteUrl: 'https://example.com',
|
|
211
|
+
})
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export default async function PostPage({ params }) {
|
|
215
|
+
const post = await getBlogPost(params.slug)
|
|
216
|
+
|
|
217
|
+
return (
|
|
218
|
+
<>
|
|
219
|
+
{/* JSON-LD Schema */}
|
|
220
|
+
<script
|
|
221
|
+
type="application/ld+json"
|
|
222
|
+
dangerouslySetInnerHTML={{
|
|
223
|
+
__html: JSON.stringify(generateBlogPostSchema(post, {
|
|
224
|
+
siteUrl: 'https://example.com',
|
|
225
|
+
siteName: 'My Company',
|
|
226
|
+
})),
|
|
227
|
+
}}
|
|
228
|
+
/>
|
|
229
|
+
|
|
230
|
+
{/* Blog Post with TOC and Related Posts */}
|
|
231
|
+
<BlogPost
|
|
232
|
+
slug={params.slug}
|
|
233
|
+
showToc
|
|
234
|
+
showRelated
|
|
235
|
+
showAuthor
|
|
236
|
+
/>
|
|
237
|
+
</>
|
|
238
|
+
)
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
#### Available Components
|
|
243
|
+
|
|
244
|
+
| Component | Purpose |
|
|
245
|
+
|-----------|---------|
|
|
246
|
+
| `BlogList` | Grid of posts with pagination & category filter |
|
|
247
|
+
| `BlogPost` | Full post with TOC, author, related posts |
|
|
248
|
+
| `BlogLayout` | Complete layout with sidebar |
|
|
249
|
+
| `BlogSidebar` | Categories, recent posts, tags, search |
|
|
250
|
+
| `TableOfContents` | Sticky TOC from headings |
|
|
251
|
+
| `AuthorCard` | Author info with social links |
|
|
252
|
+
| `RelatedPosts` | Related posts by category |
|
|
253
|
+
|
|
254
|
+
#### Server Functions
|
|
255
|
+
|
|
256
|
+
```tsx
|
|
257
|
+
import {
|
|
258
|
+
getBlogPost, // Fetch single post
|
|
259
|
+
getAllBlogSlugs, // For generateStaticParams
|
|
260
|
+
getBlogCategories, // All categories
|
|
261
|
+
generateBlogPostMetadata, // Post page metadata
|
|
262
|
+
generateBlogIndexMetadata, // Index page metadata
|
|
263
|
+
generateBlogStaticParams, // SSG params
|
|
264
|
+
generateBlogSitemap, // Sitemap entries
|
|
265
|
+
generateBlogPostSchema, // JSON-LD
|
|
266
|
+
} from '@sonordev/site-kit/blog/server'
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## Configuration
|
|
270
|
+
|
|
271
|
+
### Full Provider Options
|
|
272
|
+
|
|
273
|
+
```tsx
|
|
274
|
+
<SiteKitProvider
|
|
275
|
+
// Required
|
|
276
|
+
projectId="your-project-id"
|
|
277
|
+
supabaseUrl="https://xxx.supabase.co"
|
|
278
|
+
supabaseAnonKey="your-anon-key"
|
|
279
|
+
|
|
280
|
+
// Analytics options
|
|
281
|
+
analytics={{
|
|
282
|
+
enabled: true,
|
|
283
|
+
trackPageViews: true, // Auto-track route changes
|
|
284
|
+
trackWebVitals: true, // Report Core Web Vitals
|
|
285
|
+
trackScrollDepth: false, // Track scroll milestones
|
|
286
|
+
sessionDuration: 30, // Session timeout in minutes
|
|
287
|
+
excludePaths: ['/admin'] // Don't track these paths
|
|
288
|
+
}}
|
|
289
|
+
|
|
290
|
+
// Engage widget options
|
|
291
|
+
engage={{
|
|
292
|
+
enabled: true,
|
|
293
|
+
position: 'bottom-right', // Widget position
|
|
294
|
+
zIndex: 9999,
|
|
295
|
+
chatEnabled: true // Enable AI/live chat
|
|
296
|
+
}}
|
|
297
|
+
|
|
298
|
+
// Forms options
|
|
299
|
+
forms={{
|
|
300
|
+
enabled: true,
|
|
301
|
+
honeypotField: '_hp' // Spam protection field name
|
|
302
|
+
}}
|
|
303
|
+
|
|
304
|
+
// Debug mode - logs to console
|
|
305
|
+
debug={false}
|
|
306
|
+
>
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## Environment Variables
|
|
310
|
+
|
|
311
|
+
```bash
|
|
312
|
+
# Required
|
|
313
|
+
UPTRADE_PROJECT_ID=your-project-id
|
|
314
|
+
NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co
|
|
315
|
+
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
## Server-Side Utilities
|
|
319
|
+
|
|
320
|
+
```tsx
|
|
321
|
+
// app/sitemap.ts
|
|
322
|
+
import { generateSitemap } from '@sonordev/site-kit/seo/server'
|
|
323
|
+
|
|
324
|
+
export default async function sitemap() {
|
|
325
|
+
return generateSitemap('your-project-id', 'https://yoursite.com')
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// app/robots.ts
|
|
329
|
+
import { generateRobots } from '@sonordev/site-kit/seo/server'
|
|
330
|
+
|
|
331
|
+
export default async function robots() {
|
|
332
|
+
return generateRobots('your-project-id', 'https://yoursite.com')
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Redirect handling in middleware
|
|
336
|
+
import { handleRedirect } from '@sonordev/site-kit/seo/server'
|
|
337
|
+
|
|
338
|
+
export async function middleware(request) {
|
|
339
|
+
const redirect = await handleRedirect('your-project-id', request.nextUrl.pathname)
|
|
340
|
+
if (redirect) {
|
|
341
|
+
return NextResponse.redirect(new URL(redirect.to, request.url), redirect.statusCode)
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
## Form Routing
|
|
347
|
+
|
|
348
|
+
Forms automatically route submissions based on their type:
|
|
349
|
+
|
|
350
|
+
| Form Type | Routes To | Use Case |
|
|
351
|
+
|-----------|-----------|----------|
|
|
352
|
+
| `prospect` | CRM Leads | Sales inquiries, quote requests |
|
|
353
|
+
| `support` | Support Tickets | Help requests, bug reports |
|
|
354
|
+
| `feedback` | Feedback Entries | User feedback, suggestions |
|
|
355
|
+
| `newsletter` | Email Subscribers | Newsletter signups |
|
|
356
|
+
| `contact` | Form Submissions | General contact (no routing) |
|
|
357
|
+
| `custom` | Form Submissions | Custom handling |
|
|
358
|
+
|
|
359
|
+
## TypeScript
|
|
360
|
+
|
|
361
|
+
All modules are fully typed:
|
|
362
|
+
|
|
363
|
+
```tsx
|
|
364
|
+
import type {
|
|
365
|
+
SiteKitConfig,
|
|
366
|
+
ManagedMetadata,
|
|
367
|
+
AnalyticsEvent,
|
|
368
|
+
EngageElement,
|
|
369
|
+
ManagedFormConfig,
|
|
370
|
+
BlogPostType
|
|
371
|
+
} from '@sonordev/site-kit'
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
## License
|
|
375
|
+
|
|
376
|
+
MIT
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
interface SetupWizardProps {
|
|
4
|
+
config?: {
|
|
5
|
+
url?: string;
|
|
6
|
+
anonKey?: string;
|
|
7
|
+
portalApiUrl?: string;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
declare function SetupWizard({ config }?: SetupWizardProps): react_jsx_runtime.JSX.Element;
|
|
11
|
+
|
|
12
|
+
export { SetupWizard as S };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
interface SetupWizardProps {
|
|
4
|
+
config?: {
|
|
5
|
+
url?: string;
|
|
6
|
+
anonKey?: string;
|
|
7
|
+
portalApiUrl?: string;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
declare function SetupWizard({ config }?: SetupWizardProps): react_jsx_runtime.JSX.Element;
|
|
11
|
+
|
|
12
|
+
export { SetupWizard as S };
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import React__default from 'react';
|
|
3
|
+
import { A as AnalyticsContextValue, T as TrackEventOptions, a as TrackConversionOptions } from '../types-DNSYU7qI.mjs';
|
|
4
|
+
export { c as AnalyticsConfig, b as AnalyticsEvent, C as Conversion, P as PageView, S as Session, W as WebVitalsData } from '../types-DNSYU7qI.mjs';
|
|
5
|
+
|
|
6
|
+
interface AnalyticsProviderProps {
|
|
7
|
+
children: React__default.ReactNode;
|
|
8
|
+
apiUrl?: string;
|
|
9
|
+
apiKey?: string;
|
|
10
|
+
trackPageViews?: boolean;
|
|
11
|
+
trackWebVitals?: boolean;
|
|
12
|
+
trackScrollDepth?: boolean;
|
|
13
|
+
trackClicks?: boolean;
|
|
14
|
+
trackJourneys?: boolean;
|
|
15
|
+
sessionTimeout?: number;
|
|
16
|
+
excludePaths?: string[];
|
|
17
|
+
validateAgainstSitemap?: boolean;
|
|
18
|
+
debug?: boolean;
|
|
19
|
+
/** External visitor ID from shared identity (used by SiteKitLayout) */
|
|
20
|
+
externalVisitorId?: string;
|
|
21
|
+
/** External session ID from shared identity (used by SiteKitLayout) */
|
|
22
|
+
externalSessionId?: string;
|
|
23
|
+
/** Callback invoked with page metadata after each page view (used by Signal bridge) */
|
|
24
|
+
onPageMetadata?: (metadata: Record<string, unknown>) => void;
|
|
25
|
+
}
|
|
26
|
+
declare function AnalyticsProvider({ children, apiUrl: propApiUrl, apiKey: propApiKey, trackPageViews, trackWebVitals, trackScrollDepth, trackClicks, trackJourneys, // NEW: Enable journey tracking by default
|
|
27
|
+
sessionTimeout, excludePaths, validateAgainstSitemap, debug, externalVisitorId, externalSessionId, onPageMetadata, }: AnalyticsProviderProps): react_jsx_runtime.JSX.Element;
|
|
28
|
+
declare function useAnalytics(): AnalyticsContextValue;
|
|
29
|
+
declare function useTrackEvent(): {
|
|
30
|
+
trackEvent: (options: TrackEventOptions) => void;
|
|
31
|
+
trackConversion: (options: TrackConversionOptions) => void;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @sonordev/site-kit/analytics - Web Vitals Component
|
|
36
|
+
*
|
|
37
|
+
* Automatically reports Core Web Vitals via Portal API
|
|
38
|
+
*/
|
|
39
|
+
interface WebVitalsProps {
|
|
40
|
+
apiUrl?: string;
|
|
41
|
+
apiKey?: string;
|
|
42
|
+
debug?: boolean;
|
|
43
|
+
}
|
|
44
|
+
declare function WebVitals({ apiUrl: propApiUrl, apiKey: propApiKey, debug }: WebVitalsProps): null;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @sonordev/site-kit/analytics - Contact Tracking Hook
|
|
48
|
+
*
|
|
49
|
+
* Tracks phone calls and email clicks as conversions.
|
|
50
|
+
* Use this hook to automatically track tel: and mailto: links,
|
|
51
|
+
* or manually track contact interactions.
|
|
52
|
+
*/
|
|
53
|
+
interface UseContactTrackingOptions {
|
|
54
|
+
/** Automatically track all tel: and mailto: links (default: true) */
|
|
55
|
+
autoTrack?: boolean;
|
|
56
|
+
/** Debug mode - logs events to console */
|
|
57
|
+
debug?: boolean;
|
|
58
|
+
}
|
|
59
|
+
interface ContactTrackingReturn {
|
|
60
|
+
/** Manually track a phone call click */
|
|
61
|
+
trackPhoneClick: (phoneNumber: string, metadata?: Record<string, unknown>) => void;
|
|
62
|
+
/** Manually track an email click */
|
|
63
|
+
trackEmailClick: (email: string, metadata?: Record<string, unknown>) => void;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Hook for tracking phone and email contact interactions as conversions.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```tsx
|
|
70
|
+
* // Auto-track all tel: and mailto: links
|
|
71
|
+
* useContactTracking()
|
|
72
|
+
*
|
|
73
|
+
* // Manual tracking
|
|
74
|
+
* const { trackPhoneClick, trackEmailClick } = useContactTracking()
|
|
75
|
+
* trackPhoneClick('513-555-1234')
|
|
76
|
+
* trackEmailClick('hello@example.com')
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
declare function useContactTracking(options?: UseContactTrackingOptions): ContactTrackingReturn;
|
|
80
|
+
/**
|
|
81
|
+
* Component wrapper for contact tracking
|
|
82
|
+
* Simply include this component to auto-track all tel: and mailto: links
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```tsx
|
|
86
|
+
* <ContactTracking />
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
declare function ContactTracking({ debug }: {
|
|
90
|
+
debug?: boolean;
|
|
91
|
+
}): null;
|
|
92
|
+
|
|
93
|
+
export { AnalyticsContextValue, AnalyticsProvider, ContactTracking, TrackConversionOptions, TrackEventOptions, WebVitals, useAnalytics, useContactTracking, useTrackEvent };
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import React__default from 'react';
|
|
3
|
+
import { A as AnalyticsContextValue, T as TrackEventOptions, a as TrackConversionOptions } from '../types-DNSYU7qI.js';
|
|
4
|
+
export { c as AnalyticsConfig, b as AnalyticsEvent, C as Conversion, P as PageView, S as Session, W as WebVitalsData } from '../types-DNSYU7qI.js';
|
|
5
|
+
|
|
6
|
+
interface AnalyticsProviderProps {
|
|
7
|
+
children: React__default.ReactNode;
|
|
8
|
+
apiUrl?: string;
|
|
9
|
+
apiKey?: string;
|
|
10
|
+
trackPageViews?: boolean;
|
|
11
|
+
trackWebVitals?: boolean;
|
|
12
|
+
trackScrollDepth?: boolean;
|
|
13
|
+
trackClicks?: boolean;
|
|
14
|
+
trackJourneys?: boolean;
|
|
15
|
+
sessionTimeout?: number;
|
|
16
|
+
excludePaths?: string[];
|
|
17
|
+
validateAgainstSitemap?: boolean;
|
|
18
|
+
debug?: boolean;
|
|
19
|
+
/** External visitor ID from shared identity (used by SiteKitLayout) */
|
|
20
|
+
externalVisitorId?: string;
|
|
21
|
+
/** External session ID from shared identity (used by SiteKitLayout) */
|
|
22
|
+
externalSessionId?: string;
|
|
23
|
+
/** Callback invoked with page metadata after each page view (used by Signal bridge) */
|
|
24
|
+
onPageMetadata?: (metadata: Record<string, unknown>) => void;
|
|
25
|
+
}
|
|
26
|
+
declare function AnalyticsProvider({ children, apiUrl: propApiUrl, apiKey: propApiKey, trackPageViews, trackWebVitals, trackScrollDepth, trackClicks, trackJourneys, // NEW: Enable journey tracking by default
|
|
27
|
+
sessionTimeout, excludePaths, validateAgainstSitemap, debug, externalVisitorId, externalSessionId, onPageMetadata, }: AnalyticsProviderProps): react_jsx_runtime.JSX.Element;
|
|
28
|
+
declare function useAnalytics(): AnalyticsContextValue;
|
|
29
|
+
declare function useTrackEvent(): {
|
|
30
|
+
trackEvent: (options: TrackEventOptions) => void;
|
|
31
|
+
trackConversion: (options: TrackConversionOptions) => void;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @sonordev/site-kit/analytics - Web Vitals Component
|
|
36
|
+
*
|
|
37
|
+
* Automatically reports Core Web Vitals via Portal API
|
|
38
|
+
*/
|
|
39
|
+
interface WebVitalsProps {
|
|
40
|
+
apiUrl?: string;
|
|
41
|
+
apiKey?: string;
|
|
42
|
+
debug?: boolean;
|
|
43
|
+
}
|
|
44
|
+
declare function WebVitals({ apiUrl: propApiUrl, apiKey: propApiKey, debug }: WebVitalsProps): null;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @sonordev/site-kit/analytics - Contact Tracking Hook
|
|
48
|
+
*
|
|
49
|
+
* Tracks phone calls and email clicks as conversions.
|
|
50
|
+
* Use this hook to automatically track tel: and mailto: links,
|
|
51
|
+
* or manually track contact interactions.
|
|
52
|
+
*/
|
|
53
|
+
interface UseContactTrackingOptions {
|
|
54
|
+
/** Automatically track all tel: and mailto: links (default: true) */
|
|
55
|
+
autoTrack?: boolean;
|
|
56
|
+
/** Debug mode - logs events to console */
|
|
57
|
+
debug?: boolean;
|
|
58
|
+
}
|
|
59
|
+
interface ContactTrackingReturn {
|
|
60
|
+
/** Manually track a phone call click */
|
|
61
|
+
trackPhoneClick: (phoneNumber: string, metadata?: Record<string, unknown>) => void;
|
|
62
|
+
/** Manually track an email click */
|
|
63
|
+
trackEmailClick: (email: string, metadata?: Record<string, unknown>) => void;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Hook for tracking phone and email contact interactions as conversions.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```tsx
|
|
70
|
+
* // Auto-track all tel: and mailto: links
|
|
71
|
+
* useContactTracking()
|
|
72
|
+
*
|
|
73
|
+
* // Manual tracking
|
|
74
|
+
* const { trackPhoneClick, trackEmailClick } = useContactTracking()
|
|
75
|
+
* trackPhoneClick('513-555-1234')
|
|
76
|
+
* trackEmailClick('hello@example.com')
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
declare function useContactTracking(options?: UseContactTrackingOptions): ContactTrackingReturn;
|
|
80
|
+
/**
|
|
81
|
+
* Component wrapper for contact tracking
|
|
82
|
+
* Simply include this component to auto-track all tel: and mailto: links
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```tsx
|
|
86
|
+
* <ContactTracking />
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
declare function ContactTracking({ debug }: {
|
|
90
|
+
debug?: boolean;
|
|
91
|
+
}): null;
|
|
92
|
+
|
|
93
|
+
export { AnalyticsContextValue, AnalyticsProvider, ContactTracking, TrackConversionOptions, TrackEventOptions, WebVitals, useAnalytics, useContactTracking, useTrackEvent };
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var chunkWECQ6KOB_js = require('../chunk-WECQ6KOB.js');
|
|
5
|
+
require('../chunk-ZSMWDLMK.js');
|
|
6
|
+
var react = require('react');
|
|
7
|
+
|
|
8
|
+
function useContactTracking(options = {}) {
|
|
9
|
+
const { autoTrack = true, debug = false } = options;
|
|
10
|
+
const { trackConversion } = chunkWECQ6KOB_js.useAnalytics();
|
|
11
|
+
const trackPhoneClick = react.useCallback((phoneNumber, metadata) => {
|
|
12
|
+
if (debug) console.log("[Analytics] Phone click:", phoneNumber);
|
|
13
|
+
trackConversion({
|
|
14
|
+
type: "phone_call",
|
|
15
|
+
metadata: {
|
|
16
|
+
phoneNumber: phoneNumber.replace(/\D/g, ""),
|
|
17
|
+
// Normalize to digits
|
|
18
|
+
rawNumber: phoneNumber,
|
|
19
|
+
...metadata
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}, [trackConversion, debug]);
|
|
23
|
+
const trackEmailClick = react.useCallback((email, metadata) => {
|
|
24
|
+
if (debug) console.log("[Analytics] Email click:", email);
|
|
25
|
+
trackConversion({
|
|
26
|
+
type: "email_click",
|
|
27
|
+
metadata: {
|
|
28
|
+
email,
|
|
29
|
+
...metadata
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}, [trackConversion, debug]);
|
|
33
|
+
react.useEffect(() => {
|
|
34
|
+
if (!autoTrack || typeof document === "undefined") return;
|
|
35
|
+
const handleClick = (e) => {
|
|
36
|
+
const target = e.target;
|
|
37
|
+
const anchor = target.closest("a");
|
|
38
|
+
if (!anchor) return;
|
|
39
|
+
const href = anchor.getAttribute("href");
|
|
40
|
+
if (!href) return;
|
|
41
|
+
if (href.startsWith("tel:")) {
|
|
42
|
+
const phone = href.replace("tel:", "").trim();
|
|
43
|
+
trackPhoneClick(phone, {
|
|
44
|
+
linkText: anchor.textContent?.trim(),
|
|
45
|
+
source: "auto"
|
|
46
|
+
});
|
|
47
|
+
} else if (href.startsWith("mailto:")) {
|
|
48
|
+
const email = href.replace("mailto:", "").split("?")[0].trim();
|
|
49
|
+
trackEmailClick(email, {
|
|
50
|
+
linkText: anchor.textContent?.trim(),
|
|
51
|
+
source: "auto"
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
document.addEventListener("click", handleClick, { capture: true });
|
|
56
|
+
return () => {
|
|
57
|
+
document.removeEventListener("click", handleClick, { capture: true });
|
|
58
|
+
};
|
|
59
|
+
}, [autoTrack, trackPhoneClick, trackEmailClick]);
|
|
60
|
+
return {
|
|
61
|
+
trackPhoneClick,
|
|
62
|
+
trackEmailClick
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function ContactTracking({ debug = false }) {
|
|
66
|
+
useContactTracking({ autoTrack: true, debug });
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
Object.defineProperty(exports, "AnalyticsProvider", {
|
|
71
|
+
enumerable: true,
|
|
72
|
+
get: function () { return chunkWECQ6KOB_js.AnalyticsProvider; }
|
|
73
|
+
});
|
|
74
|
+
Object.defineProperty(exports, "WebVitals", {
|
|
75
|
+
enumerable: true,
|
|
76
|
+
get: function () { return chunkWECQ6KOB_js.WebVitals; }
|
|
77
|
+
});
|
|
78
|
+
Object.defineProperty(exports, "useAnalytics", {
|
|
79
|
+
enumerable: true,
|
|
80
|
+
get: function () { return chunkWECQ6KOB_js.useAnalytics; }
|
|
81
|
+
});
|
|
82
|
+
Object.defineProperty(exports, "useTrackEvent", {
|
|
83
|
+
enumerable: true,
|
|
84
|
+
get: function () { return chunkWECQ6KOB_js.useTrackEvent; }
|
|
85
|
+
});
|
|
86
|
+
exports.ContactTracking = ContactTracking;
|
|
87
|
+
exports.useContactTracking = useContactTracking;
|
|
88
|
+
//# sourceMappingURL=index.js.map
|
|
89
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/analytics/useContactTracking.ts"],"names":["useAnalytics","useCallback","useEffect"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @sonordev/site-kit/analytics - Contact Tracking Hook\n * \n * Tracks phone calls and email clicks as conversions.\n * Use this hook to automatically track tel: and mailto: links,\n * or manually track contact interactions.\n */\n\n'use client'\n\nimport { useCallback, useEffect } from 'react'\nimport { useAnalytics } from './AnalyticsProvider'\n\nexport interface UseContactTrackingOptions {\n /** Automatically track all tel: and mailto: links (default: true) */\n autoTrack?: boolean\n /** Debug mode - logs events to console */\n debug?: boolean\n}\n\nexport interface ContactTrackingReturn {\n /** Manually track a phone call click */\n trackPhoneClick: (phoneNumber: string, metadata?: Record<string, unknown>) => void\n /** Manually track an email click */\n trackEmailClick: (email: string, metadata?: Record<string, unknown>) => void\n}\n\n/**\n * Hook for tracking phone and email contact interactions as conversions.\n * \n * @example\n * ```tsx\n * // Auto-track all tel: and mailto: links\n * useContactTracking()\n * \n * // Manual tracking\n * const { trackPhoneClick, trackEmailClick } = useContactTracking()\n * trackPhoneClick('513-555-1234')\n * trackEmailClick('hello@example.com')\n * ```\n */\nexport function useContactTracking(options: UseContactTrackingOptions = {}): ContactTrackingReturn {\n const { autoTrack = true, debug = false } = options\n const { trackConversion } = useAnalytics()\n \n const trackPhoneClick = useCallback((phoneNumber: string, metadata?: Record<string, unknown>) => {\n if (debug) console.log('[Analytics] Phone click:', phoneNumber)\n \n trackConversion({\n type: 'phone_call',\n metadata: {\n phoneNumber: phoneNumber.replace(/\\D/g, ''), // Normalize to digits\n rawNumber: phoneNumber,\n ...metadata,\n },\n })\n }, [trackConversion, debug])\n \n const trackEmailClick = useCallback((email: string, metadata?: Record<string, unknown>) => {\n if (debug) console.log('[Analytics] Email click:', email)\n \n trackConversion({\n type: 'email_click',\n metadata: {\n email,\n ...metadata,\n },\n })\n }, [trackConversion, debug])\n \n // Auto-track tel: and mailto: links\n useEffect(() => {\n if (!autoTrack || typeof document === 'undefined') return\n \n const handleClick = (e: MouseEvent) => {\n const target = e.target as HTMLElement\n const anchor = target.closest('a')\n if (!anchor) return\n \n const href = anchor.getAttribute('href')\n if (!href) return\n \n if (href.startsWith('tel:')) {\n const phone = href.replace('tel:', '').trim()\n trackPhoneClick(phone, {\n linkText: anchor.textContent?.trim(),\n source: 'auto',\n })\n } else if (href.startsWith('mailto:')) {\n const email = href.replace('mailto:', '').split('?')[0].trim()\n trackEmailClick(email, {\n linkText: anchor.textContent?.trim(),\n source: 'auto',\n })\n }\n }\n \n document.addEventListener('click', handleClick, { capture: true })\n \n return () => {\n document.removeEventListener('click', handleClick, { capture: true })\n }\n }, [autoTrack, trackPhoneClick, trackEmailClick])\n \n return {\n trackPhoneClick,\n trackEmailClick,\n }\n}\n\n/**\n * Component wrapper for contact tracking\n * Simply include this component to auto-track all tel: and mailto: links\n * \n * @example\n * ```tsx\n * <ContactTracking />\n * ```\n */\nexport function ContactTracking({ debug = false }: { debug?: boolean }) {\n useContactTracking({ autoTrack: true, debug })\n return null\n}\n"]}
|