@metodokorexmk/tracking 1.0.0 → 1.2.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 CHANGED
@@ -11,6 +11,8 @@ Sistema de tracking reutilizable para landing pages con **Google Analytics 4**,
11
11
  - 🖱️ **Click heatmap**: Captura coordenadas de clicks por sección.
12
12
  - 📝 **Form auto-tracking**: Detecta automáticamente inicio, campos y envío de formularios.
13
13
  - ⏱️ **Dwell time por sección**: Mide tiempo de permanencia con IntersectionObserver.
14
+ - 🎯 **Funnel tracking**: Quiz, Thank You Page y WhatsApp click (Regla 1).
15
+ - 🔗 **Attribution completa**: `campaign_id`, `adset_id`, `ad_id`, UTMs (Regla 3).
14
16
  - ⚛️ **Hooks React opcionales**: Import separado que no afecta a proyectos sin React.
15
17
  - 🔧 **Framework-agnostic**: Las capas core funcionan en cualquier entorno con DOM.
16
18
 
@@ -29,69 +31,70 @@ yarn add @metodokorexmk/tracking react-ga4
29
31
  ### Vanilla JavaScript / TypeScript
30
32
 
31
33
  ```ts
32
- import { initGA, trackPageView, trackEvent, createLandingTracker } from '@metodokorexmk/tracking'
34
+ import { initGA, trackPageView, trackEvent, createLandingTracker } from '@metodokorexmk/tracking';
33
35
 
34
36
  // 1. Inicializar GA4
35
- initGA({ trackingId: 'G-XXXXXXX' })
37
+ initGA({ trackingId: 'G-XXXXXXX' });
36
38
 
37
39
  // 2. Trackear pageview
38
- trackPageView('/mi-landing')
40
+ trackPageView('/mi-landing');
39
41
 
40
42
  // 3. Crear tracker completo para la landing
41
43
  const tracker = createLandingTracker({
42
44
  pagePath: '/mi-landing',
43
45
  pageName: 'Mi Landing Page',
44
46
  gtmId: 'GTM-XXXXXXX', // Opcional
45
- })
47
+ });
46
48
 
47
49
  // 4. Trackear eventos manuales
48
- trackEvent('CTA', 'click', 'Botón Principal')
50
+ trackEvent('CTA', 'click', 'Botón Principal');
49
51
 
50
52
  // 5. Al desmontar:
51
- tracker.destroy()
53
+ tracker.destroy();
52
54
  ```
53
55
 
54
56
  ### React / Next.js
55
57
 
56
58
  ```tsx
57
- import { initGA } from '@metodokorexmk/tracking'
58
- import { useLandingPageTracking, useVideoTracking } from '@metodokorexmk/tracking/react'
59
+ import { initGA } from '@metodokorexmk/tracking';
60
+ import { useLandingPageTracking, useVideoTracking } from '@metodokorexmk/tracking/react';
59
61
 
60
62
  // Inicializar una vez en la app
61
- initGA({ trackingId: 'G-XXXXXXX' })
63
+ initGA({ trackingId: 'G-XXXXXXX' });
62
64
 
63
65
  function MiLanding() {
64
66
  // Tracking automático de la landing
65
67
  const tracker = useLandingPageTracking({
66
68
  pagePath: '/mi-landing',
67
69
  pageName: 'Mi Landing Page',
68
- })
70
+ });
69
71
 
70
72
  // Tracking de video HTML5
71
- const videoRef = useRef<HTMLVideoElement>(null)
73
+ const videoRef = useRef<HTMLVideoElement>(null);
72
74
  const { progress, isPlaying } = useVideoTracking({
73
75
  videoId: 'hero-video',
74
76
  videoElement: videoRef.current,
75
77
  onComplete: () => console.log('Video completado'),
76
- })
78
+ });
77
79
 
78
80
  return (
79
81
  <>
80
82
  <video ref={videoRef} src="/video.mp4" />
81
- <button onClick={() => tracker?.trackCTAClick('Unirse', 'hero')}>
82
- Unirse
83
- </button>
83
+ <button onClick={() => tracker?.trackCTAClick('Unirse', 'hero')}>Unirse</button>
84
84
  </>
85
- )
85
+ );
86
86
  }
87
87
  ```
