@azzas/azzas-tracker-web 1.0.71 → 1.0.73

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
@@ -1,130 +1,130 @@
1
- # azzas-tracker-web
2
-
3
- Pacote interno para **Data Tracking** das lojas WEB, centralizando a captura e envio de eventos para diferentes plataformas de mídia (Meta, Dito, DataLayer, etc).
4
-
5
- O objetivo é fornecer uma **camada única e consistente de tracking**, garantindo que todos os eventos sejam tratados, formatados e enviados de forma confiável.
6
-
7
- E, principalmente, centralizar a complexidade e a “inteligência” de tracking **fora dos repositórios das lojas**.
8
-
9
- ---
10
-
11
- ## Fluxo do Tracking
12
-
13
- O pacote segue o seguinte fluxo de eventos:
14
-
15
- 1. **User Action**
16
- Ações do usuário na loja (ex: adicionar ao carrinho, iniciar checkout, finalizar compra).
17
-
18
- 2. **Tracks**
19
- Ponto central que recebe o contexto do evento vindo da ação do usuário e encaminha para o *Formatter*.
20
-
21
- 3. **Formatter**
22
- Acessa a constante `EVENTS` e, baseado no contexto do evento, puxa os parâmetros obrigatórios e entrega a biblioteca de parâmetros (`/params`).
23
-
24
- 4. **Params Library**
25
- Contém **getters** e **resolvers** que garantem que os dados sejam legítimos e que todos os parâmetros sejam corretamente tratados.
26
-
27
- 5. **Adapters**
28
- Módulos responsáveis por enviar os dados formatados para cada destino (Meta, Datalayer, Dito, etc).
29
-
30
- ![FLUXOGRAMA](/public/fluxograma-lib-params.png)
31
-
32
- ## Instalação
33
-
34
-
35
- ```bash
36
- npm install /path/azzas-tracker-web
37
- ```
38
-
39
-
40
- ## Exemplos
41
-
42
- Listagem dos `EVENTS` e função orquestradora `trackWebEvent`:
43
- ```javascript
44
- const EVENTS = {
45
- ADD_PERSONAL_INFO: {
46
- name: 'add_personal_info',
47
- destinations: ['DataLayer'],
48
- requiredParams: ['brand', 'pre_filled', 'currency', 'value', 'subtotal'],
49
- },
50
- VIEW_CART: {
51
- name: 'add_personal_info',
52
- destinations: ['DataLayer', 'Meta', 'Dito'],
53
- requiredParams: ['....'],
54
- }
55
- }
56
-
57
- export async function trackWebEvent(event: EventName, context: EventContext = {}) {
58
- try {
59
- const parameters = await getParameters(context, event);
60
- return await dispatchTrackEvent(event, parameters);
61
- } catch (err) {
62
- return console.error(`[DT] Error tracking event ${event}:`, err);
63
- }
64
- }
65
- ```
66
-
67
- Uso básico da função no consumidor:
68
-
69
-
70
- ```javascript
71
- import { trackWebEvent } from 'azzas-tracker-web';
72
-
73
- // DATA TRACKING | add_personal_info at submit (pre-filled always false)
74
- // @see notion document for more details:
75
- const form: Element = document.querySelector('xxxxxx');
76
- if (form) {
77
- form.addEventListener('submit', () => {
78
- trackWebEvent('ADD_PERSONAL_INFO', { preFilled: false, orderForm: vtexjs.checkout.orderForm });
79
- });
80
- }
81
- ```
82
-
83
- ***OBS***: atente-se ao adicionar eventos novos e contribua na documentação do NOTION ou apenas DOCUMENTE em algum lugar! Seu futuro EU será grato 👍
84
-
85
- ## Teste Local para Ambientes CDN/DENO
86
-
87
- Para testar alterações na biblioteca localmente, simulando a forma como ela é carregada por uma CDN (<script src="...">), use o script npm run dev:deno.
88
-
89
- Este comando realiza o build mais recente da biblioteca, empacota-o e inicia um servidor HTTP local usando o Deno para servir o arquivo
90
-
91
- 1. Aqui nesse repositório, rode o script que inicia o servidor local:
92
-
93
- ```bash
94
- npm run dev:deno
95
- ```
96
-
97
- O servidor será iniciado e começará a servir o seu arquivo de build no seguinte endereço: http://localhost:4507/.
98
-
99
- 2. No Projeto Consumidor (DENO/FRONT):
100
-
101
- Altere o link do <script> no seu projeto para apontar para o servidor local.
102
-
103
- Você deve usar: <script src="http://localhost:4507/dist/mod.global.js"></script>
104
-
105
-
106
- ## Boas Práticas
107
- - Sempre garantir que os `requiredParams` de cada evento estejam preenchidos antes de enviar.
108
-
109
- - Procure sempre manter o envio das ações de usuário o mais ***genérico*** possível. Toda a inteligência e complexidade do tratamento dos dados deve ficar centralizada na lib, e não nos repositórios das lojas.
110
-
111
- - Usar nomes de eventos semânticos e consistentes (ex: VIEW_CART, ADD_PAYMENT_INFO).
112
-
113
- - Manter os contextos enxutos, enviando apenas dados realmente necessários.
114
-
115
- - Cada novo evento deve ser registrado em `EVENTS` com seus destinos e parâmetros obrigatórios. Essa constante talvez venha a ser dinâmica dependendo da MARCA utilizada
116
-
117
-
118
- ## Contribuição
119
-
120
- - Adicionar novos eventos em `EVENTS`.
121
-
122
- - Criar adapter correspondente caso seja necessário integrar com nova plataforma. Nesse caso deve-se avaliar qual será o serviço feito, o que será consumido, para onde será enviado.
123
-
124
- - Garantir que todos os parâmetros obrigatórios estejam mapeados nos getters/resolvers.
125
-
126
- - Executar build (npm run build) antes de testar no checkout/loja.
127
-
128
- ## Authors
129
-
130
- - Lucas Soares
1
+ # azzas-tracker-web
2
+
3
+ Pacote interno para **Data Tracking** das lojas WEB, centralizando a captura e envio de eventos para diferentes plataformas de mídia (Meta, Dito, DataLayer, etc).
4
+
5
+ O objetivo é fornecer uma **camada única e consistente de tracking**, garantindo que todos os eventos sejam tratados, formatados e enviados de forma confiável.
6
+
7
+ E, principalmente, centralizar a complexidade e a “inteligência” de tracking **fora dos repositórios das lojas**.
8
+
9
+ ---
10
+
11
+ ## Fluxo do Tracking
12
+
13
+ O pacote segue o seguinte fluxo de eventos:
14
+
15
+ 1. **User Action**
16
+ Ações do usuário na loja (ex: adicionar ao carrinho, iniciar checkout, finalizar compra).
17
+
18
+ 2. **Tracks**
19
+ Ponto central que recebe o contexto do evento vindo da ação do usuário e encaminha para o *Formatter*.
20
+
21
+ 3. **Formatter**
22
+ Acessa a constante `EVENTS` e, baseado no contexto do evento, puxa os parâmetros obrigatórios e entrega a biblioteca de parâmetros (`/params`).
23
+
24
+ 4. **Params Library**
25
+ Contém **getters** e **resolvers** que garantem que os dados sejam legítimos e que todos os parâmetros sejam corretamente tratados.
26
+
27
+ 5. **Adapters**
28
+ Módulos responsáveis por enviar os dados formatados para cada destino (Meta, Datalayer, Dito, etc).
29
+
30
+ ![FLUXOGRAMA](/public/fluxograma-lib-params.png)
31
+
32
+ ## Instalação
33
+
34
+
35
+ ```bash
36
+ npm install /path/azzas-tracker-web
37
+ ```
38
+
39
+
40
+ ## Exemplos
41
+
42
+ Listagem dos `EVENTS` e função orquestradora `trackWebEvent`:
43
+ ```javascript
44
+ const EVENTS = {
45
+ ADD_PERSONAL_INFO: {
46
+ name: 'add_personal_info',
47
+ destinations: ['DataLayer'],
48
+ requiredParams: ['brand', 'pre_filled', 'currency', 'value', 'subtotal'],
49
+ },
50
+ VIEW_CART: {
51
+ name: 'add_personal_info',
52
+ destinations: ['DataLayer', 'Meta', 'Dito'],
53
+ requiredParams: ['....'],
54
+ }
55
+ }
56
+
57
+ export async function trackWebEvent(event: EventName, context: EventContext = {}) {
58
+ try {
59
+ const parameters = await getParameters(context, event);
60
+ return await dispatchTrackEvent(event, parameters);
61
+ } catch (err) {
62
+ return console.error(`[DT] Error tracking event ${event}:`, err);
63
+ }
64
+ }
65
+ ```
66
+
67
+ Uso básico da função no consumidor:
68
+
69
+
70
+ ```javascript
71
+ import { trackWebEvent } from 'azzas-tracker-web';
72
+
73
+ // DATA TRACKING | add_personal_info at submit (pre-filled always false)
74
+ // @see notion document for more details:
75
+ const form: Element = document.querySelector('xxxxxx');
76
+ if (form) {
77
+ form.addEventListener('submit', () => {
78
+ trackWebEvent('ADD_PERSONAL_INFO', { preFilled: false, orderForm: vtexjs.checkout.orderForm });
79
+ });
80
+ }
81
+ ```
82
+
83
+ ***OBS***: atente-se ao adicionar eventos novos e contribua na documentação do NOTION ou apenas DOCUMENTE em algum lugar! Seu futuro EU será grato 👍
84
+
85
+ ## Teste Local para Ambientes CDN/DENO
86
+
87
+ Para testar alterações na biblioteca localmente, simulando a forma como ela é carregada por uma CDN (<script src="...">), use o script npm run dev:deno.
88
+
89
+ Este comando realiza o build mais recente da biblioteca, empacota-o e inicia um servidor HTTP local usando o Deno para servir o arquivo
90
+
91
+ 1. Aqui nesse repositório, rode o script que inicia o servidor local:
92
+
93
+ ```bash
94
+ npm run dev:deno
95
+ ```
96
+
97
+ O servidor será iniciado e começará a servir o seu arquivo de build no seguinte endereço: http://localhost:4507/.
98
+
99
+ 2. No Projeto Consumidor (DENO/FRONT):
100
+
101
+ Altere o link do <script> no seu projeto para apontar para o servidor local.
102
+
103
+ Você deve usar: <script src="http://localhost:4507/dist/mod.global.js"></script>
104
+
105
+
106
+ ## Boas Práticas
107
+ - Sempre garantir que os `requiredParams` de cada evento estejam preenchidos antes de enviar.
108
+
109
+ - Procure sempre manter o envio das ações de usuário o mais ***genérico*** possível. Toda a inteligência e complexidade do tratamento dos dados deve ficar centralizada na lib, e não nos repositórios das lojas.
110
+
111
+ - Usar nomes de eventos semânticos e consistentes (ex: VIEW_CART, ADD_PAYMENT_INFO).
112
+
113
+ - Manter os contextos enxutos, enviando apenas dados realmente necessários.
114
+
115
+ - Cada novo evento deve ser registrado em `EVENTS` com seus destinos e parâmetros obrigatórios. Essa constante talvez venha a ser dinâmica dependendo da MARCA utilizada
116
+
117
+
118
+ ## Contribuição
119
+
120
+ - Adicionar novos eventos em `EVENTS`.
121
+
122
+ - Criar adapter correspondente caso seja necessário integrar com nova plataforma. Nesse caso deve-se avaliar qual será o serviço feito, o que será consumido, para onde será enviado.
123
+
124
+ - Garantir que todos os parâmetros obrigatórios estejam mapeados nos getters/resolvers.
125
+
126
+ - Executar build (npm run build) antes de testar no checkout/loja.
127
+
128
+ ## Authors
129
+
130
+ - Lucas Soares
package/dist/mod.cjs CHANGED
@@ -424,17 +424,55 @@ async function getItemSku(item) {
424
424
  return (_b = (_a = product[0].items.find((i) => i.name === item.skuName)) == null ? void 0 : _a.itemId) != null ? _b : null;
425
425
  }
