@agenus-io/recovery 0.0.2 → 0.0.4
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 +426 -617
- package/package.json +13 -2
package/README.md
CHANGED
|
@@ -1,747 +1,556 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @agenus-io/recovery
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@agenus-io/recovery)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://www.typescriptlang.org/)
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
Sistema robusto de recuperação de abandono de formulários para capturar leads que não completaram o preenchimento. Detecta automaticamente quando usuários preenchem formulários mas não os enviam, capturando os dados preenchidos e enviando para sua API.
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
**Repositório**: [github.com/techionext/upsely-recovery](https://github.com/techionext/upsely-recovery)
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
## 🚀 Características
|
|
12
|
+
|
|
13
|
+
- ✅ **Detecção Automática**: Monitora interações do usuário com formulários automaticamente
|
|
14
|
+
- ✅ **Captura Inteligente**: Coleta dados de todos os campos preenchidos
|
|
15
|
+
- ✅ **Sessão Persistente**: Sistema de sessão com localStorage e cookies
|
|
16
|
+
- ✅ **Fingerprint de Dispositivo**: Identificação única do dispositivo
|
|
17
|
+
- ✅ **Envio Confiável**: Usa `sendBeacon` com fallback para `fetch` com `keepalive`
|
|
18
|
+
- ✅ **Auto-inicialização**: Suporte a inicialização via script tag
|
|
19
|
+
- ✅ **TypeScript**: Totalmente tipado para melhor DX
|
|
20
|
+
- ✅ **Zero Dependencies**: Apenas `ua-parser-js` para detecção de dispositivo
|
|
21
|
+
|
|
22
|
+
## 📦 Instalação
|
|
12
23
|
|
|
13
24
|
### Via NPM
|
|
14
25
|
|
|
15
26
|
```bash
|
|
16
|
-
npm install
|
|
27
|
+
npm install @agenus-io/recovery
|
|
17
28
|
# ou
|
|
18
|
-
pnpm add
|
|
29
|
+
pnpm add @agenus-io/recovery
|
|
19
30
|
# ou
|
|
20
|
-
yarn add
|
|
31
|
+
yarn add @agenus-io/recovery
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Via CDN
|
|
35
|
+
|
|
36
|
+
```html
|
|
37
|
+
<script src="https://unpkg.com/@agenus-io/recovery@latest/dist/index.global.js"></script>
|
|
21
38
|
```
|
|
22
39
|
|
|
23
40
|
## 📖 Uso
|
|
24
41
|
|
|
25
|
-
###
|
|
42
|
+
### Inicialização Manual
|
|
26
43
|
|
|
27
|
-
|
|
44
|
+
```javascript
|
|
45
|
+
import UpselyRecovery from '@agenus-io/recovery';
|
|
28
46
|
|
|
29
|
-
|
|
47
|
+
const recovery = new UpselyRecovery({
|
|
48
|
+
apiEndpoint: 'https://sua-api.com/pixel/public/event',
|
|
49
|
+
apiKey: 'sua-chave-api',
|
|
50
|
+
debug: true, // Ativa logs no console
|
|
51
|
+
timeout: 5000
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Auto-inicialização via Script Tag
|
|
30
56
|
|
|
31
57
|
```html
|
|
32
58
|
<!DOCTYPE html>
|
|
33
59
|
<html>
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
<button
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
<input name="email" placeholder="Email" required />
|
|
52
|
-
<input name="name" placeholder="Nome" required />
|
|
53
|
-
<button type="submit">Enviar</button>
|
|
54
|
-
</form>
|
|
55
|
-
|
|
56
|
-
<script>
|
|
57
|
-
// Inicializar o pixel tracker com auto-tracking
|
|
58
|
-
const pixel = new GomarkePixel({
|
|
59
|
-
apiEndpoint: 'https://sua-api.com/track',
|
|
60
|
-
apiKey: 'sua-chave-aqui',
|
|
61
|
-
debug: true,
|
|
62
|
-
|
|
63
|
-
// Configuração de auto-tracking - TUDO AUTOMÁTICO! 🚀
|
|
64
|
-
autoTracks: {
|
|
65
|
-
addToCart: {
|
|
66
|
-
enabled: true,
|
|
67
|
-
selector: '[data-add-to-cart]',
|
|
68
|
-
selectorType: 'attribute',
|
|
69
|
-
productDataSelectors: {
|
|
70
|
-
id: '[data-product-id]',
|
|
71
|
-
name: '[data-product-name]',
|
|
72
|
-
price: '[data-product-price]',
|
|
73
|
-
},
|
|
74
|
-
},
|
|
75
|
-
initiateCheckout: {
|
|
76
|
-
enabled: true,
|
|
77
|
-
selector: '[data-checkout]',
|
|
78
|
-
selectorType: 'attribute',
|
|
79
|
-
cartDataSelectors: {
|
|
80
|
-
total: '[data-cart-total]',
|
|
81
|
-
},
|
|
82
|
-
},
|
|
83
|
-
lead: {
|
|
84
|
-
enabled: true,
|
|
85
|
-
selector: 'form[data-lead]',
|
|
86
|
-
selectorType: 'attribute',
|
|
87
|
-
requiredFields: ['email', 'name'],
|
|
88
|
-
},
|
|
89
|
-
scroll: {
|
|
90
|
-
enabled: true,
|
|
91
|
-
scrollThresholds: [25, 50, 75, 90],
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
// Page view é automático, mas você ainda pode usar manualmente se quiser
|
|
97
|
-
// pixel.trackPageView();
|
|
98
|
-
// pixel.trackAddToCart('produto-123', 'Produto Exemplo', 99.90, 'BRL', 'Categoria');
|
|
99
|
-
// pixel.trackPurchase(199.90, 'BRL', 'txn_123');
|
|
100
|
-
</script>
|
|
101
|
-
</body>
|
|
60
|
+
<head>
|
|
61
|
+
<script
|
|
62
|
+
src="https://unpkg.com/@agenus-io/recovery@latest/dist/index.global.js"
|
|
63
|
+
data-api-endpoint="https://sua-api.com/pixel/public/event"
|
|
64
|
+
data-api-key="sua-chave-api"
|
|
65
|
+
data-debug="true"
|
|
66
|
+
data-timeout="5000"
|
|
67
|
+
></script>
|
|
68
|
+
</head>
|
|
69
|
+
<body>
|
|
70
|
+
<form id="contactForm">
|
|
71
|
+
<input type="text" name="nome" placeholder="Nome" />
|
|
72
|
+
<input type="email" name="email" placeholder="Email" />
|
|
73
|
+
<textarea name="mensagem" placeholder="Mensagem"></textarea>
|
|
74
|
+
<button type="submit">Enviar</button>
|
|
75
|
+
</form>
|
|
76
|
+
</body>
|
|
102
77
|
</html>
|
|
103
78
|
```
|
|
104
79
|
|
|
105
|
-
|
|
80
|
+
O sistema será inicializado automaticamente e estará disponível em `window.upselyRecovery`.
|
|
106
81
|
|
|
107
|
-
|
|
108
|
-
import GomarkePixel from 'gomarke-pixel';
|
|
82
|
+
## 🔧 Configuração
|
|
109
83
|
|
|
110
|
-
|
|
111
|
-
apiEndpoint: 'https://sua-api.com/track',
|
|
112
|
-
apiKey: 'sua-chave-aqui',
|
|
113
|
-
debug: true,
|
|
84
|
+
### Interface de Configuração
|
|
114
85
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
navigationSelectors: ['.checkout-link', '.finalizar-compra'],
|
|
134
|
-
},
|
|
135
|
-
lead: {
|
|
136
|
-
enabled: true,
|
|
137
|
-
selector: 'form.contact-form',
|
|
138
|
-
selectorType: 'class',
|
|
139
|
-
trackOnFieldFocus: true,
|
|
140
|
-
requiredFields: ['email', 'name'],
|
|
141
|
-
validationRules: {
|
|
142
|
-
email: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
|
|
143
|
-
},
|
|
144
|
-
},
|
|
145
|
-
scroll: {
|
|
146
|
-
enabled: true,
|
|
147
|
-
scrollThresholds: [25, 50, 75, 90],
|
|
148
|
-
trackScrollDepth: true,
|
|
149
|
-
trackTimeOnPage: true,
|
|
150
|
-
},
|
|
151
|
-
viewport: {
|
|
152
|
-
enabled: true,
|
|
153
|
-
selector: '.trackable-element',
|
|
154
|
-
selectorType: 'class',
|
|
155
|
-
trackElementIntersection: true,
|
|
156
|
-
trackElementClicks: true,
|
|
157
|
-
},
|
|
158
|
-
},
|
|
86
|
+
```typescript
|
|
87
|
+
interface UpselyRecoveryConfig {
|
|
88
|
+
apiEndpoint: string; // URL da sua API (obrigatório)
|
|
89
|
+
apiKey?: string; // Chave de autenticação
|
|
90
|
+
debug?: boolean; // Ativar logs de debug (padrão: false)
|
|
91
|
+
timeout?: number; // Timeout para requests em ms (padrão: 5000)
|
|
92
|
+
version?: string; // Versão do script
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Exemplo Completo
|
|
97
|
+
|
|
98
|
+
```javascript
|
|
99
|
+
const recovery = new UpselyRecovery({
|
|
100
|
+
apiEndpoint: 'https://api.exemplo.com/pixel/public/event',
|
|
101
|
+
apiKey: 'sua-chave-secreta',
|
|
102
|
+
debug: true,
|
|
103
|
+
timeout: 10000
|
|
159
104
|
});
|
|
160
105
|
|
|
161
|
-
//
|
|
162
|
-
//
|
|
163
|
-
// await pixel.trackPageView();
|
|
164
|
-
// await pixel.trackAddToCart('produto-123', 'Produto Exemplo', 99.90);
|
|
106
|
+
// O sistema já está monitorando todos os formulários na página!
|
|
107
|
+
// Quando o usuário preencher campos e fechar a página, os dados serão enviados automaticamente.
|
|
165
108
|
```
|
|
166
109
|
|
|
167
|
-
##
|
|
110
|
+
## 📊 Como Funciona
|
|
168
111
|
|
|
169
|
-
###
|
|
112
|
+
### 1. Detecção de Interação
|
|
113
|
+
|
|
114
|
+
O sistema monitora automaticamente:
|
|
115
|
+
- Eventos `focus` em campos de formulário
|
|
116
|
+
- Eventos `change` e `input` em campos
|
|
117
|
+
- Qualquer interação com `input`, `textarea` ou `select`
|
|
118
|
+
|
|
119
|
+
### 2. Detecção de Abandono
|
|
120
|
+
|
|
121
|
+
O sistema detecta abandono quando:
|
|
122
|
+
- Usuário tenta fechar a página (`beforeunload`)
|
|
123
|
+
- Aba fica oculta (`visibilitychange`)
|
|
124
|
+
- Página está sendo descarregada (`pagehide`)
|
|
125
|
+
|
|
126
|
+
### 3. Captura de Dados
|
|
127
|
+
|
|
128
|
+
Quando o abandono é detectado, o sistema:
|
|
129
|
+
- Coleta todos os campos preenchidos de todos os formulários
|
|
130
|
+
- Trata diferentes tipos de campos (text, email, checkbox, radio, select)
|
|
131
|
+
- Ignora campos vazios
|
|
132
|
+
- Prepara payload com metadados completos
|
|
133
|
+
|
|
134
|
+
### 4. Envio de Dados
|
|
135
|
+
|
|
136
|
+
Os dados são enviados com:
|
|
137
|
+
- **sendBeacon** (prioridade) - mais confiável para eventos de saída
|
|
138
|
+
- **fetch com keepalive** (fallback) - garante envio mesmo se sendBeacon falhar
|
|
139
|
+
- Retry automático em caso de falha
|
|
140
|
+
|
|
141
|
+
## 📤 Estrutura dos Dados Enviados
|
|
170
142
|
|
|
171
143
|
```typescript
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
144
|
+
{
|
|
145
|
+
event_type: 'form_abandonment',
|
|
146
|
+
forms: [
|
|
147
|
+
{
|
|
148
|
+
form_id: 'contactForm',
|
|
149
|
+
form_index: 0,
|
|
150
|
+
fields: {
|
|
151
|
+
nome: 'João Silva',
|
|
152
|
+
email: 'joao@exemplo.com',
|
|
153
|
+
mensagem: 'Olá, gostaria de mais informações...'
|
|
154
|
+
},
|
|
155
|
+
field_count: 3
|
|
156
|
+
}
|
|
157
|
+
],
|
|
158
|
+
total_forms: 1,
|
|
159
|
+
timestamp: 1234567890123
|
|
177
160
|
}
|
|
178
161
|
```
|
|
179
162
|
|
|
180
|
-
###
|
|
163
|
+
### Payload Completo do Evento
|
|
181
164
|
|
|
182
165
|
```typescript
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
| 'tag'
|
|
234
|
-
| 'text'
|
|
235
|
-
| 'url'
|
|
236
|
-
| 'data-attribute'
|
|
237
|
-
| 'custom';
|
|
238
|
-
trackOnFieldFocus?: boolean;
|
|
239
|
-
trackOnFieldBlur?: boolean;
|
|
240
|
-
trackOnFieldChange?: boolean;
|
|
241
|
-
requiredFields?: string[];
|
|
242
|
-
validationRules?: {
|
|
243
|
-
email?: RegExp;
|
|
244
|
-
phone?: RegExp;
|
|
245
|
-
minLength?: number;
|
|
246
|
-
};
|
|
247
|
-
};
|
|
248
|
-
scroll?: {
|
|
249
|
-
enabled?: boolean;
|
|
250
|
-
scrollThresholds?: number[];
|
|
251
|
-
trackScrollDepth?: boolean;
|
|
252
|
-
trackTimeOnPage?: boolean;
|
|
253
|
-
};
|
|
254
|
-
viewport?: {
|
|
255
|
-
enabled?: boolean;
|
|
256
|
-
selector?: string;
|
|
257
|
-
selectorType?:
|
|
258
|
-
| 'class'
|
|
259
|
-
| 'id'
|
|
260
|
-
| 'attribute'
|
|
261
|
-
| 'tag'
|
|
262
|
-
| 'text'
|
|
263
|
-
| 'url'
|
|
264
|
-
| 'data-attribute'
|
|
265
|
-
| 'custom';
|
|
266
|
-
trackElementIntersection?: boolean;
|
|
267
|
-
trackElementClicks?: boolean;
|
|
268
|
-
trackElementHovers?: boolean;
|
|
269
|
-
};
|
|
270
|
-
};
|
|
166
|
+
{
|
|
167
|
+
data: {
|
|
168
|
+
event_type: 'form_abandonment',
|
|
169
|
+
forms: [...],
|
|
170
|
+
total_forms: 1,
|
|
171
|
+
timestamp: 1234567890123
|
|
172
|
+
},
|
|
173
|
+
sessionId: 'session_1234567890_abc123',
|
|
174
|
+
timestamp: 1234567890123,
|
|
175
|
+
fingerprint: 'hash256_do_dispositivo',
|
|
176
|
+
user_agent: 'Mozilla/5.0...',
|
|
177
|
+
page: {
|
|
178
|
+
url: 'https://exemplo.com/contato',
|
|
179
|
+
title: 'Página de Contato',
|
|
180
|
+
referrer: 'https://google.com',
|
|
181
|
+
path: '/contato',
|
|
182
|
+
hostname: 'exemplo.com'
|
|
183
|
+
},
|
|
184
|
+
device: {
|
|
185
|
+
id: 'uuid-do-dispositivo',
|
|
186
|
+
type: 'desktop' | 'mobile' | 'tablet',
|
|
187
|
+
os: {
|
|
188
|
+
name: 'Windows' | 'Mac OS' | 'Linux' | 'iOS' | 'Android',
|
|
189
|
+
version: '10.0'
|
|
190
|
+
},
|
|
191
|
+
browser: {
|
|
192
|
+
name: 'Chrome' | 'Firefox' | 'Safari' | 'Edge',
|
|
193
|
+
version: '120.0'
|
|
194
|
+
},
|
|
195
|
+
engine: {
|
|
196
|
+
name: 'Blink',
|
|
197
|
+
version: '120.0'
|
|
198
|
+
},
|
|
199
|
+
language: 'pt-BR',
|
|
200
|
+
screen: {
|
|
201
|
+
width: 1920,
|
|
202
|
+
height: 1080,
|
|
203
|
+
pixel_ratio: 1
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
meta: {
|
|
207
|
+
version: '0.0.2',
|
|
208
|
+
recovery_source: 'upsely',
|
|
209
|
+
environment: 'production',
|
|
210
|
+
script_url: 'https://unpkg.com/@agenus-io/recovery@latest/dist/index.global.js'
|
|
211
|
+
},
|
|
212
|
+
query_params: {
|
|
213
|
+
utm_source: 'google',
|
|
214
|
+
utm_medium: 'cpc'
|
|
215
|
+
}
|
|
271
216
|
}
|
|
272
217
|
```
|
|
273
218
|
|
|
274
|
-
##
|
|
219
|
+
## 🎯 API
|
|
275
220
|
|
|
276
|
-
###
|
|
221
|
+
### Métodos Principais
|
|
277
222
|
|
|
278
|
-
|
|
279
|
-
- `trackPurchase(value, currency, transactionId?, items?)`: Track compra
|
|
280
|
-
- `trackAddToCart(itemId, itemName, value?, currency?, category?, quantity?)`: Adicionar ao carrinho
|
|
281
|
-
- `trackRemoveFromCart(itemId, itemName, value?, currency?, quantity?)`: Remover do carrinho
|
|
282
|
-
- `trackInitiateCheckout(value?, currency?, items?)`: Iniciar checkout
|
|
283
|
-
- `trackViewItem(itemId, itemName, value?, currency?, category?)`: Ver produto
|
|
284
|
-
- `trackSearch(searchTerm, resultsCount?)`: Busca
|
|
285
|
-
- `trackCustomEvent(eventName, eventCategory?, value?, currency?, customParameters?)`: Evento customizado
|
|
223
|
+
#### `getSessionId(): string`
|
|
286
224
|
|
|
287
|
-
|
|
225
|
+
Retorna o ID da sessão atual.
|
|
288
226
|
|
|
289
|
-
|
|
227
|
+
```javascript
|
|
228
|
+
const sessionId = recovery.getSessionId();
|
|
229
|
+
console.log(sessionId); // 'session_1234567890_abc123'
|
|
230
|
+
```
|
|
290
231
|
|
|
291
|
-
####
|
|
232
|
+
#### `getSessionData(): ISessionData`
|
|
292
233
|
|
|
293
|
-
|
|
294
|
-
- **AutoInitiateCheckout**: Detecta automaticamente cliques em botões "Finalizar Compra"
|
|
295
|
-
- **AutoLead**: Detecta automaticamente submissões de formulários de lead
|
|
234
|
+
Retorna dados completos da sessão.
|
|
296
235
|
|
|
297
|
-
|
|
236
|
+
```javascript
|
|
237
|
+
const sessionData = recovery.getSessionData();
|
|
238
|
+
console.log(sessionData);
|
|
239
|
+
// {
|
|
240
|
+
// sessionId: 'session_1234567890_abc123',
|
|
241
|
+
// lastActivity: 1234567890123,
|
|
242
|
+
// createdAt: 1234567890000,
|
|
243
|
+
// visitCount: 5,
|
|
244
|
+
// firstVisit: 1234567890000
|
|
245
|
+
// }
|
|
246
|
+
```
|
|
298
247
|
|
|
299
|
-
|
|
300
|
-
- **ViewportTracker**: Detecta quando elementos entram/saem do viewport
|
|
248
|
+
#### `isSessionActive(): boolean`
|
|
301
249
|
|
|
302
|
-
|
|
250
|
+
Verifica se a sessão está ativa (não expirada).
|
|
303
251
|
|
|
304
252
|
```javascript
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
apiKey: 'sua-chave',
|
|
309
|
-
debug: true,
|
|
310
|
-
});
|
|
311
|
-
|
|
312
|
-
// Auto-tracking de Add to Cart
|
|
313
|
-
await pixel
|
|
314
|
-
.getTrackerFactory()
|
|
315
|
-
.getAutoTrackerFactory()
|
|
316
|
-
.createAddToCartTracker({
|
|
317
|
-
isEnabled: true,
|
|
318
|
-
selector: '.add-to-cart-btn',
|
|
319
|
-
selectorType: 'class',
|
|
320
|
-
productDataSelectors: {
|
|
321
|
-
id: '.product-id',
|
|
322
|
-
name: '.product-name',
|
|
323
|
-
price: '.product-price',
|
|
324
|
-
category: '.product-category',
|
|
325
|
-
},
|
|
326
|
-
});
|
|
327
|
-
|
|
328
|
-
// Auto-tracking de Checkout
|
|
329
|
-
await pixel
|
|
330
|
-
.getTrackerFactory()
|
|
331
|
-
.getAutoTrackerFactory()
|
|
332
|
-
.createInitiateCheckoutTracker({
|
|
333
|
-
isEnabled: true,
|
|
334
|
-
selector: '.checkout-btn',
|
|
335
|
-
selectorType: 'class',
|
|
336
|
-
trackOnNavigation: true,
|
|
337
|
-
navigationSelectors: ['.checkout-link', '.finalizar-compra'],
|
|
338
|
-
});
|
|
339
|
-
|
|
340
|
-
// Auto-tracking de Lead
|
|
341
|
-
await pixel
|
|
342
|
-
.getTrackerFactory()
|
|
343
|
-
.getAutoTrackerFactory()
|
|
344
|
-
.createLeadTracker({
|
|
345
|
-
isEnabled: true,
|
|
346
|
-
selector: 'form.lead-form',
|
|
347
|
-
selectorType: 'class',
|
|
348
|
-
trackOnFieldFocus: true,
|
|
349
|
-
trackOnFieldBlur: true,
|
|
350
|
-
requiredFields: ['email', 'name'],
|
|
351
|
-
});
|
|
253
|
+
if (recovery.isSessionActive()) {
|
|
254
|
+
console.log('Sessão ativa!');
|
|
255
|
+
}
|
|
352
256
|
```
|
|
353
257
|
|
|
354
|
-
|
|
258
|
+
#### `updateSessionActivity(): void`
|
|
259
|
+
|
|
260
|
+
Atualiza a última atividade da sessão.
|
|
355
261
|
|
|
356
262
|
```javascript
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
apiKey: 'sua-chave',
|
|
360
|
-
debug: true,
|
|
361
|
-
});
|
|
263
|
+
recovery.updateSessionActivity();
|
|
264
|
+
```
|
|
362
265
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
'BRL',
|
|
370
|
-
'Smartphones'
|
|
371
|
-
);
|
|
372
|
-
|
|
373
|
-
// Adicionar ao carrinho
|
|
374
|
-
await pixel.trackAddToCart(
|
|
375
|
-
'produto-123',
|
|
376
|
-
'iPhone 15',
|
|
377
|
-
8999,
|
|
378
|
-
'BRL',
|
|
379
|
-
'Smartphones',
|
|
380
|
-
1
|
|
381
|
-
);
|
|
382
|
-
|
|
383
|
-
// Iniciar checkout
|
|
384
|
-
await pixel.trackInitiateCheckout(8999, 'BRL', [
|
|
385
|
-
{
|
|
386
|
-
item_id: 'produto-123',
|
|
387
|
-
item_name: 'iPhone 15',
|
|
388
|
-
category: 'Smartphones',
|
|
389
|
-
quantity: 1,
|
|
390
|
-
price: 8999,
|
|
391
|
-
},
|
|
392
|
-
]);
|
|
393
|
-
|
|
394
|
-
// Finalizar compra
|
|
395
|
-
await pixel.trackPurchase(8999, 'BRL', 'txn_123', [
|
|
396
|
-
{
|
|
397
|
-
item_id: 'produto-123',
|
|
398
|
-
item_name: 'iPhone 15',
|
|
399
|
-
category: 'Smartphones',
|
|
400
|
-
quantity: 1,
|
|
401
|
-
price: 8999,
|
|
402
|
-
},
|
|
403
|
-
]);
|
|
266
|
+
#### `renewSession(): void`
|
|
267
|
+
|
|
268
|
+
Renova a sessão (cria nova se expirada).
|
|
269
|
+
|
|
270
|
+
```javascript
|
|
271
|
+
recovery.renewSession();
|
|
404
272
|
```
|
|
405
273
|
|
|
406
|
-
|
|
274
|
+
#### `clearSession(): void`
|
|
407
275
|
|
|
408
|
-
|
|
276
|
+
Limpa todos os dados da sessão.
|
|
409
277
|
|
|
410
|
-
```
|
|
411
|
-
|
|
278
|
+
```javascript
|
|
279
|
+
recovery.clearSession();
|
|
412
280
|
```
|
|
413
281
|
|
|
414
|
-
|
|
282
|
+
#### `getConfig(): UpselyRecoveryConfig`
|
|
415
283
|
|
|
416
|
-
|
|
417
|
-
# Desenvolvimento com watch
|
|
418
|
-
pnpm dev
|
|
284
|
+
Retorna a configuração atual.
|
|
419
285
|
|
|
420
|
-
|
|
421
|
-
|
|
286
|
+
```javascript
|
|
287
|
+
const config = recovery.getConfig();
|
|
288
|
+
console.log(config);
|
|
289
|
+
```
|
|
422
290
|
|
|
423
|
-
|
|
424
|
-
pnpm lint
|
|
425
|
-
pnpm lint:fix
|
|
291
|
+
#### `updateConfig(newConfig: Partial<UpselyRecoveryConfig>): void`
|
|
426
292
|
|
|
427
|
-
|
|
428
|
-
pnpm format
|
|
293
|
+
Atualiza a configuração.
|
|
429
294
|
|
|
430
|
-
|
|
431
|
-
|
|
295
|
+
```javascript
|
|
296
|
+
recovery.updateConfig({
|
|
297
|
+
debug: false,
|
|
298
|
+
timeout: 10000
|
|
299
|
+
});
|
|
432
300
|
```
|
|
433
301
|
|
|
434
|
-
|
|
302
|
+
#### `destroyFormAbandonment(): void`
|
|
303
|
+
|
|
304
|
+
Destrói o sistema de abandono (remove listeners).
|
|
435
305
|
|
|
306
|
+
```javascript
|
|
307
|
+
recovery.destroyFormAbandonment();
|
|
436
308
|
```
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
dist/ # Arquivos compilados
|
|
471
|
-
├── index.global.js # Versão IIFE para CDN
|
|
472
|
-
├── index.cjs.js # CommonJS
|
|
473
|
-
├── index.esm.js # ES Modules
|
|
474
|
-
├── index.d.ts # Definições TypeScript
|
|
475
|
-
└── index.d.mts # Definições TypeScript (ESM)
|
|
309
|
+
|
|
310
|
+
## 🧪 Exemplos
|
|
311
|
+
|
|
312
|
+
### Exemplo Básico
|
|
313
|
+
|
|
314
|
+
```html
|
|
315
|
+
<!DOCTYPE html>
|
|
316
|
+
<html>
|
|
317
|
+
<head>
|
|
318
|
+
<title>Formulário de Contato</title>
|
|
319
|
+
</head>
|
|
320
|
+
<body>
|
|
321
|
+
<form id="contactForm">
|
|
322
|
+
<input type="text" name="nome" placeholder="Nome completo" required />
|
|
323
|
+
<input type="email" name="email" placeholder="Seu email" required />
|
|
324
|
+
<input type="tel" name="telefone" placeholder="Telefone" />
|
|
325
|
+
<textarea name="mensagem" placeholder="Sua mensagem"></textarea>
|
|
326
|
+
<button type="submit">Enviar</button>
|
|
327
|
+
</form>
|
|
328
|
+
|
|
329
|
+
<script src="https://unpkg.com/@agenus-io/recovery@latest/dist/index.global.js"></script>
|
|
330
|
+
<script>
|
|
331
|
+
const recovery = new UpselyRecovery({
|
|
332
|
+
apiEndpoint: 'https://sua-api.com/pixel/public/event',
|
|
333
|
+
apiKey: 'sua-chave-api',
|
|
334
|
+
debug: true
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
// O sistema já está monitorando o formulário!
|
|
338
|
+
// Se o usuário preencher e fechar a página, os dados serão capturados.
|
|
339
|
+
</script>
|
|
340
|
+
</body>
|
|
341
|
+
</html>
|
|
476
342
|
```
|
|
477
343
|
|
|
478
|
-
|
|
344
|
+
### Exemplo com Múltiplos Formulários
|
|
479
345
|
|
|
480
|
-
|
|
346
|
+
```html
|
|
347
|
+
<!DOCTYPE html>
|
|
348
|
+
<html>
|
|
349
|
+
<body>
|
|
350
|
+
<!-- Formulário de Newsletter -->
|
|
351
|
+
<form id="newsletterForm">
|
|
352
|
+
<input type="email" name="email" placeholder="Email" />
|
|
353
|
+
<button type="submit">Inscrever-se</button>
|
|
354
|
+
</form>
|
|
355
|
+
|
|
356
|
+
<!-- Formulário de Contato -->
|
|
357
|
+
<form id="contactForm">
|
|
358
|
+
<input type="text" name="nome" placeholder="Nome" />
|
|
359
|
+
<input type="email" name="email" placeholder="Email" />
|
|
360
|
+
<textarea name="mensagem" placeholder="Mensagem"></textarea>
|
|
361
|
+
<button type="submit">Enviar</button>
|
|
362
|
+
</form>
|
|
363
|
+
|
|
364
|
+
<script src="https://unpkg.com/@agenus-io/recovery@latest/dist/index.global.js"></script>
|
|
365
|
+
<script>
|
|
366
|
+
new UpselyRecovery({
|
|
367
|
+
apiEndpoint: 'https://sua-api.com/pixel/public/event',
|
|
368
|
+
apiKey: 'sua-chave-api',
|
|
369
|
+
debug: true
|
|
370
|
+
});
|
|
371
|
+
// Ambos os formulários são monitorados automaticamente!
|
|
372
|
+
</script>
|
|
373
|
+
</body>
|
|
374
|
+
</html>
|
|
375
|
+
```
|
|
481
376
|
|
|
482
|
-
|
|
483
|
-
- **Detecção Automática**: Detecta cliques, formulários, scroll, viewport automaticamente
|
|
484
|
-
- **DOM Dinâmico**: Funciona com elementos adicionados via JavaScript/AJAX
|
|
485
|
-
- **Performance Otimizada**: Debouncing, throttling e lazy loading automáticos
|
|
486
|
-
- **Validação Inteligente**: Valida formulários automaticamente
|
|
487
|
-
- **Retry Logic**: Tenta novamente se elementos ainda não carregaram
|
|
377
|
+
### Exemplo com TypeScript
|
|
488
378
|
|
|
489
|
-
|
|
379
|
+
```typescript
|
|
380
|
+
import UpselyRecovery from '@agenus-io/recovery';
|
|
381
|
+
import type { UpselyRecoveryConfig } from '@agenus-io/recovery';
|
|
490
382
|
|
|
491
|
-
|
|
383
|
+
const config: UpselyRecoveryConfig = {
|
|
384
|
+
apiEndpoint: 'https://sua-api.com/pixel/public/event',
|
|
385
|
+
apiKey: 'sua-chave-api',
|
|
386
|
+
debug: process.env.NODE_ENV === 'development',
|
|
387
|
+
timeout: 10000
|
|
388
|
+
};
|
|
492
389
|
|
|
493
|
-
|
|
494
|
-
// Tinha que chamar manualmente para cada evento
|
|
495
|
-
pixel.trackPageView();
|
|
496
|
-
document.querySelector('.add-to-cart').addEventListener('click', () => {
|
|
497
|
-
pixel.trackAddToCart('produto-123', 'Produto', 99.9);
|
|
498
|
-
});
|
|
499
|
-
document.querySelector('form').addEventListener('submit', () => {
|
|
500
|
-
pixel.trackLead({ email: 'user@email.com' });
|
|
501
|
-
});
|
|
502
|
-
// ... mais código manual para cada interação
|
|
503
|
-
```
|
|
390
|
+
const recovery = new UpselyRecovery(config);
|
|
504
391
|
|
|
505
|
-
|
|
392
|
+
// Verificar sessão
|
|
393
|
+
if (recovery.isSessionActive()) {
|
|
394
|
+
console.log('Sessão ativa:', recovery.getSessionId());
|
|
395
|
+
}
|
|
506
396
|
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
apiEndpoint: 'https://sua-api.com/track',
|
|
511
|
-
autoTracks: {
|
|
512
|
-
addToCart: { enabled: true, selector: '[data-add-to-cart]' },
|
|
513
|
-
lead: { enabled: true, selector: 'form[data-lead]' },
|
|
514
|
-
scroll: { enabled: true },
|
|
515
|
-
},
|
|
397
|
+
// Atualizar configuração em runtime
|
|
398
|
+
recovery.updateConfig({
|
|
399
|
+
debug: false
|
|
516
400
|
});
|
|
517
|
-
// TUDO FUNCIONA AUTOMATICAMENTE! 🎉
|
|
518
401
|
```
|
|
519
402
|
|
|
520
|
-
##
|
|
521
|
-
|
|
522
|
-
### Sistema de Classes Orientado a Objetos
|
|
403
|
+
## 🛠️ Desenvolvimento
|
|
523
404
|
|
|
524
|
-
|
|
405
|
+
### Pré-requisitos
|
|
525
406
|
|
|
526
|
-
|
|
407
|
+
- Node.js >= 18
|
|
408
|
+
- pnpm >= 8
|
|
527
409
|
|
|
528
|
-
|
|
529
|
-
- **TrackerFactory**: Factory pattern para gerenciar instâncias de trackers
|
|
530
|
-
- **PageViewTracker**, **PurchaseTracker**, **AddToCartTracker**, etc.
|
|
410
|
+
### Instalação
|
|
531
411
|
|
|
532
|
-
|
|
412
|
+
```bash
|
|
413
|
+
# Clonar repositório
|
|
414
|
+
git clone https://github.com/agenus-io/recovery.git
|
|
415
|
+
cd recovery
|
|
533
416
|
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
- **EventManager**: Gerenciador de eventos com debouncing/throttling
|
|
417
|
+
# Instalar dependências
|
|
418
|
+
pnpm install
|
|
419
|
+
```
|
|
538
420
|
|
|
539
|
-
###
|
|
421
|
+
### Scripts Disponíveis
|
|
540
422
|
|
|
541
|
-
|
|
423
|
+
```bash
|
|
424
|
+
# Desenvolvimento com watch
|
|
425
|
+
pnpm dev
|
|
542
426
|
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
- **Retry Logic**: Sistema de retry automático para elementos que ainda não carregaram
|
|
546
|
-
- **Debouncing/Throttling**: Otimização de performance para eventos frequentes
|
|
427
|
+
# Build para produção
|
|
428
|
+
pnpm build
|
|
547
429
|
|
|
548
|
-
|
|
430
|
+
# Linting
|
|
431
|
+
pnpm lint
|
|
432
|
+
pnpm lint:fix
|
|
549
433
|
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
- **Validação**: Sistema de validação de formulários
|
|
553
|
-
- **Callbacks Customizados**: Funções de callback para processamento customizado
|
|
434
|
+
# Formatação de código
|
|
435
|
+
pnpm format
|
|
554
436
|
|
|
555
|
-
|
|
437
|
+
# Verificação de tipos
|
|
438
|
+
pnpm type-check
|
|
556
439
|
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
440
|
+
# Limpar arquivos gerados
|
|
441
|
+
pnpm clean
|
|
442
|
+
```
|
|
560
443
|
|
|
561
|
-
|
|
444
|
+
### Estrutura do Projeto
|
|
562
445
|
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
446
|
+
```
|
|
447
|
+
src/
|
|
448
|
+
├── index.ts # Ponto de entrada principal
|
|
449
|
+
├── init.ts # Classe principal UpselyRecovery
|
|
450
|
+
├── config.ts # Configurações globais
|
|
451
|
+
├── types.ts # Definições de tipos TypeScript
|
|
452
|
+
└── utils/ # Utilitários
|
|
453
|
+
├── formAbandonment.ts # Sistema de detecção de abandono
|
|
454
|
+
├── getFormData.ts # Captura de dados de formulários
|
|
455
|
+
├── getSession.ts # Gerenciamento de sessão
|
|
456
|
+
├── getFingerprint.ts # Geração de fingerprint
|
|
457
|
+
├── getDeviceInfo.ts # Informações do dispositivo
|
|
458
|
+
├── sendEvent.tsx # Envio de eventos
|
|
459
|
+
└── parseConfigFromScriptTag.ts # Parser de configuração
|
|
460
|
+
```
|
|
566
461
|
|
|
567
462
|
## 📦 Build
|
|
568
463
|
|
|
569
464
|
O projeto usa `tsup` para gerar múltiplos formatos:
|
|
570
465
|
|
|
571
|
-
- **
|
|
572
|
-
- **
|
|
573
|
-
- **
|
|
574
|
-
- **TypeScript** (
|
|
466
|
+
- **CommonJS** (`dist/index.cjs.js`): Para Node.js e bundlers antigos
|
|
467
|
+
- **ES Modules** (`dist/index.esm.js`): Para bundlers modernos
|
|
468
|
+
- **IIFE** (`dist/index.global.js`): Para uso direto no browser via CDN
|
|
469
|
+
- **TypeScript** (`dist/index.d.ts`): Definições de tipos
|
|
575
470
|
|
|
576
|
-
##
|
|
471
|
+
## 🚀 Publicação
|
|
577
472
|
|
|
578
|
-
|
|
473
|
+
Para informações sobre como publicar novas versões no NPM, consulte o [README-RELEASE.md](./README-RELEASE.md).
|
|
579
474
|
|
|
580
|
-
|
|
581
|
-
const pixel = new GomarkePixel({
|
|
582
|
-
apiEndpoint: 'https://sua-api.com/track',
|
|
583
|
-
apiKey: 'sua-chave',
|
|
584
|
-
debug: true,
|
|
585
|
-
});
|
|
475
|
+
### Comandos Rápidos
|
|
586
476
|
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
// Auto-tracking de produtos
|
|
591
|
-
await autoFactory.createAddToCartTracker({
|
|
592
|
-
isEnabled: true,
|
|
593
|
-
selector: '[data-add-to-cart]',
|
|
594
|
-
selectorType: 'attribute',
|
|
595
|
-
productDataSelectors: {
|
|
596
|
-
id: '[data-product-id]',
|
|
597
|
-
name: '.product-title',
|
|
598
|
-
price: '.price-value',
|
|
599
|
-
category: '.product-category',
|
|
600
|
-
},
|
|
601
|
-
customDataExtractor: element => ({
|
|
602
|
-
brand: element.dataset.brand,
|
|
603
|
-
variant: element.dataset.variant,
|
|
604
|
-
}),
|
|
605
|
-
});
|
|
477
|
+
```bash
|
|
478
|
+
# Criar changeset
|
|
479
|
+
pnpm changeset:add
|
|
606
480
|
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
isEnabled: true,
|
|
610
|
-
selector: '.checkout-button',
|
|
611
|
-
selectorType: 'class',
|
|
612
|
-
trackOnNavigation: true,
|
|
613
|
-
navigationSelectors: ['.checkout-link', '.finalizar-compra'],
|
|
614
|
-
cartDataSelectors: {
|
|
615
|
-
total: '.cart-total',
|
|
616
|
-
currency: '.cart-currency',
|
|
617
|
-
items: '.cart-item',
|
|
618
|
-
},
|
|
619
|
-
});
|
|
481
|
+
# Preparar release
|
|
482
|
+
pnpm run release:full
|
|
620
483
|
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
isEnabled: true,
|
|
624
|
-
selector: 'form.contact-form',
|
|
625
|
-
selectorType: 'class',
|
|
626
|
-
trackOnFieldFocus: true,
|
|
627
|
-
trackOnFieldBlur: true,
|
|
628
|
-
trackOnFieldChange: true,
|
|
629
|
-
requiredFields: ['email', 'name'],
|
|
630
|
-
validationRules: {
|
|
631
|
-
email: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
|
|
632
|
-
phone: /^\(\d{2}\)\s\d{4,5}-\d{4}$/,
|
|
633
|
-
},
|
|
634
|
-
});
|
|
484
|
+
# Publicar no NPM
|
|
485
|
+
pnpm run release:publish
|
|
635
486
|
```
|
|
636
487
|
|
|
637
|
-
|
|
488
|
+
## 🔒 Privacidade e Segurança
|
|
638
489
|
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
pixel.version
|
|
645
|
-
);
|
|
646
|
-
await scrollTracker.initialize({
|
|
647
|
-
isEnabled: true,
|
|
648
|
-
scrollThresholds: [25, 50, 75, 90],
|
|
649
|
-
trackScrollDepth: true,
|
|
650
|
-
trackTimeOnPage: true,
|
|
651
|
-
debounceMs: 300,
|
|
652
|
-
});
|
|
490
|
+
- ✅ **Dados Locais**: Sessão armazenada apenas localmente (localStorage + cookies)
|
|
491
|
+
- ✅ **Sem Tracking Cross-Site**: Não rastreia usuários entre sites
|
|
492
|
+
- ✅ **Fingerprint Anônimo**: Fingerprint não contém informações pessoais
|
|
493
|
+
- ✅ **HTTPS Recomendado**: Use sempre HTTPS em produção
|
|
494
|
+
- ✅ **Sanitização**: Considere sanitizar dados sensíveis no backend
|
|
653
495
|
|
|
654
|
-
|
|
655
|
-
const viewportTracker = new ViewportTracker(
|
|
656
|
-
pixel.config,
|
|
657
|
-
pixel.sessionId,
|
|
658
|
-
pixel.version
|
|
659
|
-
);
|
|
660
|
-
await viewportTracker.initialize({
|
|
661
|
-
isEnabled: true,
|
|
662
|
-
selector: '.trackable-element',
|
|
663
|
-
selectorType: 'class',
|
|
664
|
-
trackElementIntersection: true,
|
|
665
|
-
trackElementClicks: true,
|
|
666
|
-
trackElementHovers: true,
|
|
667
|
-
visibilityThreshold: 0.5,
|
|
668
|
-
maxTrackingElements: 100,
|
|
669
|
-
});
|
|
670
|
-
```
|
|
496
|
+
## 🐛 Troubleshooting
|
|
671
497
|
|
|
672
|
-
###
|
|
498
|
+
### O sistema não está detectando abandono
|
|
673
499
|
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
// Obter estatísticas dos auto-trackers
|
|
680
|
-
const autoStats = pixel
|
|
681
|
-
.getTrackerFactory()
|
|
682
|
-
.getAutoTrackerFactory()
|
|
683
|
-
.getFactoryStats();
|
|
684
|
-
console.log('Estatísticas dos auto-trackers:', autoStats);
|
|
685
|
-
|
|
686
|
-
// Parar todos os auto-trackers
|
|
687
|
-
await pixel.getTrackerFactory().getAutoTrackerFactory().stopAllAutoTrackers();
|
|
688
|
-
|
|
689
|
-
// Reconstruir todos os auto-trackers (útil para DOM dinâmico)
|
|
690
|
-
await pixel
|
|
691
|
-
.getTrackerFactory()
|
|
692
|
-
.getAutoTrackerFactory()
|
|
693
|
-
.rebuildAllAutoTrackers();
|
|
694
|
-
```
|
|
500
|
+
1. Verifique se `debug: true` está ativado
|
|
501
|
+
2. Abra o console do navegador (F12)
|
|
502
|
+
3. Verifique se há logs `[FormAbandonment]`
|
|
503
|
+
4. Certifique-se de que o usuário interagiu com pelo menos um campo
|
|
695
504
|
|
|
696
|
-
|
|
505
|
+
### Dados não estão sendo enviados
|
|
697
506
|
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
507
|
+
1. Verifique se `apiEndpoint` está correto
|
|
508
|
+
2. Verifique se a API está acessível (CORS configurado)
|
|
509
|
+
3. Verifique o console para erros
|
|
510
|
+
4. Teste a API manualmente com `fetch` ou `curl`
|
|
701
511
|
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
512
|
+
### Sessão não persiste
|
|
513
|
+
|
|
514
|
+
1. Verifique se localStorage está habilitado
|
|
515
|
+
2. Verifique se cookies estão habilitados
|
|
516
|
+
3. Verifique se não está em modo anônimo/privado
|
|
517
|
+
4. Verifique se o domínio permite cookies
|
|
705
518
|
|
|
706
|
-
##
|
|
519
|
+
## 📄 Licença
|
|
707
520
|
|
|
708
|
-
|
|
521
|
+
MIT
|
|
709
522
|
|
|
710
|
-
|
|
523
|
+
## 🤝 Contribuindo
|
|
711
524
|
|
|
712
|
-
|
|
713
|
-
- **Arquitetura Orientada a Objetos**: Classes base e factory patterns
|
|
714
|
-
- **AutoTracks Avançados**: ScrollTracker e ViewportTracker
|
|
715
|
-
- **Sistema de Seletores**: Suporte a múltiplos tipos de seletores
|
|
716
|
-
- **Extração de Dados**: Seletores configuráveis para dados de produtos
|
|
717
|
-
- **Validação de Formulários**: Sistema de validação com regras customizadas
|
|
718
|
-
- **Monitoramento**: Estatísticas detalhadas e health checks
|
|
525
|
+
Contribuições são bem-vindas! Por favor:
|
|
719
526
|
|
|
720
|
-
|
|
527
|
+
1. Faça fork do projeto: [github.com/techionext/upsely-recovery](https://github.com/techionext/upsely-recovery)
|
|
528
|
+
2. Crie uma branch para sua feature (`git checkout -b feature/AmazingFeature`)
|
|
529
|
+
3. Commit suas mudanças (`git commit -m 'Add some AmazingFeature'`)
|
|
530
|
+
4. Push para a branch (`git push origin feature/AmazingFeature`)
|
|
531
|
+
5. Abra um Pull Request no GitHub
|
|
721
532
|
|
|
722
|
-
|
|
723
|
-
- **Performance**: Debouncing, throttling e lazy loading
|
|
724
|
-
- **DOM Dinâmico**: Suporte a elementos adicionados dinamicamente
|
|
725
|
-
- **Retry Logic**: Sistema de retry automático
|
|
726
|
-
- **Memory Management**: Limpeza automática de listeners
|
|
727
|
-
- **Bundle Optimization**: Tree-shaking e otimizações
|
|
533
|
+
### Reportar Bugs
|
|
728
534
|
|
|
729
|
-
|
|
535
|
+
Se encontrar algum bug, por favor abra uma [issue no GitHub](https://github.com/techionext/upsely-recovery/issues) com:
|
|
536
|
+
- Descrição do problema
|
|
537
|
+
- Passos para reproduzir
|
|
538
|
+
- Comportamento esperado vs comportamento atual
|
|
539
|
+
- Ambiente (navegador, versão, etc.)
|
|
730
540
|
|
|
731
|
-
|
|
732
|
-
- **BaseAutoTracker**: Classe base para auto-trackers
|
|
733
|
-
- **TrackerFactory**: Factory para gerenciar trackers
|
|
734
|
-
- **AutoTrackerFactory**: Factory para gerenciar auto-trackers
|
|
735
|
-
- **SelectorUtils**: Utilitários avançados de seleção DOM
|
|
736
|
-
- **EventManager**: Gerenciador de eventos otimizado
|
|
541
|
+
## 📞 Suporte
|
|
737
542
|
|
|
738
|
-
|
|
543
|
+
Para suporte:
|
|
544
|
+
- Abra uma [issue no GitHub](https://github.com/techionext/upsely-recovery/issues)
|
|
545
|
+
- Entre em contato com a equipe Agenus
|
|
739
546
|
|
|
740
|
-
|
|
741
|
-
- **Debug Avançado**: Logs detalhados para desenvolvimento
|
|
742
|
-
- **Health Checks**: Verificação de saúde dos trackers
|
|
743
|
-
- **Error Handling**: Tratamento robusto de erros
|
|
547
|
+
## 🔗 Links
|
|
744
548
|
|
|
745
|
-
|
|
549
|
+
- **Repositório**: [github.com/techionext/upsely-recovery](https://github.com/techionext/upsely-recovery)
|
|
550
|
+
- **NPM Package**: [npmjs.com/package/@agenus-io/recovery](https://www.npmjs.com/package/@agenus-io/recovery)
|
|
551
|
+
- **Changelog**: [CHANGELOG.md](./CHANGELOG.md)
|
|
552
|
+
- **Guia de Release**: [README-RELEASE.md](./README-RELEASE.md)
|
|
746
553
|
|
|
747
|
-
|
|
554
|
+
---
|
|
555
|
+
|
|
556
|
+
Desenvolvido com ❤️ por [Agenus](https://agenus.io)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agenus-io/recovery",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "Recuperação de leads para Upsely",
|
|
5
5
|
"main": "dist/index.cjs.js",
|
|
6
6
|
"module": "dist/index.esm.js",
|
|
@@ -21,10 +21,21 @@
|
|
|
21
21
|
"keywords": [
|
|
22
22
|
"recovery",
|
|
23
23
|
"upsely",
|
|
24
|
-
"agenus"
|
|
24
|
+
"agenus",
|
|
25
|
+
"form-abandonment",
|
|
26
|
+
"lead-capture",
|
|
27
|
+
"form-tracking"
|
|
25
28
|
],
|
|
26
29
|
"author": "Agenus",
|
|
27
30
|
"license": "MIT",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "https://github.com/techionext/upsely-recovery.git"
|
|
34
|
+
},
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/techionext/upsely-recovery/issues"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://github.com/techionext/upsely-recovery#readme",
|
|
28
39
|
"devDependencies": {
|
|
29
40
|
"@changesets/cli": "^2.27.1",
|
|
30
41
|
"@types/node": "^20.0.0",
|