All files / src/lib lead-fields.ts

100% Statements 11/11
100% Branches 8/8
100% Functions 2/2
100% Lines 9/9

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42                      4x                   51x 51x 663x 663x   51x 51x                 4x     52x    
// The lead-store fields (#1085) every www lead proxy forwards: first-touch
// attribution, entry type and offer, and the consent box. One picker so the
// three proxies (landing-lead, inquiry, book-consultation) can't drift — each
// used to hand-copy its own whitelist, and anything missing from one was
// silently dropped. The API validates every value; this only forwards
// well-typed ones.
import type { LeadFields } from "@interioring/api-types";
import { ATTRIBUTION_PARAMS } from "@interioring/utils/analytics/attribution";
 
// The UTM/click-id list is the shared one the browser captured with, so a
// new click id is added in one place.
const STRING_FIELDS = [
	...Object.values(ATTRIBUTION_PARAMS),
	"entryType",
	"offer",
	"priceTestArm",
	"city",
	"consentVersion",
] as const satisfies readonly (keyof LeadFields)[];
 
export function pickLeadFields(data: Record<string, unknown>): LeadFields {
	const out: LeadFields = {};
	for (const field of STRING_FIELDS) {
		const value = data[field];
		if (typeof value === "string" && value.trim()) out[field] = value.trim();
	}
	if (data.consent === true) out.consent = true;
	return out;
}
 
/**
 * Shown when a form arrives without the box ticked. The browser blocks this
 * first; the proxy answers a clear 400 instead of letting the API's 400 turn
 * into a generic 500. The API still enforces it either way.
 */
export const CONSENT_REQUIRED_ERROR =
	"Please tick the box to agree to be contacted.";
 
export function hasConsent(fields: LeadFields): boolean {
	return fields.consent === true && Boolean(fields.consentVersion);
}