@aranova/tracking-react 1.4.1 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -3
- package/dist/{bookings-DIu1ho6v.d.ts → bookings-B50X7GSG.d.ts} +20 -1
- package/dist/{bookings-CqCuuyP6.d.mts → bookings-n8UUzrak.d.mts} +20 -1
- package/dist/client.d.mts +4 -3
- package/dist/client.d.ts +4 -3
- package/dist/client.js +25 -4
- package/dist/client.js.map +1 -1
- package/dist/client.mjs +25 -4
- package/dist/client.mjs.map +1 -1
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +55 -37
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +54 -37
- package/dist/index.mjs.map +1 -1
- package/dist/{ingest-typed-D7UZr0EM.d.mts → ingest-typed-ABH28Ips.d.mts} +16 -2
- package/dist/{ingest-typed-D2S3Kb8m.d.ts → ingest-typed-vP-DqpxO.d.ts} +16 -2
- package/dist/{sales-hlcVTJSS.d.ts → sales-D4QRnpdz.d.ts} +1 -1
- package/dist/{sales-CxJVthx_.d.mts → sales-DByfvgzT.d.mts} +1 -1
- package/dist/sales.d.mts +2 -2
- package/dist/sales.d.ts +2 -2
- package/dist/sales.js +36 -36
- package/dist/sales.js.map +1 -1
- package/dist/sales.mjs +36 -36
- package/dist/sales.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -318,7 +318,14 @@ import { useBookingIntegration, useBookingSlots, useBookingSubmit } from "@arano
|
|
|
318
318
|
const booking = useBookingIntegration(ARANOVA_TRACKING_CONFIG);
|
|
319
319
|
const days = useBookingSlots(ARANOVA_TRACKING_CONFIG); // [{ date, weekday, morning, afternoon }]
|
|
320
320
|
const { status, outcome, submit } = useBookingSubmit(conversions.bookings, {
|
|
321
|
-
formSubmit: {
|
|
321
|
+
formSubmit: {
|
|
322
|
+
tracking,
|
|
323
|
+
formId: "booking-form",
|
|
324
|
+
// Your own questions, for our reporting only; never sent to the shop.
|
|
325
|
+
extraFields: [
|
|
326
|
+
{ name: "heardVia", type: "select", label: "How did you hear about us?", value: heardVia },
|
|
327
|
+
],
|
|
328
|
+
},
|
|
322
329
|
});
|
|
323
330
|
|
|
324
331
|
await submit({
|
|
@@ -339,7 +346,8 @@ await submit({
|
|
|
339
346
|
- `conversions` is the site's one `createSalesClient({ apiKey, endpoint, firing: getTrackingConfigRuntime(...) })`;
|
|
340
347
|
`.bookings` reads the rules from that runtime.
|
|
341
348
|
- `outcome.status`: `created` (the shop texts and emails the customer itself; send nothing of
|
|
342
|
-
your own), `pending` (same success; still being sent, the owner is alerted if it fails
|
|
349
|
+
your own), `pending` (same success; still being sent, the owner is alerted if it fails;
|
|
350
|
+
`status` turns `pending` as soon as the server says so, while the final answer is polled),
|
|
343
351
|
`failed` (success copy plus `outcome.fallbackUrl`, the prefilled shop page), `invalid`
|
|
344
352
|
(`outcome.message`, nothing sent), `stale` (the times changed; the config is refetched).
|
|
345
353
|
- `outcome.mode` (and `booking.mode` before submitting): `live` for every real customer;
|
|
@@ -349,9 +357,14 @@ await submit({
|
|
|
349
357
|
outcome (`created`, `rejected`, `unknown`, `failed`) to exercise each screen. The production
|
|
350
358
|
API ignores it. Test locally against the local API **and** the local CDN; the SDK warns in the
|
|
351
359
|
console when the endpoint is localhost but the config comes from production.
|
|
360
|
+
- `booking.options` arrive grouped by the shop's service category: each has `group` (the heading,
|
|
361
|
+
or `null`) and an optional `description`. `groupBookingOptions(booking.options)` returns
|
|
362
|
+
`[{ group, options }]` in order, so render one heading per group with its choices under it.
|
|
352
363
|
- `useBookingSlots` / `bookableSlots(rules, { timeZone })` offer exactly the portal's start hours,
|
|
353
364
|
judged by the shop's date. `useBookingSubmit` reuses one attempt key across a double-click or
|
|
354
|
-
a retry, and sends the visit's `form_submit` once: don't send your own for this form.
|
|
365
|
+
a retry, and sends the visit's `form_submit` once: don't send your own for this form. Add the
|
|
366
|
+
form's own questions with `formSubmit.extraFields`; a name the booking already reports
|
|
367
|
+
(`phone`, `email`, ...) is dropped.
|
|
355
368
|
- Ask for the last name separately, and a mobile number (the shop's confirmation text goes to it).
|
|
356
369
|
- Reports the `booking_integration` capability.
|
|
357
370
|
|
|
@@ -69,6 +69,10 @@ interface BookingOptionConfig {
|
|
|
69
69
|
/** What the site posts in `services`. */
|
|
70
70
|
key: string;
|
|
71
71
|
label: string;
|
|
72
|
+
/** The shop's service category; options arrive grouped, each category in one run. */
|
|
73
|
+
group: string | null;
|
|
74
|
+
/** Optional helper text under the label. */
|
|
75
|
+
description: string | null;
|
|
72
76
|
}
|
|
73
77
|
/** Where a booking went; decided by the API. A real customer always gets `live`. */
|
|
74
78
|
declare const BOOKING_MODES: readonly ["live", "test", "simulated"];
|
|
@@ -305,7 +309,15 @@ interface BookingFormSubmit {
|
|
|
305
309
|
};
|
|
306
310
|
/** The `<form id>`, so `form_start` and `form_submit` line up. */
|
|
307
311
|
formId: string;
|
|
312
|
+
/**
|
|
313
|
+
* The site's own questions (e.g. "How did you hear about us?"), appended to this
|
|
314
|
+
* `form_submit` for our reporting; never sent to the shop. A name the booking already
|
|
315
|
+
* reports (`phone`, `email`, ...) is dropped, so lead matching cannot be overridden.
|
|
316
|
+
*/
|
|
317
|
+
extraFields?: FormSubmitField[];
|
|
308
318
|
}
|
|
319
|
+
/** One field of a `form_submit`. */
|
|
320
|
+
type FormSubmitField = NonNullable<FormSubmitMetadata["form"]["fields"]>[number];
|
|
309
321
|
type BookingOutcome =
|
|
310
322
|
/** The shop has the request; it texts and emails the customer itself. */
|
|
311
323
|
{
|
|
@@ -349,6 +361,13 @@ interface BookingSubmitOptions {
|
|
|
349
361
|
* fallback screens. The production API ignores it, so it can never change a real booking.
|
|
350
362
|
*/
|
|
351
363
|
simulate?: BookingSimulation;
|
|
364
|
+
/**
|
|
365
|
+
* Called once when the server answers `pending`, before `submit` polls for the final answer
|
|
366
|
+
* (up to ~30 s): show the pending success right away instead of a spinner.
|
|
367
|
+
*/
|
|
368
|
+
onPending?: (outcome: Extract<BookingOutcome, {
|
|
369
|
+
status: "pending";
|
|
370
|
+
}>) => void;
|
|
352
371
|
}
|
|
353
372
|
interface SalesBookingsClient {
|
|
354
373
|
/**
|
|
@@ -363,4 +382,4 @@ interface SalesBookingsClient {
|
|
|
363
382
|
/** A fresh per-submit key. Keep it for retries of the same submit; mint a new one after. */
|
|
364
383
|
declare const newBookingAttemptKey: typeof uuidV4;
|
|
365
384
|
|
|
366
|
-
export { type BookingDropOff as B, type ConversionConfig as C, type SalesBookingsClient as S, type TrackingConfigReference as T, type BookingFormSubmit as a, type BookingInput as b, type BookingMode as c, type BookingOutcome as d, type BookingSimulation as e, type BookingSubmitOptions as f, type ConversionConfigStore as g, getTrackingConfigRuntime as h, resolveTrackingConfigUrl as i, type BookingDayWindows as j, type ConversionIntegrations as k, TrackingConfigRuntime as l, newBookingAttemptKey as n, resolveConversionConfig as r };
|
|
385
|
+
export { type BookingDropOff as B, type ConversionConfig as C, type FormSubmitField as F, type SalesBookingsClient as S, type TrackingConfigReference as T, type BookingFormSubmit as a, type BookingInput as b, type BookingMode as c, type BookingOutcome as d, type BookingSimulation as e, type BookingSubmitOptions as f, type ConversionConfigStore as g, getTrackingConfigRuntime as h, resolveTrackingConfigUrl as i, type BookingDayWindows as j, type ConversionIntegrations as k, TrackingConfigRuntime as l, newBookingAttemptKey as n, resolveConversionConfig as r };
|
|
@@ -69,6 +69,10 @@ interface BookingOptionConfig {
|
|
|
69
69
|
/** What the site posts in `services`. */
|
|
70
70
|
key: string;
|
|
71
71
|
label: string;
|
|
72
|
+
/** The shop's service category; options arrive grouped, each category in one run. */
|
|
73
|
+
group: string | null;
|
|
74
|
+
/** Optional helper text under the label. */
|
|
75
|
+
description: string | null;
|
|
72
76
|
}
|
|
73
77
|
/** Where a booking went; decided by the API. A real customer always gets `live`. */
|
|
74
78
|
declare const BOOKING_MODES: readonly ["live", "test", "simulated"];
|
|
@@ -305,7 +309,15 @@ interface BookingFormSubmit {
|
|
|
305
309
|
};
|
|
306
310
|
/** The `<form id>`, so `form_start` and `form_submit` line up. */
|
|
307
311
|
formId: string;
|
|
312
|
+
/**
|
|
313
|
+
* The site's own questions (e.g. "How did you hear about us?"), appended to this
|
|
314
|
+
* `form_submit` for our reporting; never sent to the shop. A name the booking already
|
|
315
|
+
* reports (`phone`, `email`, ...) is dropped, so lead matching cannot be overridden.
|
|
316
|
+
*/
|
|
317
|
+
extraFields?: FormSubmitField[];
|
|
308
318
|
}
|
|
319
|
+
/** One field of a `form_submit`. */
|
|
320
|
+
type FormSubmitField = NonNullable<FormSubmitMetadata["form"]["fields"]>[number];
|
|
309
321
|
type BookingOutcome =
|
|
310
322
|
/** The shop has the request; it texts and emails the customer itself. */
|
|
311
323
|
{
|
|
@@ -349,6 +361,13 @@ interface BookingSubmitOptions {
|
|
|
349
361
|
* fallback screens. The production API ignores it, so it can never change a real booking.
|
|
350
362
|
*/
|
|
351
363
|
simulate?: BookingSimulation;
|
|
364
|
+
/**
|
|
365
|
+
* Called once when the server answers `pending`, before `submit` polls for the final answer
|
|
366
|
+
* (up to ~30 s): show the pending success right away instead of a spinner.
|
|
367
|
+
*/
|
|
368
|
+
onPending?: (outcome: Extract<BookingOutcome, {
|
|
369
|
+
status: "pending";
|
|
370
|
+
}>) => void;
|
|
352
371
|
}
|
|
353
372
|
interface SalesBookingsClient {
|
|
354
373
|
/**
|
|
@@ -363,4 +382,4 @@ interface SalesBookingsClient {
|
|
|
363
382
|
/** A fresh per-submit key. Keep it for retries of the same submit; mint a new one after. */
|
|
364
383
|
declare const newBookingAttemptKey: typeof uuidV4;
|
|
365
384
|
|
|
366
|
-
export { type BookingDropOff as B, type ConversionConfig as C, type SalesBookingsClient as S, type TrackingConfigReference as T, type BookingFormSubmit as a, type BookingInput as b, type BookingMode as c, type BookingOutcome as d, type BookingSimulation as e, type BookingSubmitOptions as f, type ConversionConfigStore as g, getTrackingConfigRuntime as h, resolveTrackingConfigUrl as i, type BookingDayWindows as j, type ConversionIntegrations as k, TrackingConfigRuntime as l, newBookingAttemptKey as n, resolveConversionConfig as r };
|
|
385
|
+
export { type BookingDropOff as B, type ConversionConfig as C, type FormSubmitField as F, type SalesBookingsClient as S, type TrackingConfigReference as T, type BookingFormSubmit as a, type BookingInput as b, type BookingMode as c, type BookingOutcome as d, type BookingSimulation as e, type BookingSubmitOptions as f, type ConversionConfigStore as g, getTrackingConfigRuntime as h, resolveTrackingConfigUrl as i, type BookingDayWindows as j, type ConversionIntegrations as k, TrackingConfigRuntime as l, newBookingAttemptKey as n, resolveConversionConfig as r };
|
package/dist/client.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode, CSSProperties, InputHTMLAttributes, ChangeEvent, FocusEvent, AnchorHTMLAttributes } from 'react';
|
|
3
3
|
import { G as GtagEnvironmentMap, M as MetaPixelEnvironmentMap, h as ConsentState, f as ConsentChoiceState, g as ConsentSource, T as TrackingParams, b as TrackingEnvironment, j as PhoneConfig, P as ParsedPhone, k as PhoneDisplayFormat } from './phone-utils-CM8eUPz8.mjs';
|
|
4
|
-
import { T as TrackingConfigReference, C as ConversionConfig, d as BookingOutcome, b as BookingInput, S as SalesBookingsClient, a as BookingFormSubmit, e as BookingSimulation } from './bookings-
|
|
5
|
-
import {
|
|
4
|
+
import { T as TrackingConfigReference, C as ConversionConfig, d as BookingOutcome, b as BookingInput, S as SalesBookingsClient, a as BookingFormSubmit, e as BookingSimulation } from './bookings-n8UUzrak.mjs';
|
|
5
|
+
import { X as TriggerRegistryConfig, Z as TypedTrackingClient, a as BookingHandoffPrefill, b as BookingIntegration, B as BookableDay } from './ingest-typed-ABH28Ips.mjs';
|
|
6
6
|
import { CountryCode } from 'libphonenumber-js';
|
|
7
7
|
import './form-submit-BLb28aCk.mjs';
|
|
8
8
|
import 'zod/mini';
|
|
@@ -414,7 +414,8 @@ interface BookingSubmitState {
|
|
|
414
414
|
/**
|
|
415
415
|
* Submit state for a booking form over `salesClient.bookings`. Owns the parts that are easy to
|
|
416
416
|
* get wrong: one attempt key per submit (a double-click never books twice), the visit's
|
|
417
|
-
* `form_submit`, the stale-config refetch, and the fallback link on failure.
|
|
417
|
+
* `form_submit`, the stale-config refetch, and the fallback link on failure. A `pending` answer
|
|
418
|
+
* shows at once (`status: "pending"`) while the final one is polled; the submit stays in flight.
|
|
418
419
|
*/
|
|
419
420
|
declare function useBookingSubmit(bookings: SalesBookingsClient, options?: {
|
|
420
421
|
formSubmit?: BookingFormSubmit;
|
package/dist/client.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode, CSSProperties, InputHTMLAttributes, ChangeEvent, FocusEvent, AnchorHTMLAttributes } from 'react';
|
|
3
3
|
import { G as GtagEnvironmentMap, M as MetaPixelEnvironmentMap, h as ConsentState, f as ConsentChoiceState, g as ConsentSource, T as TrackingParams, b as TrackingEnvironment, j as PhoneConfig, P as ParsedPhone, k as PhoneDisplayFormat } from './phone-utils-l8ey3Zdm.js';
|
|
4
|
-
import { T as TrackingConfigReference, C as ConversionConfig, d as BookingOutcome, b as BookingInput, S as SalesBookingsClient, a as BookingFormSubmit, e as BookingSimulation } from './bookings-
|
|
5
|
-
import {
|
|
4
|
+
import { T as TrackingConfigReference, C as ConversionConfig, d as BookingOutcome, b as BookingInput, S as SalesBookingsClient, a as BookingFormSubmit, e as BookingSimulation } from './bookings-B50X7GSG.js';
|
|
5
|
+
import { X as TriggerRegistryConfig, Z as TypedTrackingClient, a as BookingHandoffPrefill, b as BookingIntegration, B as BookableDay } from './ingest-typed-vP-DqpxO.js';
|
|
6
6
|
import { CountryCode } from 'libphonenumber-js';
|
|
7
7
|
import './form-submit-BLb28aCk.js';
|
|
8
8
|
import 'zod/mini';
|
|
@@ -414,7 +414,8 @@ interface BookingSubmitState {
|
|
|
414
414
|
/**
|
|
415
415
|
* Submit state for a booking form over `salesClient.bookings`. Owns the parts that are easy to
|
|
416
416
|
* get wrong: one attempt key per submit (a double-click never books twice), the visit's
|
|
417
|
-
* `form_submit`, the stale-config refetch, and the fallback link on failure.
|
|
417
|
+
* `form_submit`, the stale-config refetch, and the fallback link on failure. A `pending` answer
|
|
418
|
+
* shows at once (`status: "pending"`) while the final one is polled; the submit stays in flight.
|
|
418
419
|
*/
|
|
419
420
|
declare function useBookingSubmit(bookings: SalesBookingsClient, options?: {
|
|
420
421
|
formSubmit?: BookingFormSubmit;
|
package/dist/client.js
CHANGED
|
@@ -1035,7 +1035,14 @@ function parseBookingOption(value) {
|
|
|
1035
1035
|
if (!value || typeof value !== "object") return [];
|
|
1036
1036
|
const o = value;
|
|
1037
1037
|
if (typeof o.key !== "string" || !o.key || typeof o.label !== "string") return [];
|
|
1038
|
-
return [
|
|
1038
|
+
return [
|
|
1039
|
+
{
|
|
1040
|
+
key: o.key,
|
|
1041
|
+
label: o.label,
|
|
1042
|
+
group: typeof o.group === "string" && o.group ? o.group : null,
|
|
1043
|
+
description: typeof o.description === "string" && o.description ? o.description : null
|
|
1044
|
+
}
|
|
1045
|
+
];
|
|
1039
1046
|
}
|
|
1040
1047
|
function parseIntegrations(value) {
|
|
1041
1048
|
if (!value || typeof value !== "object") return {};
|
|
@@ -1739,7 +1746,12 @@ function getBookingIntegration(integrations) {
|
|
|
1739
1746
|
timezone: booking.timezone,
|
|
1740
1747
|
configVersion: booking.config_version,
|
|
1741
1748
|
rules,
|
|
1742
|
-
options: booking.options.map((option) => ({
|
|
1749
|
+
options: booking.options.map((option) => ({
|
|
1750
|
+
key: option.key,
|
|
1751
|
+
label: option.label,
|
|
1752
|
+
group: option.group,
|
|
1753
|
+
description: option.description
|
|
1754
|
+
})),
|
|
1743
1755
|
mode: booking.mode ?? "live"
|
|
1744
1756
|
};
|
|
1745
1757
|
}
|
|
@@ -3973,7 +3985,7 @@ function GoogleAdsTracking(props) {
|
|
|
3973
3985
|
var import_react6 = require("react");
|
|
3974
3986
|
|
|
3975
3987
|
// package.json
|
|
3976
|
-
var version = "1.
|
|
3988
|
+
var version = "1.6.0";
|
|
3977
3989
|
|
|
3978
3990
|
// ../tracking-core/src/phone-react.tsx
|
|
3979
3991
|
var import_react5 = require("react");
|
|
@@ -4296,7 +4308,16 @@ function useBookingSubmit(bookings, options = {}) {
|
|
|
4296
4308
|
if (inFlight.current) return inFlight.current;
|
|
4297
4309
|
attemptKey.current ?? (attemptKey.current = newBookingAttemptKey());
|
|
4298
4310
|
setSubmitting(true);
|
|
4299
|
-
const run = bookings.submit(input, {
|
|
4311
|
+
const run = bookings.submit(input, {
|
|
4312
|
+
attemptKey: attemptKey.current,
|
|
4313
|
+
formSubmit,
|
|
4314
|
+
simulate,
|
|
4315
|
+
// The server has it: show the pending success while the final answer is polled.
|
|
4316
|
+
onPending: (pending) => {
|
|
4317
|
+
setOutcome(pending);
|
|
4318
|
+
setSubmitting(false);
|
|
4319
|
+
}
|
|
4320
|
+
}).then((result) => {
|
|
4300
4321
|
const unrecorded = result.status === "invalid" || result.status === "stale" || result.status === "failed" && result.id === null;
|
|
4301
4322
|
if (!unrecorded) attemptKey.current = null;
|
|
4302
4323
|
setOutcome(result);
|