88
88
 
89
89
  ## Documentación
90
90
 
91
- | Doc | Descripción |
92
- |---|---|
93
- | [ARCHITECTURE.md](./docs/ARCHITECTURE.md) | Arquitectura de 4 capas, patrones de diseño, reglas de implementación y convenciones de código |
94
- | [INTEGRATION-GUIDE.md](./docs/INTEGRATION-GUIDE.md) | Guía paso a paso de integración + tabla de migración desde KOREX-WEB-PROD |
91
+ | Doc | Descripción |
92
+ | ------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
93
+ | [GUIA-COMPLETA.md](./docs/GUIA-COMPLETA.md) | Guía paso a paso completa: despliegue, integración y ejemplos |
94
+ | [ARCHITECTURE.md](./docs/ARCHITECTURE.md) | Arquitectura de 4 capas, patrones de diseño, reglas de implementación y convenciones de código |
95
+ | [INTEGRATION-GUIDE.md](./docs/INTEGRATION-GUIDE.md) | Guía paso a paso de integración + tabla de migración desde KOREX-WEB-PROD |
96
+ | [backend_rules_tracking.md](./docs/backend_rules_tracking.md) | Requerimientos de backend derivados de `rules_context.md` |
97
+ | [rules_context.md](./docs/rules_context.md) | Reglas de negocio del sistema de métricas de ads |
95
98
 
96
99
  ## Arquitectura
97
100
 
@@ -111,25 +114,25 @@ Core ← analytics (GA4), gtm, types
111
114
 
112
115
  ### Patrones de diseño aplicados
113
116
 
114
- | Patrón | Uso | Archivo |
115
- |---|---|---|
116
- | **Singleton** | Una instancia global de VideoTracker | `video-tracker.ts` |
117
- | **Factory** | `createLandingTracker(config)` crea instancias | `landing-tracker.ts` |
118
- | **Observer** | Callbacks `onUpdate()` en adaptadores de video | `wistia-adapter.ts`, `voomly-adapter.ts` |
119
- | **Strategy** | `resolveTrackingId` inyecta lógica de resolución de GA ID | `analytics.ts` |
120
- | **Dual Send** | Cada evento se envía por `gtag` + `ReactGA` simultáneamente | `analytics.ts` |
117
+ | Patrón | Uso | Archivo |
118
+ | ------------- | ----------------------------------------------------------- | ---------------------------------------- |
119
+ | **Singleton** | Una instancia global de VideoTracker | `video-tracker.ts` |
120
+ | **Factory** | `createLandingTracker(config)` crea instancias | `landing-tracker.ts` |
121
+ | **Observer** | Callbacks `onUpdate()` en adaptadores de video | `wistia-adapter.ts`, `voomly-adapter.ts` |
122
+ | **Strategy** | `resolveTrackingId` inyecta lógica de resolución de GA ID | `analytics.ts` |
123
+ | **Dual Send** | Cada evento se envía por `gtag` + `ReactGA` simultáneamente | `analytics.ts` |
121
124
 
122
125
  Ver [ARCHITECTURE.md](./docs/ARCHITECTURE.md) para detalles completos.
123
126
 
124
127
  ## Convenciones de nombrado de archivos
125
128
 
126
- | Tipo | Patrón | Ejemplo |
127
- |---|---|---|
128
- | Módulo core | `{nombre}.ts` | `analytics.ts`, `gtm.ts` |
129
- | Adaptador video | `{plataforma}-adapter.ts` | `wistia-adapter.ts` |
130
- | Clase tracker | `{nombre}-tracker.ts` | `video-tracker.ts` |
131
- | Hook React | `use-{nombre}.ts` | `use-landing-tracking.ts` |
132
- | Test unitario | `{módulo}.test.ts` | `analytics.test.ts` |
129
+ | Tipo | Patrón | Ejemplo |
130
+ | --------------- | ------------------------- | ------------------------- |
131
+ | Módulo core | `{nombre}.ts` | `analytics.ts`, `gtm.ts` |
132
+ | Adaptador video | `{plataforma}-adapter.ts` | `wistia-adapter.ts` |
133
+ | Clase tracker | `{nombre}-tracker.ts` | `video-tracker.ts` |
134
+ | Hook React | `use-{nombre}.ts` | `use-landing-tracking.ts` |
135
+ | Test unitario | `{módulo}.test.ts` | `analytics.test.ts` |
133
136
 