426
426
  function getDiscount(item) {
427
- return item.discount || item.discount === 0 ? item.discount : parseFloat(Math.max(item.listPrice - item.sellingPrice, 0).toFixed(2)) / 100 || 0;
427
+ const strategies = [
428
+ // 1. listPrice - sellingPrice
429
+ () => {
430
+ if ((item == null ? void 0 : item.listPrice) != null && (item == null ? void 0 : item.sellingPrice) != null) {
431
+ const diff = Math.max(item.listPrice - item.sellingPrice, 0);
432
+ return diff ? parseFloat((diff / 100).toFixed(2)) : 0;
433
+ }
434
+ return null;
435
+ },
436
+ // 2. listPrice - price
437
+ () => {
438
+ if ((item == null ? void 0 : item.listPrice) != null && (item == null ? void 0 : item.price) != null) {
439
+ return Math.max(item.listPrice - item.price, 0);
440
+ }
441
+ return null;
442
+ },
443
+ // 3. desconto calculado.
444
+ () => (item == null ? void 0 : item.discount) || (item == null ? void 0 : item.discount) === 0 ? item.discount : null
445
+ ];
446
+ for (const getValue of strategies) {
447
+ const value = getValue();
448
+ if (value !== null && value !== void 0) {
449
+ return value;
450
+ }
451
+ }
452
+ return 0;
428
453
  }
