keystone-design-bootstrap 1.0.96 → 1.0.98
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/contexts/index.js +122 -1
- package/dist/contexts/index.js.map +1 -1
- package/dist/design_system/components/DynamicFormFields.js +118 -3
- package/dist/design_system/components/DynamicFormFields.js.map +1 -1
- package/dist/design_system/elements/index.js +118 -3
- package/dist/design_system/elements/index.js.map +1 -1
- package/dist/design_system/sections/index.js +138 -9
- package/dist/design_system/sections/index.js.map +1 -1
- package/dist/index.js +172 -21
- package/dist/index.js.map +1 -1
- package/dist/lib/server-api.js +49 -2
- package/dist/lib/server-api.js.map +1 -1
- package/dist/tracking/index.d.ts +14 -1
- package/dist/tracking/index.js +248 -50
- package/dist/tracking/index.js.map +1 -1
- package/package.json +5 -1
- package/src/contexts/ThemeContext.tsx +2 -1
- package/src/design_system/chat/useRealtimeReplyOrchestrator.ts +24 -5
- package/src/design_system/components/ChatWidget.tsx +10 -3
- package/src/design_system/elements/map/GoogleMap.tsx +9 -2
- package/src/design_system/sections/blog-post.tsx +13 -3
- package/src/design_system/sections/home-hero-component.tsx +4 -1
- package/src/lib/server-api.ts +6 -2
- package/src/lib/server-log.ts +39 -0
- package/src/next/routes/chat.ts +3 -2
- package/src/next/routes/form.ts +2 -1
- package/src/tracking/MetaPixel.tsx +10 -1
- package/src/tracking/PostHogProvider.tsx +10 -1
- package/src/tracking/firePixelEvent.ts +7 -2
- package/src/tracking/logging.ts +116 -24
package/dist/lib/server-api.js
CHANGED
|
@@ -1,3 +1,47 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
3
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
5
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
6
|
+
var __spreadValues = (a, b) => {
|
|
7
|
+
for (var prop in b || (b = {}))
|
|
8
|
+
if (__hasOwnProp.call(b, prop))
|
|
9
|
+
__defNormalProp(a, prop, b[prop]);
|
|
10
|
+
if (__getOwnPropSymbols)
|
|
11
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
12
|
+
if (__propIsEnum.call(b, prop))
|
|
13
|
+
__defNormalProp(a, prop, b[prop]);
|
|
14
|
+
}
|
|
15
|
+
return a;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
// src/lib/server-log.ts
|
|
19
|
+
function normalizeError(error) {
|
|
20
|
+
if (error instanceof Error) {
|
|
21
|
+
return {
|
|
22
|
+
message: error.message,
|
|
23
|
+
stack: error.stack || "",
|
|
24
|
+
name: error.name
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
return { message: String(error) };
|
|
28
|
+
}
|
|
29
|
+
function writeServerLog(level, event, detail) {
|
|
30
|
+
const payload = {
|
|
31
|
+
level,
|
|
32
|
+
event,
|
|
33
|
+
detail: detail != null ? detail : {},
|
|
34
|
+
at: (/* @__PURE__ */ new Date()).toISOString()
|
|
35
|
+
};
|
|
36
|
+
const line = `[ks-server] ${JSON.stringify(payload)}
|
|
37
|
+
`;
|
|
38
|
+
const stream = level === "ERROR" ? process.stderr : process.stdout;
|
|
39
|
+
stream.write(line);
|
|
40
|
+
}
|
|
41
|
+
function serverError(event, error, detail) {
|
|
42
|
+
writeServerLog("ERROR", event, __spreadValues(__spreadValues({}, detail != null ? detail : {}), error !== void 0 ? { error: normalizeError(error) } : {}));
|
|
43
|
+
}
|
|
44
|
+
|
|
1
45
|
// src/lib/server-api.ts
|
|
2
46
|
var API_URL = process.env.API_URL || "http://localhost:3000/api/v1";
|
|
3
47
|
var API_KEY = process.env.API_KEY || "";
|
|
@@ -17,13 +61,16 @@ async function serverFetch(endpoint, options = {}) {
|
|
|
17
61
|
}
|
|
18
62
|
const response = await fetch(url, fetchOptions);
|
|
19
63
|
if (!response.ok) {
|
|
20
|
-
|
|
64
|
+
serverError("SERVER_API_NON_OK_RESPONSE", void 0, {
|
|
65
|
+
endpoint,
|
|
66
|
+
status: response.status
|
|
67
|
+
});
|
|
21
68
|
return null;
|
|
22
69
|
}
|
|
23
70
|
const json = await response.json();
|
|
24
71
|
return (_a = json.data) != null ? _a : json;
|
|
25
72
|
} catch (error) {
|
|
26
|
-
|
|
73
|
+
serverError("SERVER_API_FETCH_FAILED", error, { endpoint });
|
|
27
74
|
return null;
|
|
28
75
|
}
|
|
29
76
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/server-api.ts"],"sourcesContent":["/**\n * Server-side API client for SSR\n * API key is stored securely on the server - never exposed to browser\n */\n\nimport type { CompanyInformation } from '../types/api/company-information';\nimport type { Service } from '../types/api/service';\nimport type { Package } from '../types/api/package';\nimport type { WebsitePhotos } from '../types/api/website-photos';\n\nconst API_URL = process.env.API_URL || 'http://localhost:3000/api/v1';\nconst API_KEY = process.env.API_KEY || '';\n\ninterface FetchOptions {\n cache?: RequestCache;\n revalidate?: number;\n}\n\nasync function serverFetch<T>(endpoint: string, options: FetchOptions = {}): Promise<T | null> {\n const url = `${API_URL}${endpoint}`;\n \n try {\n const fetchOptions: RequestInit & { next?: { revalidate?: number } } = {\n headers: {\n 'X-API-Key': API_KEY,\n 'Content-Type': 'application/json',\n },\n cache: options.cache,\n };\n \n if (options.revalidate) {\n fetchOptions.next = { revalidate: options.revalidate };\n }\n \n const response = await fetch(url, fetchOptions);\n\n if (!response.ok) {\n console.error(`[Server API] Error ${response.status} for ${endpoint}`);\n return null;\n }\n\n const json = await response.json();\n \n // Rails API returns { data: [...], meta: {...} }\n return json.data ?? json;\n } catch (error) {\n console.error(`[Server API] Failed to fetch ${endpoint}:`, error);\n return null;\n }\n}\n\n/**\n * Generic serverApi object for flexible endpoint access\n */\nexport const serverApi = {\n get: <T = unknown>(endpoint: string, options?: FetchOptions): Promise<T | null> => {\n return serverFetch<T>(endpoint, options || { revalidate: 60 });\n }\n};\n\n// Revalidate data every 60 seconds (ISR)\nconst defaultOptions: FetchOptions = { revalidate: 60 };\n\nexport async function getCompanyInformation(): Promise<CompanyInformation | null> {\n return serverFetch<CompanyInformation>('/public/company_information', defaultOptions);\n}\n\n/** Ads config (e.g. Meta Pixel). Returns { meta_pixel_id?: string } or {}. Only present when account has connected Meta Ads. */\nexport async function getAdsConfig(): Promise<{ meta_pixel_id?: string } | null> {\n const data = await serverFetch<{ meta_pixel_id?: string }>('/public/ads_config', defaultOptions);\n return data ?? null;\n}\n\n/** Extract Meta Pixel ID from ads config for use with <MetaPixel pixelId={...} />. Only returns a value when present and valid (numeric). */\nexport function getMetaPixelId(adsConfig: { meta_pixel_id?: string } | null | undefined): string | null {\n const id = adsConfig && typeof adsConfig === 'object' && 'meta_pixel_id' in adsConfig && adsConfig.meta_pixel_id;\n const str = id != null && id !== '' ? String(id).trim() : '';\n return str !== '' && str !== 'null' && /^\\d+$/.test(str) ? str : null;\n}\n\nexport type AnalyticsConfig = {\n /** PostHog project API key — platform-wide, from POSTHOG_API_KEY env var on the Rails server. */\n posthog_api_key?: string;\n /** Per-site GTM container ID (e.g. GTM-ABC123), provisioned by Keystone. */\n gtm_container_public_id?: string;\n /**\n * Environment identifier from KEYSTONE_ENV on the Rails server (e.g. \"production\", \"staging\",\n * \"development\"). Registered as a PostHog super property on every event so the sync job can\n * filter by environment and avoid cross-environment data contamination.\n */\n environment?: string;\n};\n\n/** Analytics config for customer sites. Returns platform-wide analytics keys (e.g. PostHog). */\nexport async function getAnalyticsConfig(): Promise<AnalyticsConfig | null> {\n const data = await serverFetch<AnalyticsConfig>('/public/analytics_config', defaultOptions);\n return data ?? null;\n}\n\n/** Extract PostHog API key from analytics config for use with <PostHogProvider apiKey={...} />. */\nexport function getPostHogApiKey(analyticsConfig: AnalyticsConfig | null | undefined): string | null {\n const key = analyticsConfig?.posthog_api_key;\n const str = key != null && key !== '' ? String(key).trim() : '';\n return str !== '' && str !== 'null' ? str : null;\n}\n\n/** Extract GTM container ID from analytics config for use with <GoogleTagManager containerId={...} />. */\nexport function getGtmContainerPublicId(analyticsConfig: AnalyticsConfig | null | undefined): string | null {\n const value = analyticsConfig?.gtm_container_public_id;\n const str = value != null && value !== '' ? String(value).trim() : '';\n return str !== '' && str !== 'null' && /^GTM-[A-Z0-9]+$/i.test(str) ? str : null;\n}\n\n/** Extract environment string from analytics config for use with <PostHogProvider environment={...} />. */\nexport function getKeystoneEnvironment(analyticsConfig: AnalyticsConfig | null | undefined): string {\n return analyticsConfig?.environment?.trim() || 'development';\n}\n\nexport async function getServices(): Promise<Service[] | null> {\n return serverFetch<Service[]>('/public/services', defaultOptions);\n}\n\nexport async function getService(slug: string): Promise<Service | null> {\n return serverFetch<Service>(`/public/services/by_slug/${slug}`, defaultOptions);\n}\n\nexport async function getLocations() {\n return serverFetch('/public/locations', defaultOptions);\n}\n\nexport async function getLocation(slug: string) {\n return serverFetch(`/public/locations/by_slug/${slug}`, defaultOptions);\n}\n\nexport async function getReviews() {\n return serverFetch('/public/reviews', defaultOptions);\n}\n\nexport async function getFAQs() {\n return serverFetch('/public/faq_questions', defaultOptions);\n}\n\nexport async function getBlogPosts() {\n return serverFetch('/public/blog_posts', defaultOptions);\n}\n\nexport async function getBlogPost(slug: string) {\n return serverFetch(`/public/blog_posts/by_slug/${slug}`, defaultOptions);\n}\n\nexport async function getTeamMembers() {\n return serverFetch('/public/team_members', defaultOptions);\n}\n\nexport async function getWebsitePhotos(): Promise<WebsitePhotos | null> {\n return serverFetch<WebsitePhotos>('/public/website_photos', defaultOptions);\n}\n\nexport async function getJobPostings() {\n return serverFetch('/public/job_postings', defaultOptions);\n}\n\nexport async function getJobPosting(slug: string) {\n return serverFetch(`/public/job_postings/by_slug/${slug}`, defaultOptions);\n}\n\nexport async function getSocialPosts() {\n return serverFetch('/public/social_posts', defaultOptions);\n}\n\n/** Packages (bundles of service items). */\nexport async function getPackages(): Promise<Package[] | null> {\n return serverFetch<Package[]>('/public/packages', defaultOptions);\n}\n\nexport async function getPackage(slug: string): Promise<Package | null> {\n return serverFetch<Package>(`/public/packages/by_slug/${encodeURIComponent(slug)}`, defaultOptions);\n}\n\n// Alias for testimonials (API uses \"reviews\")\nexport async function getTestimonials() {\n return getReviews();\n}\n\n/** Form definition for dynamic form rendering, fetched by form_type. */\nexport async function getForm(formType: string) {\n type FormDefinition = import('../types/api/form').FormDefinition;\n return serverFetch<FormDefinition>(`/public/forms/${encodeURIComponent(formType)}`, defaultOptions);\n}\n\n/** Form definition for dynamic form rendering, fetched by numeric ID. */\nexport async function getFormById(id: number | string) {\n type FormDefinition = import('../types/api/form').FormDefinition;\n return serverFetch<FormDefinition>(`/public/form_by_id/${encodeURIComponent(id)}`, defaultOptions);\n}\n\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/lib/server-log.ts","../../src/lib/server-api.ts"],"sourcesContent":["type ServerLogLevel = 'INFO' | 'WARN' | 'ERROR';\n\nfunction normalizeError(error: unknown): Record<string, string> {\n if (error instanceof Error) {\n return {\n message: error.message,\n stack: error.stack || '',\n name: error.name,\n };\n }\n return { message: String(error) };\n}\n\nfunction writeServerLog(level: ServerLogLevel, event: string, detail?: Record<string, unknown>): void {\n const payload = {\n level,\n event,\n detail: detail ?? {},\n at: new Date().toISOString(),\n };\n const line = `[ks-server] ${JSON.stringify(payload)}\\n`;\n const stream = level === 'ERROR' ? process.stderr : process.stdout;\n stream.write(line);\n}\n\nexport function serverLog(event: string, detail?: Record<string, unknown>): void {\n writeServerLog('INFO', event, detail);\n}\n\nexport function serverWarn(event: string, detail?: Record<string, unknown>): void {\n writeServerLog('WARN', event, detail);\n}\n\nexport function serverError(event: string, error?: unknown, detail?: Record<string, unknown>): void {\n writeServerLog('ERROR', event, {\n ...(detail ?? {}),\n ...(error !== undefined ? { error: normalizeError(error) } : {}),\n });\n}\n","/**\n * Server-side API client for SSR\n * API key is stored securely on the server - never exposed to browser\n */\n\nimport type { CompanyInformation } from '../types/api/company-information';\nimport type { Service } from '../types/api/service';\nimport type { Package } from '../types/api/package';\nimport type { WebsitePhotos } from '../types/api/website-photos';\nimport { serverError } from './server-log';\n\nconst API_URL = process.env.API_URL || 'http://localhost:3000/api/v1';\nconst API_KEY = process.env.API_KEY || '';\n\ninterface FetchOptions {\n cache?: RequestCache;\n revalidate?: number;\n}\n\nasync function serverFetch<T>(endpoint: string, options: FetchOptions = {}): Promise<T | null> {\n const url = `${API_URL}${endpoint}`;\n \n try {\n const fetchOptions: RequestInit & { next?: { revalidate?: number } } = {\n headers: {\n 'X-API-Key': API_KEY,\n 'Content-Type': 'application/json',\n },\n cache: options.cache,\n };\n \n if (options.revalidate) {\n fetchOptions.next = { revalidate: options.revalidate };\n }\n \n const response = await fetch(url, fetchOptions);\n\n if (!response.ok) {\n serverError('SERVER_API_NON_OK_RESPONSE', undefined, {\n endpoint,\n status: response.status,\n });\n return null;\n }\n\n const json = await response.json();\n \n // Rails API returns { data: [...], meta: {...} }\n return json.data ?? json;\n } catch (error) {\n serverError('SERVER_API_FETCH_FAILED', error, { endpoint });\n return null;\n }\n}\n\n/**\n * Generic serverApi object for flexible endpoint access\n */\nexport const serverApi = {\n get: <T = unknown>(endpoint: string, options?: FetchOptions): Promise<T | null> => {\n return serverFetch<T>(endpoint, options || { revalidate: 60 });\n }\n};\n\n// Revalidate data every 60 seconds (ISR)\nconst defaultOptions: FetchOptions = { revalidate: 60 };\n\nexport async function getCompanyInformation(): Promise<CompanyInformation | null> {\n return serverFetch<CompanyInformation>('/public/company_information', defaultOptions);\n}\n\n/** Ads config (e.g. Meta Pixel). Returns { meta_pixel_id?: string } or {}. Only present when account has connected Meta Ads. */\nexport async function getAdsConfig(): Promise<{ meta_pixel_id?: string } | null> {\n const data = await serverFetch<{ meta_pixel_id?: string }>('/public/ads_config', defaultOptions);\n return data ?? null;\n}\n\n/** Extract Meta Pixel ID from ads config for use with <MetaPixel pixelId={...} />. Only returns a value when present and valid (numeric). */\nexport function getMetaPixelId(adsConfig: { meta_pixel_id?: string } | null | undefined): string | null {\n const id = adsConfig && typeof adsConfig === 'object' && 'meta_pixel_id' in adsConfig && adsConfig.meta_pixel_id;\n const str = id != null && id !== '' ? String(id).trim() : '';\n return str !== '' && str !== 'null' && /^\\d+$/.test(str) ? str : null;\n}\n\nexport type AnalyticsConfig = {\n /** PostHog project API key — platform-wide, from POSTHOG_API_KEY env var on the Rails server. */\n posthog_api_key?: string;\n /** Per-site GTM container ID (e.g. GTM-ABC123), provisioned by Keystone. */\n gtm_container_public_id?: string;\n /**\n * Environment identifier from KEYSTONE_ENV on the Rails server (e.g. \"production\", \"staging\",\n * \"development\"). Registered as a PostHog super property on every event so the sync job can\n * filter by environment and avoid cross-environment data contamination.\n */\n environment?: string;\n};\n\n/** Analytics config for customer sites. Returns platform-wide analytics keys (e.g. PostHog). */\nexport async function getAnalyticsConfig(): Promise<AnalyticsConfig | null> {\n const data = await serverFetch<AnalyticsConfig>('/public/analytics_config', defaultOptions);\n return data ?? null;\n}\n\n/** Extract PostHog API key from analytics config for use with <PostHogProvider apiKey={...} />. */\nexport function getPostHogApiKey(analyticsConfig: AnalyticsConfig | null | undefined): string | null {\n const key = analyticsConfig?.posthog_api_key;\n const str = key != null && key !== '' ? String(key).trim() : '';\n return str !== '' && str !== 'null' ? str : null;\n}\n\n/** Extract GTM container ID from analytics config for use with <GoogleTagManager containerId={...} />. */\nexport function getGtmContainerPublicId(analyticsConfig: AnalyticsConfig | null | undefined): string | null {\n const value = analyticsConfig?.gtm_container_public_id;\n const str = value != null && value !== '' ? String(value).trim() : '';\n return str !== '' && str !== 'null' && /^GTM-[A-Z0-9]+$/i.test(str) ? str : null;\n}\n\n/** Extract environment string from analytics config for use with <PostHogProvider environment={...} />. */\nexport function getKeystoneEnvironment(analyticsConfig: AnalyticsConfig | null | undefined): string {\n return analyticsConfig?.environment?.trim() || 'development';\n}\n\nexport async function getServices(): Promise<Service[] | null> {\n return serverFetch<Service[]>('/public/services', defaultOptions);\n}\n\nexport async function getService(slug: string): Promise<Service | null> {\n return serverFetch<Service>(`/public/services/by_slug/${slug}`, defaultOptions);\n}\n\nexport async function getLocations() {\n return serverFetch('/public/locations', defaultOptions);\n}\n\nexport async function getLocation(slug: string) {\n return serverFetch(`/public/locations/by_slug/${slug}`, defaultOptions);\n}\n\nexport async function getReviews() {\n return serverFetch('/public/reviews', defaultOptions);\n}\n\nexport async function getFAQs() {\n return serverFetch('/public/faq_questions', defaultOptions);\n}\n\nexport async function getBlogPosts() {\n return serverFetch('/public/blog_posts', defaultOptions);\n}\n\nexport async function getBlogPost(slug: string) {\n return serverFetch(`/public/blog_posts/by_slug/${slug}`, defaultOptions);\n}\n\nexport async function getTeamMembers() {\n return serverFetch('/public/team_members', defaultOptions);\n}\n\nexport async function getWebsitePhotos(): Promise<WebsitePhotos | null> {\n return serverFetch<WebsitePhotos>('/public/website_photos', defaultOptions);\n}\n\nexport async function getJobPostings() {\n return serverFetch('/public/job_postings', defaultOptions);\n}\n\nexport async function getJobPosting(slug: string) {\n return serverFetch(`/public/job_postings/by_slug/${slug}`, defaultOptions);\n}\n\nexport async function getSocialPosts() {\n return serverFetch('/public/social_posts', defaultOptions);\n}\n\n/** Packages (bundles of service items). */\nexport async function getPackages(): Promise<Package[] | null> {\n return serverFetch<Package[]>('/public/packages', defaultOptions);\n}\n\nexport async function getPackage(slug: string): Promise<Package | null> {\n return serverFetch<Package>(`/public/packages/by_slug/${encodeURIComponent(slug)}`, defaultOptions);\n}\n\n// Alias for testimonials (API uses \"reviews\")\nexport async function getTestimonials() {\n return getReviews();\n}\n\n/** Form definition for dynamic form rendering, fetched by form_type. */\nexport async function getForm(formType: string) {\n type FormDefinition = import('../types/api/form').FormDefinition;\n return serverFetch<FormDefinition>(`/public/forms/${encodeURIComponent(formType)}`, defaultOptions);\n}\n\n/** Form definition for dynamic form rendering, fetched by numeric ID. */\nexport async function getFormById(id: number | string) {\n type FormDefinition = import('../types/api/form').FormDefinition;\n return serverFetch<FormDefinition>(`/public/form_by_id/${encodeURIComponent(id)}`, defaultOptions);\n}\n\n"],"mappings":"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","names":[]}
|
package/dist/tracking/index.d.ts
CHANGED
|
@@ -238,4 +238,17 @@ declare function captureEvent<E extends KsEventName>(event: E, ...args: KsEventP
|
|
|
238
238
|
*/
|
|
239
239
|
declare function captureCustomEvent(event: string, properties?: Record<string, unknown>): void;
|
|
240
240
|
|
|
241
|
-
|
|
241
|
+
type LogLevel = 'info' | 'warn' | 'error';
|
|
242
|
+
type LogOptions = {
|
|
243
|
+
/** Send this log payload to PostHog Logs product. */
|
|
244
|
+
shipToPostHog?: boolean;
|
|
245
|
+
};
|
|
246
|
+
/**
|
|
247
|
+
* Channel → accent colour. Unregistered channels fall through to gray.
|
|
248
|
+
*/
|
|
249
|
+
declare const CHANNEL_COLORS: Record<string, string>;
|
|
250
|
+
declare function log(channel: string, event: string, detail?: Record<string, unknown>, options?: LogOptions): void;
|
|
251
|
+
declare function warn(channel: string, event: string, detail?: Record<string, unknown>, options?: LogOptions): void;
|
|
252
|
+
declare function error(channel: string, event: string, detail?: Record<string, unknown>, options?: LogOptions): void;
|
|
253
|
+
|
|
254
|
+
export { CHANNEL_COLORS, GoogleTagManager, type GoogleTagManagerProps, KeystoneAnalyticsTracker, type KsEventName, type KsEventProperties, type LogLevel, type LogOptions, MetaPixel, type MetaPixelProps, MetaPixelTracker, type PixelEvent, type PixelEventParams, type PixelUserData, PostHogProvider, type PostHogProviderProps, captureCustomEvent, captureEvent, error, firePixelEvent, log, setPixelUserData, warn };
|
package/dist/tracking/index.js
CHANGED
|
@@ -19,51 +19,160 @@ var __spreadValues = (a, b) => {
|
|
|
19
19
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
20
|
|
|
21
21
|
// src/tracking/MetaPixel.tsx
|
|
22
|
+
import { useEffect } from "react";
|
|
22
23
|
import Script from "next/script";
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
24
|
+
|
|
25
|
+
// src/tracking/logging.ts
|
|
26
|
+
import { logs } from "@opentelemetry/api-logs";
|
|
27
|
+
import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
|
|
28
|
+
import { resourceFromAttributes } from "@opentelemetry/resources";
|
|
29
|
+
import { BatchLogRecordProcessor, LoggerProvider } from "@opentelemetry/sdk-logs";
|
|
30
|
+
var BUILD_CONSOLE_DISABLED = process.env.NEXT_PUBLIC_LOGGING_DISABLED === "1";
|
|
31
|
+
var BUILD_POSTHOG_DISABLED = process.env.NEXT_PUBLIC_POSTHOG_LOGGING_DISABLED === "1";
|
|
32
|
+
var otelProvider = null;
|
|
33
|
+
var otelLogger = null;
|
|
34
|
+
var otelInitFingerprint = "";
|
|
35
|
+
var browserConsole = globalThis == null ? void 0 : globalThis["console"];
|
|
36
|
+
var CHANNEL_COLORS = {
|
|
37
|
+
// Shared diagnostics
|
|
38
|
+
"global-client": "#d2a8ff",
|
|
39
|
+
// Section pins (desktop)
|
|
40
|
+
"every-channel-pin": "#9febd7",
|
|
41
|
+
"hero-pin": "#6ecc8b",
|
|
42
|
+
"pricing-pin": "#399587",
|
|
43
|
+
"product-screens-pin": "#4fafa0",
|
|
44
|
+
"social-proof-pin": "#ffbb8a",
|
|
45
|
+
"value-props-pin": "#e0a733",
|
|
46
|
+
"work-pin": "#f57e56",
|
|
47
|
+
// Section pins (mobile)
|
|
48
|
+
"mobile-every-channel-pin": "#7ed9c6",
|
|
49
|
+
"mobile-hero-pin": "#f0eee6",
|
|
50
|
+
"mobile-pricing-pin": "#80d4ff",
|
|
51
|
+
"mobile-product-screens-pin": "#3a9085",
|
|
52
|
+
"mobile-social-proof-pin": "#ffd580",
|
|
53
|
+
"mobile-value-props-pin": "#4fafa0"
|
|
54
|
+
};
|
|
55
|
+
function flattenAttributes(input, prefix = "") {
|
|
56
|
+
const output = {};
|
|
57
|
+
for (const [key, value] of Object.entries(input)) {
|
|
58
|
+
const nextKey = prefix ? `${prefix}.${key}` : key;
|
|
59
|
+
if (value === null || value === void 0) continue;
|
|
60
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
61
|
+
output[nextKey] = value;
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (Array.isArray(value)) {
|
|
65
|
+
output[nextKey] = JSON.stringify(value);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (typeof value === "object") {
|
|
69
|
+
Object.assign(output, flattenAttributes(value, nextKey));
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
output[nextKey] = String(value);
|
|
37
73
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
74
|
+
return output;
|
|
75
|
+
}
|
|
76
|
+
function stripTrailingSlash(host) {
|
|
77
|
+
return host.replace(/\/+$/, "");
|
|
78
|
+
}
|
|
79
|
+
function initializePostHogLogging(options) {
|
|
80
|
+
var _a, _b, _c, _d, _e, _f;
|
|
81
|
+
if (typeof window === "undefined") return;
|
|
82
|
+
if (!((_a = options.apiKey) == null ? void 0 : _a.trim())) return;
|
|
83
|
+
const apiHost = stripTrailingSlash(((_b = options.apiHost) == null ? void 0 : _b.trim()) || "https://us.i.posthog.com");
|
|
84
|
+
const serviceName = ((_c = options.serviceName) == null ? void 0 : _c.trim()) || "keystone-customer-site";
|
|
85
|
+
const environment = ((_d = options.environment) == null ? void 0 : _d.trim()) || "production";
|
|
86
|
+
const fingerprint = `${apiHost}|${options.apiKey}|${serviceName}|${environment}|${(_e = options.accountId) != null ? _e : ""}|${(_f = options.accountName) != null ? _f : ""}`;
|
|
87
|
+
if (otelLogger && otelInitFingerprint === fingerprint) return;
|
|
88
|
+
if (otelProvider) {
|
|
89
|
+
void otelProvider.shutdown().catch(() => {
|
|
90
|
+
});
|
|
91
|
+
otelProvider = null;
|
|
92
|
+
otelLogger = null;
|
|
44
93
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
{
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
style: { display: "none" },
|
|
58
|
-
src: `https://www.facebook.com/tr?id=${id}&ev=PageView&noscript=1`,
|
|
59
|
-
alt: ""
|
|
94
|
+
const baseAttributes = {
|
|
95
|
+
"service.name": serviceName,
|
|
96
|
+
environment,
|
|
97
|
+
site_domain: window.location.hostname
|
|
98
|
+
};
|
|
99
|
+
if (options.accountId !== void 0) baseAttributes.account_id = options.accountId;
|
|
100
|
+
if (options.accountName) baseAttributes.account_name = options.accountName;
|
|
101
|
+
const exporter = new OTLPLogExporter({
|
|
102
|
+
url: `${apiHost}/i/v1/logs?token=${encodeURIComponent(options.apiKey)}`,
|
|
103
|
+
headers: {
|
|
104
|
+
// Keep request "simple" to avoid CORS preflight in browser.
|
|
105
|
+
"Content-Type": "text/plain"
|
|
60
106
|
}
|
|
61
|
-
)
|
|
107
|
+
});
|
|
108
|
+
otelProvider = new LoggerProvider({
|
|
109
|
+
resource: resourceFromAttributes(baseAttributes),
|
|
110
|
+
processors: [new BatchLogRecordProcessor(exporter)]
|
|
111
|
+
});
|
|
112
|
+
logs.setGlobalLoggerProvider(otelProvider);
|
|
113
|
+
otelLogger = logs.getLogger(serviceName);
|
|
114
|
+
otelInitFingerprint = fingerprint;
|
|
115
|
+
}
|
|
116
|
+
function isConsoleEnabled() {
|
|
117
|
+
if (BUILD_CONSOLE_DISABLED) return false;
|
|
118
|
+
if (typeof window === "undefined") return true;
|
|
119
|
+
return window.__loggingDisabled !== true;
|
|
120
|
+
}
|
|
121
|
+
function isPostHogShippingEnabled() {
|
|
122
|
+
if (BUILD_POSTHOG_DISABLED) return false;
|
|
123
|
+
if (typeof window === "undefined") return false;
|
|
124
|
+
return window.__posthogLoggingDisabled !== true;
|
|
125
|
+
}
|
|
126
|
+
function formatDetail(detail) {
|
|
127
|
+
return Object.entries(detail).map(([k, v]) => `${k}=${typeof v === "number" ? v.toFixed(4) : String(v)}`).join(" ");
|
|
128
|
+
}
|
|
129
|
+
function emitConsole(level, channel, event, detail) {
|
|
130
|
+
var _a, _b, _c, _d;
|
|
131
|
+
const color = (_a = CHANNEL_COLORS[channel]) != null ? _a : "#aaa";
|
|
132
|
+
const detailStr = formatDetail(detail);
|
|
133
|
+
const message = `%c[${channel}] %c${event}%c ${detailStr}`;
|
|
134
|
+
const channelStyle = `color:${color}; font-weight:bold`;
|
|
135
|
+
const eventStyle = level === "error" ? "color:#e94e4e; font-weight:bold" : level === "warn" ? "color:#f5a623; font-weight:bold" : "color:#fff; font-weight:bold";
|
|
136
|
+
const detailStyle = "color:#999; font-weight:normal";
|
|
137
|
+
if (level === "error") {
|
|
138
|
+
(_b = browserConsole == null ? void 0 : browserConsole.error) == null ? void 0 : _b.call(browserConsole, message, channelStyle, eventStyle, detailStyle);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (level === "warn") {
|
|
142
|
+
(_c = browserConsole == null ? void 0 : browserConsole.warn) == null ? void 0 : _c.call(browserConsole, message, channelStyle, eventStyle, detailStyle);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
(_d = browserConsole == null ? void 0 : browserConsole.log) == null ? void 0 : _d.call(browserConsole, message, channelStyle, eventStyle, detailStyle);
|
|
146
|
+
}
|
|
147
|
+
function emitToPostHog(level, channel, event, detail) {
|
|
148
|
+
if (!otelLogger) return;
|
|
149
|
+
const severityText = level === "warn" ? "WARNING" : level === "error" ? "ERROR" : "INFO";
|
|
150
|
+
const attributes = flattenAttributes(__spreadValues({ channel }, detail));
|
|
151
|
+
otelLogger.emit({
|
|
152
|
+
severityText,
|
|
153
|
+
body: event,
|
|
154
|
+
attributes
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
function emit(level, channel, event, detail, options) {
|
|
158
|
+
var _a;
|
|
159
|
+
const shouldShip = ((_a = options == null ? void 0 : options.shipToPostHog) != null ? _a : level !== "info") && isPostHogShippingEnabled();
|
|
160
|
+
if (level !== "info" || isConsoleEnabled()) {
|
|
161
|
+
emitConsole(level, channel, event, detail);
|
|
162
|
+
}
|
|
163
|
+
if (shouldShip) {
|
|
164
|
+
emitToPostHog(level, channel, event, detail);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
function log(channel, event, detail = {}, options) {
|
|
168
|
+
emit("info", channel, event, detail, options);
|
|
169
|
+
}
|
|
170
|
+
function warn(channel, event, detail = {}, options) {
|
|
171
|
+
emit("warn", channel, event, detail, options);
|
|
172
|
+
}
|
|
173
|
+
function error(channel, event, detail = {}, options) {
|
|
174
|
+
emit("error", channel, event, detail, options);
|
|
62
175
|
}
|
|
63
|
-
|
|
64
|
-
// src/tracking/MetaPixelTracker.tsx
|
|
65
|
-
import { useEffect } from "react";
|
|
66
|
-
import { usePathname } from "next/navigation";
|
|
67
176
|
|
|
68
177
|
// src/tracking/firePixelEvent.ts
|
|
69
178
|
var STORAGE_KEY = "ks_pud";
|
|
@@ -111,7 +220,7 @@ async function setPixelUserData(userData) {
|
|
|
111
220
|
function firePixelEvent(event, params, eventId) {
|
|
112
221
|
const fbq = getFbq();
|
|
113
222
|
if (!fbq) {
|
|
114
|
-
|
|
223
|
+
warn("meta-pixel", "PIXEL_EVENT_SKIPPED_FBQ_NOT_LOADED", { event });
|
|
115
224
|
return;
|
|
116
225
|
}
|
|
117
226
|
applyStoredUserData(fbq);
|
|
@@ -120,11 +229,61 @@ function firePixelEvent(event, params, eventId) {
|
|
|
120
229
|
if (params == null ? void 0 : params.contentCategory) normalized.content_category = params.contentCategory;
|
|
121
230
|
const customData = Object.keys(normalized).length > 0 ? normalized : void 0;
|
|
122
231
|
const eventData = eventId ? { eventID: eventId } : void 0;
|
|
123
|
-
|
|
232
|
+
log("meta-pixel", "PIXEL_EVENT_FIRED", __spreadValues(__spreadValues({
|
|
233
|
+
event
|
|
234
|
+
}, normalized), eventId ? { eventId } : {}), { shipToPostHog: true });
|
|
124
235
|
fbq("track", event, customData, eventData);
|
|
125
236
|
}
|
|
126
237
|
|
|
238
|
+
// src/tracking/MetaPixel.tsx
|
|
239
|
+
var FBEVENTS_URL = "https://connect.facebook.net/en_US/fbevents.js";
|
|
240
|
+
var PIXEL_SCRIPT = (pixelId) => `
|
|
241
|
+
!function(f,b,e,v,n,t,s)
|
|
242
|
+
{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
|
|
243
|
+
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
|
|
244
|
+
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
|
|
245
|
+
n.queue=[];t=b.createElement(e);t.async=!0;
|
|
246
|
+
t.src=v;s=b.getElementsByTagName(e)[0];
|
|
247
|
+
s.parentNode.insertBefore(t,s)}(window, document,'script','${FBEVENTS_URL}');
|
|
248
|
+
fbq('init', '${pixelId.replace(/'/g, "\\'")}');
|
|
249
|
+
window.__ks_pixel_ids = window.__ks_pixel_ids || [];
|
|
250
|
+
if (window.__ks_pixel_ids.indexOf('${pixelId.replace(/'/g, "\\'")}') === -1) {
|
|
251
|
+
window.__ks_pixel_ids.push('${pixelId.replace(/'/g, "\\'")}');
|
|
252
|
+
}
|
|
253
|
+
`;
|
|
254
|
+
function MetaPixel({ pixelId }) {
|
|
255
|
+
const raw = typeof pixelId === "string" ? pixelId.trim() : "";
|
|
256
|
+
const id = raw && raw !== "null" && /^\d+$/.test(raw) ? raw : "";
|
|
257
|
+
useEffect(() => {
|
|
258
|
+
if (!id) return;
|
|
259
|
+
log("meta-pixel", "PIXEL_INIT", { pixelId: id }, { shipToPostHog: true });
|
|
260
|
+
firePixelEvent("PageView");
|
|
261
|
+
}, [id]);
|
|
262
|
+
if (!id) {
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
|
|
266
|
+
Script,
|
|
267
|
+
{
|
|
268
|
+
id: "meta-pixel",
|
|
269
|
+
strategy: "afterInteractive",
|
|
270
|
+
dangerouslySetInnerHTML: { __html: PIXEL_SCRIPT(id) }
|
|
271
|
+
}
|
|
272
|
+
), /* @__PURE__ */ React.createElement("noscript", null, /* @__PURE__ */ React.createElement(
|
|
273
|
+
"img",
|
|
274
|
+
{
|
|
275
|
+
height: 1,
|
|
276
|
+
width: 1,
|
|
277
|
+
style: { display: "none" },
|
|
278
|
+
src: `https://www.facebook.com/tr?id=${id}&ev=PageView&noscript=1`,
|
|
279
|
+
alt: ""
|
|
280
|
+
}
|
|
281
|
+
)));
|
|
282
|
+
}
|
|
283
|
+
|
|
127
284
|
// src/tracking/MetaPixelTracker.tsx
|
|
285
|
+
import { useEffect as useEffect2 } from "react";
|
|
286
|
+
import { usePathname } from "next/navigation";
|
|
128
287
|
function slugToTitle(slug) {
|
|
129
288
|
return slug.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
130
289
|
}
|
|
@@ -164,7 +323,7 @@ var ROUTE_RULES = [
|
|
|
164
323
|
];
|
|
165
324
|
function MetaPixelTracker({ bookingUrl }) {
|
|
166
325
|
const pathname = usePathname();
|
|
167
|
-
|
|
326
|
+
useEffect2(() => {
|
|
168
327
|
for (const rule of ROUTE_RULES) {
|
|
169
328
|
const match = pathname.match(rule.pattern);
|
|
170
329
|
if (match) {
|
|
@@ -174,7 +333,7 @@ function MetaPixelTracker({ bookingUrl }) {
|
|
|
174
333
|
}
|
|
175
334
|
}
|
|
176
335
|
}, [pathname]);
|
|
177
|
-
|
|
336
|
+
useEffect2(() => {
|
|
178
337
|
if (!bookingUrl) return;
|
|
179
338
|
const handleClick = (e) => {
|
|
180
339
|
var _a;
|
|
@@ -192,7 +351,7 @@ function MetaPixelTracker({ bookingUrl }) {
|
|
|
192
351
|
// src/tracking/PostHogProvider.tsx
|
|
193
352
|
import posthog from "posthog-js";
|
|
194
353
|
import { PostHogProvider as PHProvider } from "posthog-js/react";
|
|
195
|
-
import { useEffect as
|
|
354
|
+
import { useEffect as useEffect3, Suspense } from "react";
|
|
196
355
|
import { usePathname as usePathname2, useSearchParams } from "next/navigation";
|
|
197
356
|
var DEFAULT_HOST = "https://us.i.posthog.com";
|
|
198
357
|
function resolvePageInfo(pathname) {
|
|
@@ -231,7 +390,7 @@ function resolvePageInfo(pathname) {
|
|
|
231
390
|
function PostHogPageviewTracker() {
|
|
232
391
|
const pathname = usePathname2();
|
|
233
392
|
const searchParams = useSearchParams();
|
|
234
|
-
|
|
393
|
+
useEffect3(() => {
|
|
235
394
|
if (!pathname) return;
|
|
236
395
|
const search = searchParams == null ? void 0 : searchParams.toString();
|
|
237
396
|
const url = window.location.origin + pathname + (search ? `?${search}` : "");
|
|
@@ -245,7 +404,7 @@ function PostHogPageviewTracker() {
|
|
|
245
404
|
return null;
|
|
246
405
|
}
|
|
247
406
|
function PostHogProvider({ apiKey, apiHost, accountId, accountName, environment, children }) {
|
|
248
|
-
|
|
407
|
+
useEffect3(() => {
|
|
249
408
|
posthog.init(apiKey, {
|
|
250
409
|
api_host: apiHost != null ? apiHost : DEFAULT_HOST,
|
|
251
410
|
person_profiles: "identified_only",
|
|
@@ -254,12 +413,47 @@ function PostHogProvider({ apiKey, apiHost, accountId, accountName, environment,
|
|
|
254
413
|
posthog.register(__spreadProps(__spreadValues(__spreadValues(__spreadValues({}, accountId !== void 0 && { account_id: accountId }), accountName && { account_name: accountName }), environment && { environment }), {
|
|
255
414
|
site_domain: window.location.hostname
|
|
256
415
|
}));
|
|
416
|
+
initializePostHogLogging({
|
|
417
|
+
apiKey,
|
|
418
|
+
apiHost: apiHost != null ? apiHost : DEFAULT_HOST,
|
|
419
|
+
serviceName: "keystone-customer-site",
|
|
420
|
+
environment,
|
|
421
|
+
accountId,
|
|
422
|
+
accountName
|
|
423
|
+
});
|
|
257
424
|
}, [apiKey, apiHost, accountId, accountName, environment]);
|
|
425
|
+
useEffect3(() => {
|
|
426
|
+
const onWindowError = (event) => {
|
|
427
|
+
error(
|
|
428
|
+
"global-client",
|
|
429
|
+
"WINDOW_ERROR",
|
|
430
|
+
{
|
|
431
|
+
message: event.message || "unknown_error",
|
|
432
|
+
filename: event.filename || "unknown_file",
|
|
433
|
+
lineno: event.lineno || 0,
|
|
434
|
+
colno: event.colno || 0,
|
|
435
|
+
stack: event.error instanceof Error ? event.error.stack || "" : ""
|
|
436
|
+
},
|
|
437
|
+
{ shipToPostHog: true }
|
|
438
|
+
);
|
|
439
|
+
};
|
|
440
|
+
const onUnhandledRejection = (event) => {
|
|
441
|
+
const reason = event.reason;
|
|
442
|
+
const payload = reason instanceof Error ? { message: reason.message, stack: reason.stack || "" } : { message: String(reason), stack: "" };
|
|
443
|
+
error("global-client", "UNHANDLED_REJECTION", payload, { shipToPostHog: true });
|
|
444
|
+
};
|
|
445
|
+
window.addEventListener("error", onWindowError);
|
|
446
|
+
window.addEventListener("unhandledrejection", onUnhandledRejection);
|
|
447
|
+
return () => {
|
|
448
|
+
window.removeEventListener("error", onWindowError);
|
|
449
|
+
window.removeEventListener("unhandledrejection", onUnhandledRejection);
|
|
450
|
+
};
|
|
451
|
+
}, []);
|
|
258
452
|
return /* @__PURE__ */ React.createElement(PHProvider, { client: posthog }, /* @__PURE__ */ React.createElement(Suspense, { fallback: null }, /* @__PURE__ */ React.createElement(PostHogPageviewTracker, null)), children);
|
|
259
453
|
}
|
|
260
454
|
|
|
261
455
|
// src/tracking/KeystoneAnalyticsTracker.tsx
|
|
262
|
-
import { useEffect as
|
|
456
|
+
import { useEffect as useEffect4 } from "react";
|
|
263
457
|
import { usePathname as usePathname3 } from "next/navigation";
|
|
264
458
|
|
|
265
459
|
// src/tracking/captureEvent.ts
|
|
@@ -274,7 +468,7 @@ function captureCustomEvent(event, properties) {
|
|
|
274
468
|
// src/tracking/KeystoneAnalyticsTracker.tsx
|
|
275
469
|
function KeystoneAnalyticsTracker({ bookingUrl }) {
|
|
276
470
|
const pathname = usePathname3();
|
|
277
|
-
|
|
471
|
+
useEffect4(() => {
|
|
278
472
|
if (!bookingUrl) return;
|
|
279
473
|
const handleClick = (e) => {
|
|
280
474
|
var _a;
|
|
@@ -318,6 +512,7 @@ function GoogleTagManager({ containerId }) {
|
|
|
318
512
|
)));
|
|
319
513
|
}
|
|
320
514
|
export {
|
|
515
|
+
CHANNEL_COLORS,
|
|
321
516
|
GoogleTagManager,
|
|
322
517
|
KeystoneAnalyticsTracker,
|
|
323
518
|
MetaPixel,
|
|
@@ -325,7 +520,10 @@ export {
|
|
|
325
520
|
PostHogProvider,
|
|
326
521
|
captureCustomEvent,
|
|
327
522
|
captureEvent,
|
|
523
|
+
error,
|
|
328
524
|
firePixelEvent,
|
|
329
|
-
|
|
525
|
+
log,
|
|
526
|
+
setPixelUserData,
|
|
527
|
+
warn
|
|
330
528
|
};
|
|
331
529
|
//# sourceMappingURL=index.js.map
|