134
137
  > Todos los archivos usan **kebab-case**. Exports usan `camelCase` (funciones) y `PascalCase` (clases/tipos).
135
138
 
@@ -137,30 +140,36 @@ Ver [ARCHITECTURE.md](./docs/ARCHITECTURE.md) para detalles completos.
137
140
 
138
141
  ### Core (`@metodokorexmk/tracking`)
139
142
 
140
- | Export | Descripción |
141
- |---|---|
142
- | `initGA(config)` | Inicializa Google Analytics 4 |
143
- | `trackEvent(cat, action, label?, value?, data?)` | Envía evento a GA4 |
144
- | `trackPageView(path)` | Envía pageview |
145
- | `captureUTMParams()` | Extrae UTM params de la URL |
146
- | `captureUserIdFromURL()` | Lee `?user_id=` de la URL |
147
- | `createLandingTracker(config)` | Crea orquestador de sesión completa |
148
- | `trackWistiaByMediaId(id)` | Tracking de video Wistia |
149
- | `trackVoomlyByEmbedId(id)` | Tracking de video Voomly |
150
- | `trackHTML5Video(id, element)` | Tracking de `<video>` nativo |
151
- | `trackCTAClick(btn, section)` | Evento CTA click |
152
- | `trackFormSubmit(name, success)` | Evento formulario enviado |
153
- | `trackConversion(type, value?)` | Evento de conversión |
154
- | `pushToDataLayer(event, data)` | Push directo al GTM dataLayer |
155
- | `injectGTMScript(gtmId)` | Inyecta script de GTM |
143
+ | Export | Descripción |
144
+ | ------------------------------------------------ | ------------------------------------------------- |
145
+ | `initGA(config)` | Inicializa Google Analytics 4 |
146
+ | `trackEvent(cat, action, label?, value?, data?)` | Envía evento a GA4 |
147
+ | `trackPageView(path)` | Envía pageview |
148
+ | `captureUTMParams()` | Extrae UTM params de la URL |
149
+ | `captureUserIdFromURL()` | Lee `?user_id=` de la URL |
150
+ | `createLandingTracker(config)` | Crea orquestador de sesión completa |
151
+ | `trackWistiaByMediaId(id)` | Tracking de video Wistia |
152
+ | `trackVoomlyByEmbedId(id)` | Tracking de video Voomly |
153
+ | `trackHTML5Video(id, element)` | Tracking de `<video>` nativo |
154
+ | `trackCTAClick(btn, section)` | Evento CTA click |
155
+ | `trackFormSubmit(name, success)` | Evento formulario enviado |
156
+ | `trackConversion(type, value?)` | Evento de conversión |
157
+ | `trackQuizStart(quizName)` | Evento inicio de quiz |
158
+ | `trackQuizAnswer(quizName, index, answer)` | Evento respuesta a pregunta del quiz |
159
+ | `trackQuizComplete(quizName, total?, score?)` | Evento quiz completado |
160
+ | `trackThankYouPageVisit(source?)` | Evento visita a Thank You Page |
161
+ | `trackWhatsAppClick(phone?, section?)` | Evento clic en enlace WhatsApp |
162
+ | `extractUrlParams(url?)` | Extrae params de tracking incl. `adsetId`, `adId` |
163
+ | `pushToDataLayer(event, data)` | Push directo al GTM dataLayer |
164
+ | `injectGTMScript(gtmId)` | Inyecta script de GTM |
156
165
 
