diff --git a/package-lock.json b/package-lock.json index 9c5725c..5fe57c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "pages", - "version": "0.0.3", + "version": "0.0.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "pages", - "version": "0.0.3", + "version": "0.0.5", "license": "MIT", "devDependencies": { "@eslint/js": "^10.0.1", diff --git a/pages/chat/main.ts b/pages/chat/main.ts index e5c2193..72e98bd 100644 --- a/pages/chat/main.ts +++ b/pages/chat/main.ts @@ -26,8 +26,8 @@ const i18n = { attrTargetUrlDefault: 'app.doctorina.com', attrChildren: 'Child <p> elements: 1 = static placeholder, 2+ = typing animation', attrChildrenDefault: 'None', - attrParams: 'JSON object of extra query parameters (e.g. UTM tags)', - attrParamsDefault: 'None', + attrParams: 'JSON object of extra query parameters (e.g. UTM tags). Overrides defaults.', + attrParamsDefault: 'utm_medium=user_message', examples: 'Examples', exBasicTitle: 'Basic Usage', exBasicDesc: 'Minimal setup — just add the container and the script:', @@ -63,8 +63,8 @@ const i18n = { attrTargetUrlDefault: 'app.doctorina.com', attrChildren: 'Elementos hijos <p>: 1 = placeholder estático, 2+ = animación de escritura', attrChildrenDefault: 'Ninguno', - attrParams: 'Objeto JSON con parámetros extra (ej. etiquetas UTM)', - attrParamsDefault: 'Ninguno', + attrParams: 'Objeto JSON con parámetros extra (ej. etiquetas UTM). Sobrescribe los valores predeterminados.', + attrParamsDefault: 'utm_medium=user_message', examples: 'Ejemplos', exBasicTitle: 'Uso básico', exBasicDesc: 'Configuración mínima — solo agrega el contenedor y el script:', @@ -100,8 +100,8 @@ const i18n = { attrTargetUrlDefault: 'app.doctorina.com', attrChildren: 'Дочерние элементы <p>: 1 = статический placeholder, 2+ = анимация печатания', attrChildrenDefault: 'Нет', - attrParams: 'JSON-объект с дополнительными query-параметрами (напр. UTM-метки)', - attrParamsDefault: 'Нет', + attrParams: 'JSON-объект с дополнительными query-параметрами (напр. UTM-метки). Перекрывает значения по умолчанию.', + attrParamsDefault: 'utm_medium=user_message', examples: 'Примеры', exBasicTitle: 'Базовое подключение', exBasicDesc: 'Минимальная настройка — только контейнер и скрипт:', @@ -147,7 +147,7 @@ const SNIPPET_PLACEHOLDER = `
`; const SNIPPET_PARAMS = `
+ data-params='{"utm_source":"landing","utm_campaign":"spring"}'>
`; diff --git a/src/widget/tab-opener.ts b/src/widget/tab-opener.ts index 83713f6..329263a 100644 --- a/src/widget/tab-opener.ts +++ b/src/widget/tab-opener.ts @@ -1,18 +1,26 @@ import type { WidgetConfig } from './config'; +// The widget *is* the user-message medium — every redirect is the user pressing Send. +// Embedders override by passing utm_medium in data-params. +const DEFAULT_PARAMS: Readonly> = Object.freeze({ + utm_medium: 'user_message', +}); + function normalizeMessage(raw: string): string { return raw.trim().replace(/\s+/g, ' '); } +function effectiveParams(config: WidgetConfig): Record { + return { ...DEFAULT_PARAMS, ...(config.params ?? {}) }; +} + function buildTargetUrl(config: WidgetConfig, message?: string): string { const url = new URL(config.targetUrl); url.searchParams.set('auto_accept_policies', '1'); url.searchParams.set('referrer', window.location.href); - if (config.params) { - for (const [key, value] of Object.entries(config.params)) { - url.searchParams.set(key, value); - } + for (const [key, value] of Object.entries(effectiveParams(config))) { + url.searchParams.set(key, value); } if (message) { @@ -43,9 +51,7 @@ export function openTarget(config: WidgetConfig, message: string): void { if (text) { payload.message = text; } - if (config.params) { - payload.params = config.params; - } + payload.params = effectiveParams(config); newTab.name = JSON.stringify(payload); newTab.location.href = buildTargetUrl(config); } else {