429
454
  function getItemCategory(item) {
430
455
  const strategies = [
431
456
  () => {
432
- var _a;
433
- return ((_a = item == null ? void 0 : item.productCategories) == null ? void 0 : _a["39"]) === "BAZAR" ? "Sale" : "Cole\xE7\xE3o";
457
+ const stringCategories = ((item == null ? void 0 : item.categories) || (item == null ? void 0 : item.productCategories)).toString().toLowerCase();
458
+ const hasOutletSaleOrBazar = stringCategories.includes("outlet") || stringCategories.includes("sale") || stringCategories.includes("bazar");
459
+ return hasOutletSaleOrBazar ? (item == null ? void 0 : item.brand) === "By NV" ? "Outlet" : "Sale" : "Cole\xE7\xE3o";
434
460
  },
435
461
  () => item == null ? void 0 : item.item_category,
436
462
  () => item == null ? void 0 : item.category,
437
- () => item == null ? void 0 : item.categories[0]
463
+ () => item == null ? void 0 : item.categories[0],
464
+ () => {
465
+ var _a, _b;
466
+ const breadcrumb = (_b = (_a = item == null ? void 0 : item.itemOffered) == null ? void 0 : _a.breadcrumbList) == null ? void 0 : _b.itemListElement;
467
+ if (!Array.isArray(breadcrumb)) return null;
468
+ const level1 = breadcrumb.find((el) => {
469
+ const path = el == null ? void 0 : el.item;
470
+ if (!path) return false;
471
+ const parts = path.replace(/^\/|\/$/g, "").split("/");
472
+ return parts.length === 1;
473
+ });
474
+ return (level1 == null ? void 0 : level1.name) || null;
475
+ }
438
476
  ];
439
477
  for (const getValue of strategies) {
440
478
  const value = getValue();
@@ -448,18 +486,15 @@ function getItemCategory2(item) {
448
486
  const strategies = [
449
487
  () => Object.values((item == null ? void 0 : item.productCategories) || {}).pop(),
450
488
  // checkout select_item context
451
- () => {
452
- var _a;
453
- return (_a = Object.values((item == null ? void 0 : item.categories) || {}).pop()) == null ? void 0 : _a.slice(1, -1).replace(/\//g, ",");
454
- },
455
- //
489
+ () => Object.values((item == null ? void 0 : item.categories) || {}).pop(),
456
490
  () => {
457
491
  var _a, _b, _c, _d, _e;
458
492
  return (_e = (_d = (_c = (_b = (_a = item == null ? void 0 : item.category) == null ? void 0 : _a.split) == null ? void 0 : _b.call(_a, ">")) == null ? void 0 : _c[1]) == null ? void 0 : _d.trim) == null ? void 0 : _e.call(_d);
459
493
  },
460
494
  // deco select_item context
461
- () => item.item_category2
495
+ () => item.item_category2,
462
496
  // deco add_to_cart context PDP
497
+ () => item == null ? void 0 : item.subGrup
463
498
  ];
464
499
  for (const getValue of strategies) {
465
500
  const value = getValue();
@@ -575,24 +610,24 @@ async function itemsFromOrderForm(context) {
575
610
 
576
611
  // src/params/resolvers/items/fromItem.ts
577
612
  async function itemsFromItem(context, event) {
578
- var _a, _b, _c, _d, _e, _f;
613
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
579
614
  const { item, orderForm, itemListName } = context;
580
615
  return [
581
616
  {
582
617
  index: typeof (item == null ? void 0 : item.index) === "number" ? item.index : null,
583
618
  quantity: 1,
584
- item_id: (item == null ? void 0 : item.productId) || (item == null ? void 0 : item.item_group_id) || (item == null ? void 0 : item.sku) || null,
619
+ item_id: (item == null ? void 0 : item.productId) || (item == null ? void 0 : item.item_group_id) || (item == null ? void 0 : item.sku) || (item == null ? void 0 : item.id) || null,
585
620
  item_category2: getItemCategory2(item),
586
621
  item_category4: getItemCategory4(item),
587
622
  item_shipping_tier: event === "REMOVE_FROM_CART" ? getItemShippingTier(orderForm, item) : null,
588
623
  price: (item == null ? void 0 : item.listPrice) || (item == null ? void 0 : item.price) || 0,
589
- item_ref: (item == null ? void 0 : item.ref) || (item == null ? void 0 : item.refId) || (item == null ? void 0 : item.item_ref) || ((_a = item == null ? void 0 : item.additionalProperty) == null ? void 0 : _a.find((i) => i.name === "RefId").value) || null,
590
- item_brand: ((_b = item == null ? void 0 : item.additionalInfo) == null ? void 0 : _b.brandName) || (item == null ? void 0 : item.item_brand) || ((_c = item == null ? void 0 : item.brand) == null ? void 0 : _c.name) || null,
591
- item_sku: (item == null ? void 0 : item.sku) || (item == null ? void 0 : item.id) || (item == null ? void 0 : item.item_id) || await getItemSku(item) || null,
592
- item_name: (item == null ? void 0 : item.name) || (item == null ? void 0 : item.item_name) || null,
624
+ item_ref: (item == null ? void 0 : item.ref) || (item == null ? void 0 : item.refId) || (item == null ? void 0 : item.item_ref) || ((_a = item == null ? void 0 : item.additionalProperty) == null ? void 0 : _a.find((i) => i.name === "RefId").value) || ((_c = item == null ? void 0 : item.itemOffered) == null ? void 0 : _c.gtin.substring(0, (_b = item == null ? void 0 : item.itemOffered) == null ? void 0 : _b.gtin.lastIndexOf("_"))) || null,
625
+ item_brand: ((_d = item == null ? void 0 : item.additionalInfo) == null ? void 0 : _d.brandName) || (item == null ? void 0 : item.item_brand) || ((_e = item == null ? void 0 : item.brand) == null ? void 0 : _e.name) || ((_g = (_f = item == null ? void 0 : item.itemOffered) == null ? void 0 : _f.brand) == null ? void 0 : _g.name) || null,
626
+ item_sku: (item == null ? void 0 : item.sku) || ((_h = item == null ? void 0 : item.itemOffered) == null ? void 0 : _h.sku) || (item == null ? void 0 : item.item_id) || (item == null ? void 0 : item.id) || await getItemSku(item) || null,
627
+ item_name: (item == null ? void 0 : item.name) || (item == null ? void 0 : item.item_name) || ((_j = (_i = item == null ? void 0 : item.itemOffered) == null ? void 0 : _i.isVariantOf) == null ? void 0 : _j.name) || null,
593
628
  item_category: getItemCategory(item) || null,
594
- item_variant: ((item == null ? void 0 : item.skuName) || (item == null ? void 0 : item.item_variant) || (item == null ? void 0 : item.name)).split(/[-/]/)[0].trim() || null,
595
- item_variant2: (item == null ? void 0 : item.size) || ((_d = item == null ? void 0 : item.itemAttributes) == null ? void 0 : _d.size) || ((_f = (_e = (item == null ? void 0 : item.skuName) || (item == null ? void 0 : item.name)) == null ? void 0 : _e.split(/[-/]/).pop()) == null ? void 0 : _f.trim()) || null,
629
+ item_variant: ((item == null ? void 0 : item.skuName) || (item == null ? void 0 : item.item_variant) || (item == null ? void 0 : item.name) || (item == null ? void 0 : item.itemOffered.name)).split(/[-/]/)[0].trim() || null,
630
+ item_variant2: (item == null ? void 0 : item.size) || ((_k = item == null ? void 0 : item.itemAttributes) == null ? void 0 : _k.size) || ((_m = (_l = (item == null ? void 0 : item.skuName) || (item == null ? void 0 : item.name) || (item == null ? void 0 : item.itemOffered.name)) == null ? void 0 : _l.split(/[-/]/).pop()) == null ? void 0 : _m.trim()) || null,
596
631
  discount: getDiscount(item),
597
632
  item_list_name: itemListName || null,
598
633
  item_url: (item == null ? void 0 : item.item_url) || null
@@ -610,7 +645,7 @@ async function itemsFromList(context) {
610
645
  quantity: 1,
611
646
  item_ref: (item == null ? void 0 : item.ref) || (item == null ? void 0 : item.item_ref) || ((_e = item == null ? void 0 : item.referenceId) == null ? void 0 : _e[0].Value) || (item == null ? void 0 : item.productReference) || (item == null ? void 0 : item.additionalProperty.find((i) => i.name === "RefId").value) || null,
612
647
  index: typeof (context == null ? void 0 : context.index) === "number" ? context.index : Number(item == null ? void 0 : item.index),
613
- item_brand: item.isNotFarm ? item == null ? void 0 : item.item_brand : normalizeBrand((_f = item == null ? void 0 : item.brand) == null ? void 0 : _f.name) || normalizeBrand(context.brand) || normalizeBrand(item == null ? void 0 : item.item_brand) || null,
648
+ item_brand: (item == null ? void 0 : item.item_brand) ? item.item_brand : item.isNotFarm ? item == null ? void 0 : item.item_brand : normalizeBrand((_f = item == null ? void 0 : item.brand) == null ? void 0 : _f.name) || normalizeBrand(context.brand) || normalizeBrand(item == null ? void 0 : item.item_brand) || null,
614
649
  item_name: ((_g = item == null ? void 0 : item.productName) == null ? void 0 : _g.split(" - ").shift()) || ((_h = item == null ? void 0 : item.alternateName) == null ? void 0 : _h.split(" - ").shift()) || ((_i = item == null ? void 0 : item.item_name) == null ? void 0 : _i.split(" - ").shift()) || ((_k = (_j = item == null ? void 0 : item.seo) == null ? void 0 : _j.title) == null ? void 0 : _k.split(" - ").shift()) || null,
615
650
  item_category: getItemCategory(item) || null,
616
651
  item_variant: ((_m = (_l = item == null ? void 0 : item.name) == null ? void 0 : _l.split("-")) == null ? void 0 : _m[0].trim()) || (item == null ? void 0 : item.item_variant) || ((_o = (_n = item == null ? void 0 : item.productName) == null ? void 0 : _n.split("-")) == null ? void 0 : _o[1].trim()) || null,