157
166
  ### React Hooks (`@metodokorexmk/tracking/react`)
158
167
 
159
- | Export | Descripción |
160
- |---|---|
161
- | `useLandingPageTracking(config)` | Hook orquestador de landing |
162
- | `useVideoTracking(options)` | Hook para HTML5 video |
163
- | `useWistiaVideoTracking(mediaId)` | Hook para Wistia video |
168
+ | Export | Descripción |
169
+ | --------------------------------- | --------------------------- |
170
+ | `useLandingPageTracking(config)` | Hook orquestador de landing |
171
+ | `useVideoTracking(options)` | Hook para HTML5 video |
172
+ | `useWistiaVideoTracking(mediaId)` | Hook para Wistia video |
164
173
 
165
174
  ## Calidad de código
166
175
 
@@ -175,11 +184,11 @@ npm run format:check # Verificar formato sin modificar
175
184
 
176
185
  ### Config
177
186
 
178
- | Herramienta | Config | Estilo |
179
- |---|---|---|
180
- | **ESLint** | `.eslintrc.json` | Airbnb base + TypeScript + Prettier |
181
- | **Prettier** | `.prettierrc` | `singleQuote`, `semi`, `printWidth: 140`, `tabWidth: 2` |
182
- | **TypeScript** | `tsconfig.json` | `strict: true`, ES2020, bundler module resolution |
187
+ | Herramienta | Config | Estilo |
188
+ | -------------- | ---------------- | ------------------------------------------------------- |
189
+ | **ESLint** | `.eslintrc.json` | Airbnb base + TypeScript + Prettier |
190
+ | **Prettier** | `.prettierrc` | `singleQuote`, `semi`, `printWidth: 140`, `tabWidth: 2` |
191
+ | **TypeScript** | `tsconfig.json` | `strict: true`, ES2020, bundler module resolution |
183
192
 
184
193
  ## Scripts
185
194
 
@@ -197,4 +206,3 @@ npm run format:check # Verificar formato
197
206
  ## Licencia
198
207
 
199
208
  MIT
200
-
package/dist/index.cjs CHANGED
@@ -259,7 +259,7 @@ var VideoTracker = class {
259
259
  this.watchTimeIntervals = /* @__PURE__ */ new Map();
260
260
  }
261
261
  /**
262
- * Inicializa el tracking para un video.
262
+ * Initializes tracking for a video.
263
263
  */
264
264
  initVideo(videoId) {
265
265
  if (this.videos.has(videoId)) return;
@@ -287,7 +287,7 @@ var VideoTracker = class {
287
287
  });
288
288
  }
289
289
  /**
290
- * Tracking de evento play.
290
+ * Tracks a play event.
291
291
  */
292
292
  trackPlay(videoId, currentTime = 0) {
293
293
  const state = this.getOrCreateState(videoId);
@@ -303,7 +303,7 @@ var VideoTracker = class {
303
303
  });
304
304
  }
305
305
  /**
306
- * Tracking de evento pause.
306
+ * Tracks a pause event.
307
307
  */
308
308
  trackPause(videoId, currentTime, duration) {
309
309
  const state = this.getOrCreateState(videoId);
@@ -325,7 +325,7 @@ var VideoTracker = class {
325
325
  });
326
326
  }
327
327
  /**
328
- * Tracking de evento seek (saltar en el timeline).
328
+ * Tracks a seek event (timeline jump).
329
329
  */
330
330
  trackSeek(videoId, fromTime, toTime) {
331
331
  const state = this.getOrCreateState(videoId);
@@ -340,7 +340,7 @@ var VideoTracker = class {
340
340
  });
341
341
  }
342
342
  /**
343
- * Tracking de progreso (milestones: 25%, 50%, 75%).
343
+ * Tracks progress milestones (25%, 50%, 75%).
344
344
  */
345
345
  trackProgress(videoId, percentage, currentTime) {
346
346
  const state = this.getOrCreateState(videoId);
@@ -356,7 +356,7 @@ var VideoTracker = class {
356
356
  }
357
357
  }
