cdp-edge 1.13.0 → 1.14.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 +172 -172
- package/extracted-skill/tracking-events-generator/agents/ab-ltv-agent.md +196 -0
- package/extracted-skill/tracking-events-generator/agents/bidding-agent.md +347 -0
- package/extracted-skill/tracking-events-generator/agents/devops-agent.md +9 -1
- package/extracted-skill/tracking-events-generator/agents/domain-setup-agent.md +6 -0
- package/extracted-skill/tracking-events-generator/agents/fraud-detection-agent.md +142 -0
- package/extracted-skill/tracking-events-generator/agents/master-orchestrator.md +11 -1
- package/extracted-skill/tracking-events-generator/agents/ml-clustering-agent.md +738 -0
- package/extracted-skill/tracking-events-generator/agents/page-analyzer.md +14 -2
- package/package.json +1 -1
- package/server-edge-tracker/INSTALAR.md +189 -14
- package/server-edge-tracker/SEGMENTATION-DOCS.md +444 -0
- package/server-edge-tracker/schema-ab-ltv.sql +97 -0
- package/server-edge-tracker/schema-bidding.sql +86 -0
- package/server-edge-tracker/schema-fraud.sql +90 -0
- package/server-edge-tracker/schema-segmentation.sql +219 -0
- package/server-edge-tracker/worker.js +1461 -18
- package/server-edge-tracker/wrangler.toml +3 -3
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
# API de Segmentação Dinâmica ML — Documentação Completa
|
|
2
|
+
|
|
3
|
+
## Visão Geral
|
|
4
|
+
|
|
5
|
+
API REST para segmentação dinâmica de leads via Machine Learning (K-means, DBSCAN, Hierarchical).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Endpoints Disponíveis
|
|
10
|
+
|
|
11
|
+
| Método | Endpoint | Descrição |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| **POST** | `/api/segmentation/cluster` | Executar clustering K-means |
|
|
14
|
+
| **GET** | `/api/segmentation/list` | Listar todos os segmentos ativos |
|
|
15
|
+
| **GET** | `/api/segmentation/outliers` | Listar leads anômalos (outliers) |
|
|
16
|
+
| **PUT** | `/api/segmentation/update` | Atualizar recomendações de segmento |
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 1. POST /api/segmentation/cluster — Executar Clustering
|
|
21
|
+
|
|
22
|
+
Executa clustering K-means via Workers AI para criar segmentos de leads.
|
|
23
|
+
|
|
24
|
+
### Request Body
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"algorithm": "kmeans", // Opcional: 'kmeans', 'dbscan', 'hierarchical'
|
|
29
|
+
"n_clusters": 5, // Opcional: 3-10 (padrão: 5)
|
|
30
|
+
"vertical": "curso-online", // Opcional: vertical do cliente
|
|
31
|
+
"force": false // Opcional: forçar novo clustering
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Response
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"success": true,
|
|
40
|
+
"cluster_id": 123,
|
|
41
|
+
"clustering_algorithm": "kmeans",
|
|
42
|
+
"n_clusters": 5,
|
|
43
|
+
"client_vertical": "curso-online",
|
|
44
|
+
"duration_ms": 12543,
|
|
45
|
+
"clusters": [
|
|
46
|
+
{
|
|
47
|
+
"cluster_id": 0,
|
|
48
|
+
"name": "Segmento 0 - Alto Valor + Alto Engajamento (SP)",
|
|
49
|
+
"size": 95,
|
|
50
|
+
"percentage": 0.25,
|
|
51
|
+
"characteristics": {
|
|
52
|
+
"avg_ltv": 497.50,
|
|
53
|
+
"avg_ltv_class": "High",
|
|
54
|
+
"avg_behavior_score": 75.3,
|
|
55
|
+
"avg_engagement_score": 82.1,
|
|
56
|
+
"avg_intention_level": 85.0,
|
|
57
|
+
"dominant_countries": ["BR", "AR"],
|
|
58
|
+
"dominant_states": ["SP", "RJ"],
|
|
59
|
+
"dominant_utm_sources": ["facebook", "google"],
|
|
60
|
+
"top_features": ["ltv", "behavior_score", "engagement_score"]
|
|
61
|
+
},
|
|
62
|
+
"centroid": {
|
|
63
|
+
"ltv_class": 0.75,
|
|
64
|
+
"behavior_score": 0.80,
|
|
65
|
+
"engagement_score": 0.85
|
|
66
|
+
},
|
|
67
|
+
"sample_leads": ["lead_451", "lead_892", "lead_1034"]
|
|
68
|
+
}
|
|
69
|
+
],
|
|
70
|
+
"silhouette_scores": {
|
|
71
|
+
"overall": 0.62,
|
|
72
|
+
"by_cluster": [0.71, 0.58, 0.65, 0.60, 0.55]
|
|
73
|
+
},
|
|
74
|
+
"convergence": {
|
|
75
|
+
"iterations": 47,
|
|
76
|
+
"final_inertia": 1523.45
|
|
77
|
+
},
|
|
78
|
+
"generated_at": "2026-04-09T18:45:32.000Z"
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Exemplo de Uso (cURL)
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
curl -X POST "https://seudominio.com/api/segmentation/cluster" \
|
|
86
|
+
-H "Content-Type: application/json" \
|
|
87
|
+
-d '{
|
|
88
|
+
"algorithm": "kmeans",
|
|
89
|
+
"n_clusters": 5,
|
|
90
|
+
"vertical": "curso-online"
|
|
91
|
+
}'
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## 2. GET /api/segmentation/list — Listar Segmentos
|
|
97
|
+
|
|
98
|
+
Lista todos os segmentos ativos com estatísticas detalhadas.
|
|
99
|
+
|
|
100
|
+
### Query Parameters
|
|
101
|
+
|
|
102
|
+
| Parâmetro | Tipo | Descrição |
|
|
103
|
+
|---|---|---|
|
|
104
|
+
| `algorithm` | string | Filtro por algoritmo: `kmeans`, `dbscan`, `hierarchical` |
|
|
105
|
+
| `active` | boolean | Filtro por status: `1` (ativo) ou `0` (arquivado) |
|
|
106
|
+
| `limit` | number | Máximo de resultados (padrão: 10) |
|
|
107
|
+
|
|
108
|
+
### Exemplo de Request
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
curl "https://seudominio.com/api/segmentation/list?algorithm=kmeans&active=1&limit=10"
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Response
|
|
115
|
+
|
|
116
|
+
```json
|
|
117
|
+
{
|
|
118
|
+
"success": true,
|
|
119
|
+
"count": 5,
|
|
120
|
+
"segments": [
|
|
121
|
+
{
|
|
122
|
+
"id": 45,
|
|
123
|
+
"cluster_id": 123,
|
|
124
|
+
"cluster_name": "Segmento 0 - Alto Valor + Alto Engajamento (SP)",
|
|
125
|
+
"clustering_algorithm": "kmeans",
|
|
126
|
+
"client_vertical": "curso-online",
|
|
127
|
+
"size": 95,
|
|
128
|
+
"percentage": 0.25,
|
|
129
|
+
"avg_ltv": 497.50,
|
|
130
|
+
"avg_ltv_class": "High",
|
|
131
|
+
"avg_behavior_score": 75.3,
|
|
132
|
+
"avg_engagement_score": 82.1,
|
|
133
|
+
"avg_intention_level": 85.0,
|
|
134
|
+
"dominant_countries": ["BR", "AR"],
|
|
135
|
+
"dominant_states": ["SP", "RJ"],
|
|
136
|
+
"dominant_features": ["ltv", "behavior_score", "engagement_score"],
|
|
137
|
+
"silhouette_score": 0.71,
|
|
138
|
+
"action_recommendations": [
|
|
139
|
+
"Priorizar remarketing em 24h",
|
|
140
|
+
"Criar lookalike audience de alto valor"
|
|
141
|
+
],
|
|
142
|
+
"bid_recommendations": [
|
|
143
|
+
{"adset_id": "456", "recommended_bid": "R$ 18.50", "confidence": 0.85}
|
|
144
|
+
],
|
|
145
|
+
"campaign_recommendations": [
|
|
146
|
+
{"creative": "VSL A", "audience": "Segmento 0"},
|
|
147
|
+
{"creative": "VSL B", "audience": "Segmento 0"}
|
|
148
|
+
],
|
|
149
|
+
"is_active": true,
|
|
150
|
+
"created_at": "2026-04-09T18:45:32.000Z",
|
|
151
|
+
"updated_at": "2026-04-09T18:45:32.000Z"
|
|
152
|
+
}
|
|
153
|
+
]
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## 3. GET /api/segmentation/outliers — Listar Anomalias
|
|
160
|
+
|
|
161
|
+
Lista leads considerados outliers/anomalias (detecção DBSCAN).
|
|
162
|
+
|
|
163
|
+
### Query Parameters
|
|
164
|
+
|
|
165
|
+
| Parâmetro | Tipo | Descrição |
|
|
166
|
+
|---|---|---|
|
|
167
|
+
| `confidence` | number | Threshold de confiança (padrão: 0.5) |
|
|
168
|
+
| `risk` | string | Filtro por nível: `high`, `medium`, `low` |
|
|
169
|
+
| `limit` | number | Máximo de resultados (padrão: 50) |
|
|
170
|
+
|
|
171
|
+
### Exemplo de Request
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
curl "https://seudominio.com/api/segmentation/outliers?confidence=0.3&risk=high&limit=20"
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Response
|
|
178
|
+
|
|
179
|
+
```json
|
|
180
|
+
{
|
|
181
|
+
"success": true,
|
|
182
|
+
"outliers": [
|
|
183
|
+
{
|
|
184
|
+
"lead_id": "lead_451",
|
|
185
|
+
"email": "suspicious@example.com",
|
|
186
|
+
"first_name": "João",
|
|
187
|
+
"last_name": "Silva",
|
|
188
|
+
"ltv_class": "High",
|
|
189
|
+
"behavior_score": 98,
|
|
190
|
+
"engagement_score": 85,
|
|
191
|
+
"intention_level": 90,
|
|
192
|
+
"days_since_lead": 0,
|
|
193
|
+
"cluster_id": null,
|
|
194
|
+
"cluster_name": "Outlier",
|
|
195
|
+
"confidence": 0.12,
|
|
196
|
+
"distance_to_centroid": 0.89,
|
|
197
|
+
"is_outlier": true,
|
|
198
|
+
"outlier_reason": "behavior_score too high (> 95), instant lead, suspicious",
|
|
199
|
+
"risk_level": "high",
|
|
200
|
+
"risk_score": 88,
|
|
201
|
+
"should_block": true,
|
|
202
|
+
"actionable_reasons": [
|
|
203
|
+
"Comportamento extremamente ativo (possível bot)",
|
|
204
|
+
"Lead instantâneo com engajamento muito alto (suspicious)"
|
|
205
|
+
],
|
|
206
|
+
"assigned_at": "2026-04-09T18:47:15.000Z"
|
|
207
|
+
}
|
|
208
|
+
],
|
|
209
|
+
"statistics": {
|
|
210
|
+
"total_outliers": 20,
|
|
211
|
+
"by_risk_level": {
|
|
212
|
+
"high": 15,
|
|
213
|
+
"medium": 3,
|
|
214
|
+
"low": 2
|
|
215
|
+
},
|
|
216
|
+
"by_reason": {
|
|
217
|
+
"behavior_score too high (> 95)": 12,
|
|
218
|
+
"instant lead": 8,
|
|
219
|
+
"unusual geo": 0
|
|
220
|
+
},
|
|
221
|
+
"avg_confidence": 0.18
|
|
222
|
+
},
|
|
223
|
+
"generated_at": "2026-04-09T18:47:15.000Z"
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## 4. PUT /api/segmentation/update — Atualizar Segmento
|
|
230
|
+
|
|
231
|
+
Atualiza recomendações de ações, bids e campanhas de um segmento existente.
|
|
232
|
+
|
|
233
|
+
### Request Body
|
|
234
|
+
|
|
235
|
+
```json
|
|
236
|
+
{
|
|
237
|
+
"cluster_id": 45,
|
|
238
|
+
"action_recommendations": [
|
|
239
|
+
"Priorizar remarketing em 24h",
|
|
240
|
+
"Criar lookalike audience de alto valor",
|
|
241
|
+
"Enrichir creative com copy específico"
|
|
242
|
+
],
|
|
243
|
+
"bid_recommendations": [
|
|
244
|
+
{"adset_id": "456", "recommended_bid": "R$ 20.00"},
|
|
245
|
+
{"adset_id": "789", "recommended_bid": "R$ 18.50"}
|
|
246
|
+
],
|
|
247
|
+
"campaign_recommendations": [
|
|
248
|
+
{"creative": "VSL Segmentado", "audience": "Segmento 0"}
|
|
249
|
+
],
|
|
250
|
+
"is_active": true
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Response
|
|
255
|
+
|
|
256
|
+
```json
|
|
257
|
+
{
|
|
258
|
+
"success": true,
|
|
259
|
+
"cluster_id": 45,
|
|
260
|
+
"cluster_name": "Segmento 0 - Alto Valor + Alto Engajamento (SP)",
|
|
261
|
+
"updates_applied": {
|
|
262
|
+
"action_recommendations": 3,
|
|
263
|
+
"bid_recommendations": 2,
|
|
264
|
+
"campaign_recommendations": 1,
|
|
265
|
+
"is_active": true
|
|
266
|
+
},
|
|
267
|
+
"updated_at": "2026-04-09T18:50:23.000Z"
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## Estrutura das Tabelas D1
|
|
274
|
+
|
|
275
|
+
### ml_segments — Metadados dos Segmentos
|
|
276
|
+
|
|
277
|
+
```sql
|
|
278
|
+
CREATE TABLE ml_segments (
|
|
279
|
+
id INTEGER PRIMARY KEY,
|
|
280
|
+
cluster_id INTEGER NOT NULL,
|
|
281
|
+
cluster_name TEXT NOT NULL,
|
|
282
|
+
clustering_algorithm TEXT NOT NULL, -- 'kmeans', 'dbscan', 'hierarchical'
|
|
283
|
+
client_vertical TEXT,
|
|
284
|
+
created_at TEXT,
|
|
285
|
+
updated_at TEXT,
|
|
286
|
+
|
|
287
|
+
-- Estatísticas
|
|
288
|
+
size INTEGER, -- Nº de leads
|
|
289
|
+
percentage REAL, -- % do total
|
|
290
|
+
|
|
291
|
+
-- Centróides (médias)
|
|
292
|
+
avg_ltv REAL,
|
|
293
|
+
avg_ltv_class REAL,
|
|
294
|
+
avg_behavior_score REAL,
|
|
295
|
+
avg_engagement_score REAL,
|
|
296
|
+
avg_intention_level REAL,
|
|
297
|
+
|
|
298
|
+
-- Características dominantes
|
|
299
|
+
dominant_countries TEXT, -- JSON: ["BR", "US"]
|
|
300
|
+
dominant_states TEXT, -- JSON: ["SP", "RJ"]
|
|
301
|
+
dominant_cities TEXT, -- JSON: ["São Paulo", "Rio"]
|
|
302
|
+
dominant_timezones TEXT, -- JSON: ["America/Sao_Paulo"]
|
|
303
|
+
dominant_utm_sources TEXT, -- JSON: ["facebook", "google"]
|
|
304
|
+
dominant_features TEXT, -- JSON: ["ltv", "behavior_score"]
|
|
305
|
+
|
|
306
|
+
-- Métricas de qualidade
|
|
307
|
+
silhouette_score REAL, -- 0-1 (quanto maior, melhor)
|
|
308
|
+
cohesion REAL, -- Similaridade intra-cluster
|
|
309
|
+
separation REAL, -- Distância inter-cluster
|
|
310
|
+
inertia REAL, -- Soma dos quadrados
|
|
311
|
+
|
|
312
|
+
-- Recomendações automáticas
|
|
313
|
+
action_recommendations TEXT, -- JSON array
|
|
314
|
+
bid_recommendations TEXT, -- JSON array
|
|
315
|
+
campaign_recommendations TEXT, -- JSON array
|
|
316
|
+
|
|
317
|
+
-- Metadados
|
|
318
|
+
is_active INTEGER DEFAULT 1,
|
|
319
|
+
min_data_points INTEGER,
|
|
320
|
+
epsilon REAL, -- DBSCAN
|
|
321
|
+
min_samples INTEGER, -- DBSCAN
|
|
322
|
+
max_depth INTEGER -- Hierarchical
|
|
323
|
+
);
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### ml_segment_members — Associação Lead ↔ Segmento
|
|
327
|
+
|
|
328
|
+
```sql
|
|
329
|
+
CREATE TABLE ml_segment_members (
|
|
330
|
+
id INTEGER PRIMARY KEY,
|
|
331
|
+
lead_id TEXT NOT NULL,
|
|
332
|
+
cluster_id INTEGER NOT NULL,
|
|
333
|
+
clustering_algorithm TEXT NOT NULL,
|
|
334
|
+
confidence REAL NOT NULL, -- 0-1 (quão perto do centroide)
|
|
335
|
+
distance_to_centroid REAL,
|
|
336
|
+
updated_at TEXT,
|
|
337
|
+
assigned_at TEXT,
|
|
338
|
+
is_outlier INTEGER DEFAULT 0,
|
|
339
|
+
outlier_reason TEXT,
|
|
340
|
+
|
|
341
|
+
-- Estado do lead no momento da atribuição
|
|
342
|
+
lead_ltv REAL,
|
|
343
|
+
lead_ltv_class REAL,
|
|
344
|
+
lead_behavior_score REAL,
|
|
345
|
+
lead_engagement_score REAL,
|
|
346
|
+
lead_intention_level REAL,
|
|
347
|
+
|
|
348
|
+
-- Características
|
|
349
|
+
lead_country TEXT,
|
|
350
|
+
lead_state TEXT,
|
|
351
|
+
lead_city TEXT,
|
|
352
|
+
|
|
353
|
+
UNIQUE(lead_id, cluster_id, clustering_algorithm)
|
|
354
|
+
);
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
---
|
|
358
|
+
|
|
359
|
+
## Integração com Outros Agentes
|
|
360
|
+
|
|
361
|
+
### Com LTV Predictor Agent
|
|
362
|
+
|
|
363
|
+
```typescript
|
|
364
|
+
// Enricher predição LTV com segment_id
|
|
365
|
+
const enrichedLTV = {
|
|
366
|
+
original_prediction: 497.50,
|
|
367
|
+
segment_id: 123,
|
|
368
|
+
segment_name: "Alto Valor + Alto Engajamento (SP)",
|
|
369
|
+
adjusted_prediction: 612.30, // +23% baseado no segmento
|
|
370
|
+
confidence: 0.85
|
|
371
|
+
};
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### Com Dashboard Agent
|
|
375
|
+
|
|
376
|
+
```typescript
|
|
377
|
+
// Visualização de segmentos em gráficos
|
|
378
|
+
const segmentChartData = {
|
|
379
|
+
labels: ["Segmento 0", "Segmento 1", "Segmento 2"],
|
|
380
|
+
data: [95, 150, 120, 85, 50],
|
|
381
|
+
colors: ["#22c55e", "#3b82f6", "#1e40af", "#06b6d4", "#f59e0b"]
|
|
382
|
+
};
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### Com Meta Agent
|
|
386
|
+
|
|
387
|
+
```typescript
|
|
388
|
+
// Criar campanhas segmentadas por segmento
|
|
389
|
+
const segmentedCampaigns = [
|
|
390
|
+
{
|
|
391
|
+
adset_name: "Segmento 0 - Alto Valor",
|
|
392
|
+
audience: ml_segment_id_123,
|
|
393
|
+
creative: "VSL Personalizado Segmento 0",
|
|
394
|
+
bid_strategy: "high_bid"
|
|
395
|
+
}
|
|
396
|
+
];
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
---
|
|
400
|
+
|
|
401
|
+
## Troubleshooting Comum
|
|
402
|
+
|
|
403
|
+
### Erro: "Dados insuficientes para clustering"
|
|
404
|
+
|
|
405
|
+
**Causa:** Menos de 100 leads nos últimos 6 meses
|
|
406
|
+
|
|
407
|
+
**Solução:**
|
|
408
|
+
- Aguardar mais dados acumularem
|
|
409
|
+
- Aumentar `max_data_age_months` para 12
|
|
410
|
+
- Usar `force=true` para clustering com menos dados
|
|
411
|
+
|
|
412
|
+
### Erro: "Silhouette Score < 0.3"
|
|
413
|
+
|
|
414
|
+
**Causa:** Clusters não são bem separados
|
|
415
|
+
|
|
416
|
+
**Solução:**
|
|
417
|
+
- Aumentar `n_clusters` para 7-10
|
|
418
|
+
- Reduzir dimensionalidade (usar features mais importantes)
|
|
419
|
+
- Usar algoritmo `hierarchical` em vez de `kmeans`
|
|
420
|
+
|
|
421
|
+
### Erro: "Workers AI timeout"
|
|
422
|
+
|
|
423
|
+
**Causa:** Prompt muito longo ou muitos dados
|
|
424
|
+
|
|
425
|
+
**Solução:**
|
|
426
|
+
- Reduzir leads por batch (max 500)
|
|
427
|
+
- Simplificar prompt (menos instruções)
|
|
428
|
+
- Aumentar timeout no wrangler.toml
|
|
429
|
+
|
|
430
|
+
---
|
|
431
|
+
|
|
432
|
+
## Roadmap Futuro
|
|
433
|
+
|
|
434
|
+
- [ ] DBSCAN Clustering completo (outliers avançado)
|
|
435
|
+
- [ ] Hierarchical Clustering (drill-down de clusters)
|
|
436
|
+
- [ ] Auto-feature selection (identificar features mais importantes)
|
|
437
|
+
- [ ] Clustering temporal (leads mudam de segmento ao longo do tempo)
|
|
438
|
+
- [ ] A/B testing automático de segmentos
|
|
439
|
+
- [ ] Dashboard visual de segmentos em gráficos interativos
|
|
440
|
+
|
|
441
|
+
---
|
|
442
|
+
|
|
443
|
+
*API de Segmentação Dinâmica ML v1.0 — CDP Edge*
|
|
444
|
+
*Data: 9 de Abril de 2026*
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
-- Schema A/B Testing de Prompts LTV — CDP Edge Quantum Tier
|
|
2
|
+
-- Versão: 1.0
|
|
3
|
+
-- Data: 9 de Abril de 2026
|
|
4
|
+
-- Fase 3 Enterprise-Level
|
|
5
|
+
|
|
6
|
+
-- TABELA: Experimentos A/B
|
|
7
|
+
CREATE TABLE IF NOT EXISTS ltv_ab_tests (
|
|
8
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
9
|
+
name TEXT NOT NULL,
|
|
10
|
+
description TEXT,
|
|
11
|
+
status TEXT NOT NULL DEFAULT 'draft', -- 'draft', 'running', 'paused', 'completed'
|
|
12
|
+
winner_id INTEGER, -- FK para ltv_ab_variations.id
|
|
13
|
+
started_at TEXT,
|
|
14
|
+
completed_at TEXT,
|
|
15
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
16
|
+
min_sample INTEGER NOT NULL DEFAULT 100, -- Mínimo de assignments para declarar vencedor
|
|
17
|
+
confidence_threshold REAL NOT NULL DEFAULT 0.90 -- Nível de confiança estatística (90%)
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
-- TABELA: Variações de Prompt por Experimento
|
|
21
|
+
CREATE TABLE IF NOT EXISTS ltv_ab_variations (
|
|
22
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
23
|
+
test_id INTEGER NOT NULL REFERENCES ltv_ab_tests(id),
|
|
24
|
+
name TEXT NOT NULL, -- Ex: 'Variação A — Foco em Engajamento'
|
|
25
|
+
system_prompt TEXT NOT NULL, -- O prompt system enviado ao Workers AI
|
|
26
|
+
weight REAL NOT NULL DEFAULT 0.5, -- Peso de distribuição (0-1, soma deve = 1)
|
|
27
|
+
is_control INTEGER NOT NULL DEFAULT 0, -- 1 = variação controle (baseline)
|
|
28
|
+
|
|
29
|
+
-- Métricas acumuladas
|
|
30
|
+
total_assigned INTEGER NOT NULL DEFAULT 0,
|
|
31
|
+
total_purchases INTEGER NOT NULL DEFAULT 0,
|
|
32
|
+
sum_predicted_ltv REAL NOT NULL DEFAULT 0,
|
|
33
|
+
sum_real_revenue REAL NOT NULL DEFAULT 0,
|
|
34
|
+
|
|
35
|
+
-- Métricas calculadas (atualizadas por trigger ou batch)
|
|
36
|
+
avg_predicted_ltv REAL,
|
|
37
|
+
avg_real_revenue REAL,
|
|
38
|
+
conversion_rate REAL,
|
|
39
|
+
accuracy_score REAL, -- Quão próximo do valor real (1 - |predicted-real|/real)
|
|
40
|
+
|
|
41
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
-- TABELA: Assignments — qual variação foi usada para qual lead
|
|
45
|
+
CREATE TABLE IF NOT EXISTS ltv_ab_assignments (
|
|
46
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
47
|
+
test_id INTEGER NOT NULL REFERENCES ltv_ab_tests(id),
|
|
48
|
+
variation_id INTEGER NOT NULL REFERENCES ltv_ab_variations(id),
|
|
49
|
+
user_id TEXT NOT NULL,
|
|
50
|
+
email_hash TEXT, -- SHA256 do email (indexação sem PII)
|
|
51
|
+
predicted_ltv REAL,
|
|
52
|
+
predicted_class TEXT,
|
|
53
|
+
assigned_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
54
|
+
|
|
55
|
+
-- Preenchido quando purchase chega via webhook
|
|
56
|
+
converted INTEGER NOT NULL DEFAULT 0,
|
|
57
|
+
real_revenue REAL,
|
|
58
|
+
converted_at TEXT
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
-- Índices
|
|
62
|
+
CREATE INDEX IF NOT EXISTS idx_ab_tests_status ON ltv_ab_tests(status);
|
|
63
|
+
CREATE INDEX IF NOT EXISTS idx_ab_variations_test ON ltv_ab_variations(test_id);
|
|
64
|
+
CREATE INDEX IF NOT EXISTS idx_ab_assignments_test ON ltv_ab_assignments(test_id);
|
|
65
|
+
CREATE INDEX IF NOT EXISTS idx_ab_assignments_user ON ltv_ab_assignments(user_id);
|
|
66
|
+
CREATE INDEX IF NOT EXISTS idx_ab_assignments_email ON ltv_ab_assignments(email_hash);
|
|
67
|
+
CREATE INDEX IF NOT EXISTS idx_ab_assignments_conv ON ltv_ab_assignments(converted);
|
|
68
|
+
|
|
69
|
+
-- VIEW: Resumo de performance por variação
|
|
70
|
+
CREATE VIEW IF NOT EXISTS v_ab_test_performance AS
|
|
71
|
+
SELECT
|
|
72
|
+
t.id AS test_id,
|
|
73
|
+
t.name AS test_name,
|
|
74
|
+
t.status,
|
|
75
|
+
v.id AS variation_id,
|
|
76
|
+
v.name AS variation_name,
|
|
77
|
+
v.is_control,
|
|
78
|
+
v.weight,
|
|
79
|
+
v.total_assigned,
|
|
80
|
+
v.total_purchases,
|
|
81
|
+
CASE WHEN v.total_assigned > 0
|
|
82
|
+
THEN ROUND(CAST(v.total_purchases AS REAL) / v.total_assigned * 100, 2)
|
|
83
|
+
ELSE 0
|
|
84
|
+
END AS conversion_rate_pct,
|
|
85
|
+
CASE WHEN v.total_assigned > 0
|
|
86
|
+
THEN ROUND(v.sum_predicted_ltv / v.total_assigned, 2)
|
|
87
|
+
ELSE 0
|
|
88
|
+
END AS avg_predicted_ltv,
|
|
89
|
+
CASE WHEN v.total_purchases > 0
|
|
90
|
+
THEN ROUND(v.sum_real_revenue / v.total_purchases, 2)
|
|
91
|
+
ELSE 0
|
|
92
|
+
END AS avg_real_revenue,
|
|
93
|
+
v.accuracy_score,
|
|
94
|
+
t.winner_id = v.id AS is_winner
|
|
95
|
+
FROM ltv_ab_tests t
|
|
96
|
+
JOIN ltv_ab_variations v ON v.test_id = t.id
|
|
97
|
+
ORDER BY t.id, v.id;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
-- Schema de Recomendações de Bids Automáticas — CDP Edge Quantum Tier
|
|
2
|
+
-- Versão: 1.0
|
|
3
|
+
-- Data: 9 de Abril de 2026
|
|
4
|
+
-- Complementa: schema-segmentation.sql
|
|
5
|
+
|
|
6
|
+
-- TABELA PRINCIPAL: Recomendações de Bids
|
|
7
|
+
CREATE TABLE IF NOT EXISTS bid_recommendations (
|
|
8
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
9
|
+
generated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
10
|
+
vertical TEXT NOT NULL, -- 'infoproduto', 'ecommerce', 'saas'
|
|
11
|
+
platform TEXT NOT NULL, -- 'meta', 'google', 'tiktok', 'all'
|
|
12
|
+
period_days INTEGER NOT NULL DEFAULT 30, -- Janela de análise
|
|
13
|
+
target_roi REAL NOT NULL DEFAULT 3.5, -- ROI alvo
|
|
14
|
+
|
|
15
|
+
-- Segmento ML de origem (FK para ml_segments)
|
|
16
|
+
segment_id INTEGER,
|
|
17
|
+
segment_name TEXT,
|
|
18
|
+
|
|
19
|
+
-- Dados analisados
|
|
20
|
+
leads_analyzed INTEGER NOT NULL DEFAULT 0,
|
|
21
|
+
conversions_found INTEGER NOT NULL DEFAULT 0,
|
|
22
|
+
avg_ltv REAL, -- LTV médio do segmento
|
|
23
|
+
cpa_target REAL, -- CPA alvo calculado: avg_ltv / target_roi
|
|
24
|
+
|
|
25
|
+
-- Output: O Bid em si
|
|
26
|
+
recommended_bid REAL, -- Bid recomendado em BRL
|
|
27
|
+
bid_currency TEXT NOT NULL DEFAULT 'BRL',
|
|
28
|
+
confidence REAL NOT NULL DEFAULT 0, -- 0-1 (base: conversions / 100)
|
|
29
|
+
expected_roi REAL, -- ROI esperado com este bid
|
|
30
|
+
|
|
31
|
+
-- Rastreabilidade
|
|
32
|
+
reasoning TEXT, -- Explicação detalhada da lógica
|
|
33
|
+
ai_used INTEGER DEFAULT 0, -- 1 = Workers AI usado
|
|
34
|
+
alert_message TEXT, -- Ex: "Dados insuficientes (< 30 conversões)"
|
|
35
|
+
|
|
36
|
+
-- Fatores internos de cálculo (para auditoria)
|
|
37
|
+
platform_factor REAL, -- 0.75–0.90 por plataforma
|
|
38
|
+
confidence_adjustment REAL, -- 0.70–1.00 por nível de confiança
|
|
39
|
+
segment_multiplier REAL, -- 0.60–1.40 por tipo de segmento
|
|
40
|
+
|
|
41
|
+
-- Ciclo de vida
|
|
42
|
+
is_active INTEGER NOT NULL DEFAULT 1,
|
|
43
|
+
applied_at TEXT, -- Quando o usuário aplicou o bid
|
|
44
|
+
applied_campaign TEXT, -- ID da campanha onde foi aplicado
|
|
45
|
+
applied_result TEXT -- JSON: {clicks, conversions, real_roi}
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
-- Índices
|
|
49
|
+
CREATE INDEX IF NOT EXISTS idx_bid_recs_vertical ON bid_recommendations(vertical);
|
|
50
|
+
CREATE INDEX IF NOT EXISTS idx_bid_recs_platform ON bid_recommendations(platform);
|
|
51
|
+
CREATE INDEX IF NOT EXISTS idx_bid_recs_generated ON bid_recommendations(generated_at);
|
|
52
|
+
CREATE INDEX IF NOT EXISTS idx_bid_recs_active ON bid_recommendations(is_active);
|
|
53
|
+
CREATE INDEX IF NOT EXISTS idx_bid_recs_segment ON bid_recommendations(segment_id);
|
|
54
|
+
CREATE INDEX IF NOT EXISTS idx_bid_recs_confidence ON bid_recommendations(confidence);
|
|
55
|
+
|
|
56
|
+
-- VIEW: Recomendações Ativas (com dados dos segmentos)
|
|
57
|
+
CREATE VIEW IF NOT EXISTS v_active_bid_recommendations AS
|
|
58
|
+
SELECT
|
|
59
|
+
br.id,
|
|
60
|
+
br.generated_at,
|
|
61
|
+
br.vertical,
|
|
62
|
+
br.platform,
|
|
63
|
+
br.period_days,
|
|
64
|
+
br.target_roi,
|
|
65
|
+
br.segment_name,
|
|
66
|
+
br.leads_analyzed,
|
|
67
|
+
br.conversions_found,
|
|
68
|
+
br.avg_ltv,
|
|
69
|
+
br.cpa_target,
|
|
70
|
+
br.recommended_bid,
|
|
71
|
+
br.bid_currency,
|
|
72
|
+
br.confidence,
|
|
73
|
+
br.expected_roi,
|
|
74
|
+
br.reasoning,
|
|
75
|
+
br.alert_message,
|
|
76
|
+
br.ai_used,
|
|
77
|
+
-- Dados do segmento ML relacionado
|
|
78
|
+
ms.cluster_name AS ml_cluster_name,
|
|
79
|
+
ms.avg_behavior_score,
|
|
80
|
+
ms.avg_engagement_score,
|
|
81
|
+
ms.silhouette_score,
|
|
82
|
+
ms.size AS segment_size
|
|
83
|
+
FROM bid_recommendations br
|
|
84
|
+
LEFT JOIN ml_segments ms ON br.segment_id = ms.id
|
|
85
|
+
WHERE br.is_active = 1
|
|
86
|
+
ORDER BY br.generated_at DESC;
|