@metron-labs/quote-react 0.1.20 → 0.1.22
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/LICENSE +31 -31
- package/README.md +253 -222
- package/dist/app/EstimatingTools.js +23 -7
- package/dist/app/QuickQuote.js +21 -3
- package/dist/app/stages/BasketStage.js +9 -1
- package/dist/app/stages/EntryStage.js +6 -1
- package/dist/app/stages/ScheduleResultsStage.js +3 -0
- package/dist/embed/quote.js +6760 -6760
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/lib/analytics.d.ts +16 -0
- package/dist/lib/analytics.js +37 -0
- package/dist/lib/config.d.ts +9 -0
- package/dist/lib/productImage.js +19 -19
- package/dist/styles.css +6748 -6748
- package/dist/util/pricing.js +3 -4
- package/package.json +53 -53
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ export { default as EstimatingTools } from "./app/EstimatingTools";
|
|
|
4
4
|
export type { EstimatingToolsProps } from "./app/EstimatingTools";
|
|
5
5
|
export { QuoteProvider } from "./lib/QuoteProvider";
|
|
6
6
|
export type { QuoteConfig } from "./lib/config";
|
|
7
|
+
export { STEP_EVENT, DATALAYER_EVENT } from "./lib/analytics";
|
|
8
|
+
export type { Step, WidgetEvent, WidgetName } from "./lib/analytics";
|
|
7
9
|
export { ESTIMATOR_TOOLS } from "./components/estimators/registry";
|
|
8
10
|
export type { EstimatorToolId } from "./components/estimators/registry";
|
|
9
11
|
export type { EstimatorRequirement } from "./lib/estimators/types";
|
package/dist/index.js
CHANGED
|
@@ -5,4 +5,5 @@
|
|
|
5
5
|
export { default as QuickQuote } from "./app/QuickQuote";
|
|
6
6
|
export { default as EstimatingTools } from "./app/EstimatingTools";
|
|
7
7
|
export { QuoteProvider } from "./lib/QuoteProvider";
|
|
8
|
+
export { STEP_EVENT, DATALAYER_EVENT } from "./lib/analytics";
|
|
8
9
|
export { ESTIMATOR_TOOLS } from "./components/estimators/registry";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { RefObject } from "react";
|
|
2
|
+
export declare const STEP_EVENT = "metron:step";
|
|
3
|
+
export declare const DATALAYER_EVENT = "metron_step";
|
|
4
|
+
export type WidgetName = "quick-quote" | "estimating-tools";
|
|
5
|
+
export type Step = "viewed" | "method_selected" | "list_submitted" | "results_shown" | "error" | "calculator_selected" | "estimate_completed" | "basket_viewed" | "downloaded" | "quote_requested";
|
|
6
|
+
export interface WidgetEvent {
|
|
7
|
+
widget: WidgetName;
|
|
8
|
+
step: Step;
|
|
9
|
+
[field: string]: string | number | boolean | undefined;
|
|
10
|
+
}
|
|
11
|
+
export type Track = (step: Step, fields?: Omit<WidgetEvent, "widget" | "step">) => void;
|
|
12
|
+
/** The tracker for the widget a component sits in. Outside a widget, a no-op. */
|
|
13
|
+
export declare const TrackContext: import("react").Context<Track>;
|
|
14
|
+
export declare const useTrack: () => Track;
|
|
15
|
+
/** Creates the tracker a widget provides to its steps, reporting from its root element. */
|
|
16
|
+
export declare function useTracker(widget: WidgetName, root: RefObject<HTMLElement | null>): Track;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { createContext, useCallback, useContext } from "react";
|
|
2
|
+
import { getQuoteConfig } from "./config";
|
|
3
|
+
// Funnel events, so a host site can see where customers drop off. The widgets never load a
|
|
4
|
+
// tracker of their own: they only report steps, and the host's analytics decides what to do.
|
|
5
|
+
// Each event goes to up to three places:
|
|
6
|
+
//
|
|
7
|
+
// 1. A "metron:step" DOM event from the widget's root. It bubbles out of the script-tag
|
|
8
|
+
// build's shadow root (composed), so the host listens on the element or on document.
|
|
9
|
+
// 2. config.onEvent, for React hosts.
|
|
10
|
+
// 3. window.dataLayer, if the page already has one (Google Tag Manager), as
|
|
11
|
+
// { event: "metron_step", widget, step, ... }. Never created here.
|
|
12
|
+
//
|
|
13
|
+
// config.analytics "events-only" skips the dataLayer; "none" sends nothing at all.
|
|
14
|
+
//
|
|
15
|
+
// The step names and fields are a contract: hosts build GTM triggers on them, so rename one only
|
|
16
|
+
// alongside a new major embed version (see the v1 note in the Quote-Package README). Events carry
|
|
17
|
+
// counts and names only, never what a customer typed.
|
|
18
|
+
export const STEP_EVENT = "metron:step";
|
|
19
|
+
export const DATALAYER_EVENT = "metron_step";
|
|
20
|
+
/** The tracker for the widget a component sits in. Outside a widget, a no-op. */
|
|
21
|
+
export const TrackContext = createContext(() => { });
|
|
22
|
+
export const useTrack = () => useContext(TrackContext);
|
|
23
|
+
/** Creates the tracker a widget provides to its steps, reporting from its root element. */
|
|
24
|
+
export function useTracker(widget, root) {
|
|
25
|
+
return useCallback((step, fields = {}) => {
|
|
26
|
+
const config = getQuoteConfig();
|
|
27
|
+
const mode = config.analytics ?? "all";
|
|
28
|
+
if (mode === "none")
|
|
29
|
+
return;
|
|
30
|
+
const event = { ...fields, widget, step };
|
|
31
|
+
root.current?.dispatchEvent(new CustomEvent(STEP_EVENT, { detail: event, bubbles: true, composed: true }));
|
|
32
|
+
config.onEvent?.(event);
|
|
33
|
+
const dataLayer = window.dataLayer;
|
|
34
|
+
if (mode === "all" && Array.isArray(dataLayer))
|
|
35
|
+
dataLayer.push({ event: DATALAYER_EVENT, ...event });
|
|
36
|
+
}, [widget, root]);
|
|
37
|
+
}
|
package/dist/lib/config.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { WidgetEvent } from "./analytics";
|
|
1
2
|
export interface QuoteConfig {
|
|
2
3
|
/**
|
|
3
4
|
* Origin serving Metron's API, e.g. "https://api.metronlabs.ai". No trailing slash needed.
|
|
@@ -22,6 +23,14 @@ export interface QuoteConfig {
|
|
|
22
23
|
* { "--accent": "#ffc72c", "--navy": "#002e5f" }.
|
|
23
24
|
*/
|
|
24
25
|
theme?: Record<string, string>;
|
|
26
|
+
/**
|
|
27
|
+
* Funnel events (see analytics.ts). "all" (the default) dispatches metron:step DOM events,
|
|
28
|
+
* calls onEvent and pushes to window.dataLayer when the page has one; "events-only" skips the
|
|
29
|
+
* dataLayer; "none" sends nothing.
|
|
30
|
+
*/
|
|
31
|
+
analytics?: "all" | "events-only" | "none";
|
|
32
|
+
/** Called with each funnel event, e.g. to forward it to your own analytics. */
|
|
33
|
+
onEvent?: (event: WidgetEvent) => void;
|
|
25
34
|
}
|
|
26
35
|
/** Called by QuoteProvider. Not part of the public API. */
|
|
27
36
|
export declare function setModuleConfig(config: QuoteConfig): void;
|
package/dist/lib/productImage.js
CHANGED
|
@@ -23,26 +23,26 @@ export function productImageSrc(description, productId, pdpPhotoUrl) {
|
|
|
23
23
|
if (photo)
|
|
24
24
|
return assetUrl(photo.path);
|
|
25
25
|
if (text.includes("insulation")) {
|
|
26
|
-
return encodeSvg(`
|
|
27
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 420">
|
|
28
|
-
<rect width="640" height="420" fill="#fbf1cf"/>
|
|
29
|
-
<rect x="88" y="78" width="432" height="264" rx="16" fill="#f0c43f"/>
|
|
30
|
-
<rect x="120" y="110" width="368" height="200" rx="10" fill="#ffd95e"/>
|
|
31
|
-
<g stroke="#e2b12e" stroke-width="8" opacity="0.75">
|
|
32
|
-
<line x1="140" y1="140" x2="468" y2="140"/>
|
|
33
|
-
<line x1="140" y1="190" x2="468" y2="190"/>
|
|
34
|
-
<line x1="140" y1="240" x2="468" y2="240"/>
|
|
35
|
-
</g>
|
|
36
|
-
</svg>
|
|
26
|
+
return encodeSvg(`
|
|
27
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 420">
|
|
28
|
+
<rect width="640" height="420" fill="#fbf1cf"/>
|
|
29
|
+
<rect x="88" y="78" width="432" height="264" rx="16" fill="#f0c43f"/>
|
|
30
|
+
<rect x="120" y="110" width="368" height="200" rx="10" fill="#ffd95e"/>
|
|
31
|
+
<g stroke="#e2b12e" stroke-width="8" opacity="0.75">
|
|
32
|
+
<line x1="140" y1="140" x2="468" y2="140"/>
|
|
33
|
+
<line x1="140" y1="190" x2="468" y2="190"/>
|
|
34
|
+
<line x1="140" y1="240" x2="468" y2="240"/>
|
|
35
|
+
</g>
|
|
36
|
+
</svg>
|
|
37
37
|
`);
|
|
38
38
|
}
|
|
39
|
-
return encodeSvg(`
|
|
40
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 420">
|
|
41
|
-
<rect width="640" height="420" fill="#edf1f5"/>
|
|
42
|
-
<rect x="132" y="108" width="376" height="204" rx="18" fill="#d5dde6"/>
|
|
43
|
-
<rect x="168" y="144" width="304" height="24" rx="12" fill="#9aa6b2"/>
|
|
44
|
-
<rect x="168" y="188" width="250" height="24" rx="12" fill="#aab5c0"/>
|
|
45
|
-
<rect x="168" y="232" width="220" height="24" rx="12" fill="#aab5c0"/>
|
|
46
|
-
</svg>
|
|
39
|
+
return encodeSvg(`
|
|
40
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 420">
|
|
41
|
+
<rect width="640" height="420" fill="#edf1f5"/>
|
|
42
|
+
<rect x="132" y="108" width="376" height="204" rx="18" fill="#d5dde6"/>
|
|
43
|
+
<rect x="168" y="144" width="304" height="24" rx="12" fill="#9aa6b2"/>
|
|
44
|
+
<rect x="168" y="188" width="250" height="24" rx="12" fill="#aab5c0"/>
|
|
45
|
+
<rect x="168" y="232" width="220" height="24" rx="12" fill="#aab5c0"/>
|
|
46
|
+
</svg>
|
|
47
47
|
`);
|
|
48
48
|
}
|