358
358
  /**
359
- * Tracking de completación del video (95%).
359
+ * Tracks video completion (>=95%).
360
360
  */
361
361
  trackComplete(videoId, totalDuration) {
362
362
  const state = this.getOrCreateState(videoId);
@@ -373,7 +373,7 @@ var VideoTracker = class {
373
373
  });
374
374
  }
375
375
  /**
376
- * Tracking de fin del video (evento ended nativo).
376
+ * Tracks video end (native ended event).
377
377
  */
378
378
  trackEnd(videoId) {
379
379
  const state = this.getOrCreateState(videoId);
@@ -386,7 +386,7 @@ var VideoTracker = class {
386
386
  });
387
387
  }
388
388
  /**
389
- * Tracking de cambio de velocidad de reproducción.
389
+ * Tracks playback speed change.
390
390
  */
391
391
  trackSpeedChange(videoId, speed) {
392
392
  const state = this.getOrCreateState(videoId);
@@ -397,7 +397,7 @@ var VideoTracker = class {
397
397
  });
398
398
  }
399
399
  /**
400
- * Tracking de pantalla completa.
400
+ * Tracks fullscreen toggle.
401
401
  */
402
402
  trackFullscreen(videoId, isFullscreen) {
403
403
  trackEvent("Video", isFullscreen ? "fullscreen_enter" : "fullscreen_exit", videoId, void 0, {
@@ -406,7 +406,7 @@ var VideoTracker = class {
406
406
  });
407
407
  }
408
408
  /**
409
- * Tracking de no interacción (el usuario está en la página pero no interactúa con el video).
409
+ * Tracks no interaction (user is on the page but not interacting with the video).
410
410
  */
411
411
  trackNoInteraction(videoId, timeOnPage) {
412
412
  trackEvent("Video", "no_interaction", videoId, void 0, {
@@ -415,20 +415,20 @@ var VideoTracker = class {
415
415
  });
416
416
  }
417
417
  /**
418
- * Obtiene el estado actual de un video.
418
+ * Returns the current state of a video.
419
419
  */
420
420
  getState(videoId) {
421
421
  return this.videos.get(videoId);
422
422
  }
423
423
  /**
424
- * Limpia el tracking de un video específico.
424
+ * Cleans up tracking for a specific video.
425
425
  */
426
426
  cleanup(videoId) {
427
427
  this.stopWatchTimeTracking(videoId);
428
428
  this.videos.delete(videoId);
429
429
  }
430
430
  /**
431
- * Limpia todo el tracking.
431
+ * Cleans up all video tracking.
432
432
  */
433
433
  cleanupAll() {
434
434
  for (const videoId of this.videos.keys()) {
@@ -436,7 +436,7 @@ var VideoTracker = class {
436
436
  }
437
437
  this.videos.clear();
438
438
  }
439
- // --- Métodos privados ---
439
+ // --- Private methods ---
440
440
  getOrCreateState(videoId) {
441
441
  if (!this.videos.has(videoId)) {
442
442
  this.initVideo(videoId);
@@ -559,6 +559,34 @@ var trackDownload = (fileName, fileType) => {
559
559
  file_type: fileType
560
560
  });
561
561
  };
562
+ var trackQuizStart = (quizName) => {
563
+ trackEvent("Quiz", "started", quizName, void 0, {
564
+ quiz_name: quizName
565
+ });
566
+ };
567
+ var trackQuizAnswer = (quizName, questionIndex, answer) => {
568
+ trackEvent("Quiz", "answer", quizName, questionIndex, {
569
+ quiz_name: quizName,
570
+ question_index: questionIndex,
571
+ answer
572
+ });
573
+ };
574
+ var trackQuizComplete = (quizName, totalQuestions, score) => {
575
+ trackEvent("Quiz", "completed", quizName, totalQuestions, {
576
+ quiz_name: quizName,
577
+ ...totalQuestions !== void 0 && { total_questions: totalQuestions },
578
+ ...score !== void 0 && { score }
579
+ });
580
+ };
581
+ var trackThankYouPageVisit = (source) => {
582
+ trackEvent("Funnel", "thank_you_page_visit", source);
583
+ };
584
+ var trackWhatsAppClick = (phoneNumber, section) => {
585
+ trackEvent("WhatsApp", "click", section, void 0, {
586
+ ...phoneNumber && { phone_number: phoneNumber },
587
+ ...section && { section }
588
+ });
589
+ };
562
590
 
563
591
  // src/trackers/wistia-adapter.ts
564
592
  var createStats = (timeWatched, completed) => ({
@@ -856,7 +884,7 @@ var LandingTracker = class {
856
884
  this.listeners = [];
857
885
  }
858
886
  /**
859
- * Inicializa el tracking de la landing con la configuración dada.
887
+ * Initializes landing page tracking with the given configuration.
860
888
  */
861
889
  init(config) {
862
890
  if (typeof window === "undefined") return;
@@ -892,7 +920,7 @@ var LandingTracker = class {
892
920
  this.trackSessionStart();
893
921
  }
894
922
  /**
895
- * Destruye el tracker y limpia todos los observers y listeners.
923
+ * Destroys the tracker and cleans up all observers and listeners.
896
924
  */
897
925
  destroy() {
898
926
  this.observers.forEach((obs) => obs.disconnect());
@@ -908,43 +936,43 @@ var LandingTracker = class {
908
936
  this.sectionTimers.clear();
909
937
  }
910
938
  // ====================================
911
- // MÉTODOS PÚBLICOS DE TRACKING
939
+ // PUBLIC TRACKING METHODS
912
940
  // ====================================
913
- /** Trackear click en un CTA */
941
+ /** Track a CTA click */
914
942
  trackCTAClick(buttonName, section, additionalData) {
915
943
  trackCTAClick(buttonName, section, additionalData);
916
944
  this.pushGTMEvent("cta_click", { button_text: buttonName, section });
917
945
  }
918
- /** Trackear conversión */
946
+ /** Track a conversion */
919
947
  trackConversion(type, value, additionalData) {
920
948
  trackEvent("Conversion", type, void 0, value, additionalData);
921
949
  this.pushGTMEvent("conversion", { conversion_type: type, value });
922
950
  }
923
- /** Trackear click en FAQs */
951
+ /** Track FAQ expansion */
924
952
  trackFAQExpand(question, index) {
925
953
  trackEvent("FAQ", "expand", question, index);
926
954
  }
927
- /** Trackear click social */
955
+ /** Track social link click */
928
956
  trackSocialClick(platform, action) {
929
957
  trackEvent("Social", "click", platform, void 0, { social_action: action });
930
958
  }
931
- /** Trackear click en imagen */
959
+ /** Track image click */
932
960
  trackImageClick(imageName, section) {
933
961
  trackEvent("Engagement", "image_click", imageName, void 0, { section });
934
962
  }
935
- /** Trackear scroll a sección */
963
+ /** Track scroll to a section */
936
964
  trackScrollTo(section) {
937
965
  trackEvent("Navigation", "scroll_to", section);
938
966
  }
939
- /** Trackear share */
967
+ /** Track content share */
940
968
  trackShare(platform, content) {
941
969
  trackEvent("Share", "click", platform, void 0, { share_content: content });
942
970
  }
943
- /** Trackear descarga */
971
+ /** Track file download */
944
972
  trackDownload(fileName, fileType) {
945
973
  trackEvent("Download", "click", fileName, void 0, { file_type: fileType });
946
974
  }
947
- /** Obtener datos de la sesión actual */
975
+ /** Get current session data */
948
976
  getSessionData() {
949
977
  return {
950
978
  duration: Math.round((Date.now() - this.sessionStartTime) / 1e3),
@@ -953,7 +981,7 @@ var LandingTracker = class {
953
981
  };
954
982
  }
955
983
  // ====================================
956
- // MÉTODOS PRIVADOS
984
+ // PRIVATE METHODS
957
985
  // ====================================
958
986
  captureInitialData() {
959
987
  const utmParams = captureUTMParams();
@@ -1141,7 +1169,7 @@ var initTrackingAPI = (config) => {
1141
1169
  };
1142
1170
  var getAPIConfig = () => {
1143
1171
  if (!apiConfig) {
1144
- throw new Error("[@metodokorexmk/tracking] initTrackingAPI() debe llamarse antes de usar funciones de persistencia.");
1172
+ throw new Error("[@metodokorexmk/tracking] initTrackingAPI() must be called before using persistence functions.");
1145
1173
  }
1146
1174
  return apiConfig;
1147
1175
  };
@@ -1197,11 +1225,14 @@ var extractUrlParams = (url) => {
1197
1225
  return {
1198
1226
  userId: "",
1199
1227
  idCampana: "",
1228
+ adsetId: "",
1229
+ adId: "",
1200
1230
  utmContent: "",
1201
1231
  fbclid: "",
1202
1232
  nombreNetworker: "",
1203
1233
  whatsapp: "",
1204
1234
  pipelineId: "",
1235
+ leadCampaign: "Funnel Organico",
1205
1236
  leadCampaing: "Funnel Organico",
1206
1237
  isOrganico: true
1207
1238
  };
@@ -1219,6 +1250,8 @@ var extractUrlParams = (url) => {
1219
1250
  }
1220
1251
  const userId = searchParams.get("user_id") || "";
1221
1252
  const idCampana = searchParams.get("campaign_id") || searchParams.get("utm_id") || "";
1253
+ const adsetId = searchParams.get("adset_id") || "";
1254
+ const adId = searchParams.get("ad_id") || "";
1222
1255
  const utmContent = searchParams.get("utm_content") || "";
1223
1256
  const fbclid = searchParams.get("fbclid") || "";
1224
1257
  const whatsapp = searchParams.get("whatsapp") || "";
@@ -1234,6 +1267,8 @@ var extractUrlParams = (url) => {
1234
1267
  return {
1235
1268
  userId,
1236
1269
  idCampana,
1270
+ adsetId,
1271
+ adId,
1237
1272
  utmContent,
1238
1273
  fbclid,
1239
1274
  nombreNetworker,
@@ -1244,6 +1279,7 @@ var extractUrlParams = (url) => {
1244
1279
  utmSource,
1245
1280
  utmMedium,
1246
1281
  utmCampaign,
1282
+ leadCampaign: leadCampaing,
1247
1283
  leadCampaing,
1248
1284
  isOrganico
1249
1285
  };
@@ -1286,6 +1322,12 @@ var buildTrackingRequestBody = (params, formData, origin, options) => {
1286
1322
  body.referringUserId = collaboratorId;
1287
1323
  body.referring_user_id = collaboratorId;
1288
1324
  }
1325
+ if (params.adsetId) body.adsetId = params.adsetId;
1326
+ if (params.adId) body.adId = params.adId;
1327
+ if (params.utmSource) body.utmSource = params.utmSource;
1328
+ if (params.utmMedium) body.utmMedium = params.utmMedium;
1329
+ if (params.utmCampaign) body.utmCampaign = params.utmCampaign;
1330
+ if (params.leadCampaign) body.leadCampaign = params.leadCampaign;
1289
1331
  if (params.pipelineId) {
1290
1332
  const parsed = parseInt(params.pipelineId, 10);
1291
1333
  if (!isNaN(parsed)) body.pipeline_id = parsed;
@@ -1384,7 +1426,7 @@ var DwellTimeTracker = class {
1384
1426
  this.boundVisibilityChange = this.handleVisibilityChange.bind(this);
1385
1427
  }
1386
1428
  /**
1387
- * Inicia el tracking del tiempo de permanencia.
1429
+ * Starts dwell time tracking.
1388
1430
  */
1389
1431
  start(config) {
1390
1432
  if (typeof window === "undefined") return;
@@ -1421,7 +1463,7 @@ var DwellTimeTracker = class {
1421
1463
  this.retryPendingUpdates();
1422
1464
  }
1423
1465
  /**
1424
- * Detiene el tracking y envía el tiempo acumulado.
1466
+ * Stops tracking and sends accumulated time.
1425
1467
  */
1426
1468
  stop() {
1427
1469
  if (this.startTime) {
@@ -1436,7 +1478,7 @@ var DwellTimeTracker = class {
1436
1478
  this.cleanup();
1437
1479
  }
1438
1480
  /**
1439
- * Obtiene el tiempo transcurrido en segundos (restando tiempo pausado).
1481
+ * Returns elapsed time in seconds (excluding paused time).
1440
1482
  */
1441
1483
  getElapsedTime() {
1442
1484
  if (!this.startTime) return 0;
@@ -1448,8 +1490,8 @@ var DwellTimeTracker = class {
1448
1490
  return Math.max(0, totalTime - currentPauseTime);
1449
1491
  }
1450
1492
  /**
1451
- * Actualiza manualmente el tiempo del video.
1452
- * Llamar desde el VideoTracker u otros adaptadores.
1493
+ * Manually updates video time.
1494
+ * Called from VideoTracker or other adapters.
1453
1495
  */
1454
1496
  updateVideoTime(videoTimeWatched, videoCompleted = false) {
1455
1497
  const hasNewTime = videoTimeWatched > this.videoTimeWatched;
@@ -1463,7 +1505,7 @@ var DwellTimeTracker = class {
1463
1505
  }
1464
1506
  }
1465
1507
  /**
1466
- * Actualiza el trackingDataId (útil cuando se obtiene después del registro).
1508
+ * Updates the trackingDataId (useful when obtained after registration).
1467
1509
  */
1468
1510
  updateTrackingId(trackingDataId) {
1469
1511
  if (!trackingDataId || typeof trackingDataId === "string" && trackingDataId.trim() === "") return;
@@ -1486,7 +1528,7 @@ var DwellTimeTracker = class {
1486
1528
  }
1487
1529
  }
1488
1530
  /**
1489
- * Limpia todos los listeners y timers.
1531
+ * Cleans up all listeners and timers.
1490
1532
  */
1491
1533
  destroy() {
1492
1534
  this.stop();
@@ -1546,7 +1588,7 @@ var DwellTimeTracker = class {
1546
1588
  const isNetworkError = err.name === "AbortError" || err.name === "TimeoutError" || err.name === "TypeError" && err.message?.includes("Failed to fetch");
1547
1589
  if (token) this.savePendingUpdate(elapsedTime);
1548
1590
  if (this.onError && !isNetworkError) {
1549
- this.onError(error instanceof Error ? error : new Error("Error desconocido"));
1591
+ this.onError(error instanceof Error ? error : new Error("Unknown error"));
1550
1592
  }
1551
1593
  } finally {
1552
1594
  this.isSending = false;
@@ -1766,12 +1808,17 @@ exports.trackHTML5Video = trackHTML5Video;
1766
1808
  exports.trackImageClick = trackImageClick;
1767
1809
  exports.trackPageView = trackPageView;
1768
1810
  exports.trackPricingCardClick = trackPricingCardClick;
1811
+ exports.trackQuizAnswer = trackQuizAnswer;
1812
+ exports.trackQuizComplete = trackQuizComplete;
1813
+ exports.trackQuizStart = trackQuizStart;
1769
1814
  exports.trackScrollTo = trackScrollTo;
1770
1815
  exports.trackSectionClick = trackSectionClick;
1771
1816
  exports.trackShare = trackShare;
1772
1817
  exports.trackSocialClick = trackSocialClick;
1818
+ exports.trackThankYouPageVisit = trackThankYouPageVisit;
1773
1819
  exports.trackTimeInSection = trackTimeInSection;
1774
1820
  exports.trackVoomlyByEmbedId = trackVoomlyByEmbedId;
1821
+ exports.trackWhatsAppClick = trackWhatsAppClick;
1775
1822
  exports.trackWistiaByMediaId = trackWistiaByMediaId;
1776
1823
  exports.updateTrackingLead = updateTrackingLead;
1777
1824
  exports.videoTracker = videoTracker;