cdp-edge 1.2.2 → 1.4.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 +153 -306
- package/bin/cdp-edge.js +71 -61
- package/contracts/agent-versions.json +682 -0
- package/contracts/api-versions.json +372 -368
- package/contracts/types.ts +81 -0
- package/dist/commands/analyze.js +52 -52
- package/dist/commands/infra.js +54 -54
- package/dist/commands/install.js +26 -3
- package/dist/commands/server.js +174 -174
- package/dist/commands/setup.js +332 -100
- package/dist/commands/validate.js +248 -84
- package/dist/index.js +12 -12
- package/dist/sdk/cdpTrack.js +2095 -0
- package/dist/sdk/cdpTrack.min.js +64 -0
- package/dist/sdk/install-snippet.html +10 -0
- package/docs/whatsapp-ctwa.md +5 -4
- package/extracted-skill/tracking-events-generator/INTEGRACAO-COMPLETA.md +89 -0
- package/extracted-skill/tracking-events-generator/MELHORIAS-IMPLEMENTADAS.md +101 -0
- package/extracted-skill/tracking-events-generator/advanced-matching.js +364 -364
- package/extracted-skill/tracking-events-generator/agents/ab-ltv-agent.md +196 -0
- package/extracted-skill/tracking-events-generator/agents/ab-testing-agent.md +1 -1
- package/extracted-skill/tracking-events-generator/agents/attribution-agent.md +41 -41
- package/extracted-skill/tracking-events-generator/agents/bidding-agent.md +347 -0
- package/extracted-skill/tracking-events-generator/agents/bing-agent.md +40 -50
- package/extracted-skill/tracking-events-generator/agents/browser-tracking.md +174 -74
- package/extracted-skill/tracking-events-generator/agents/code-guardian-agent.md +1 -1
- package/extracted-skill/tracking-events-generator/agents/compliance-agent.md +25 -5
- package/extracted-skill/tracking-events-generator/agents/dashboard-agent.md +10 -10
- package/extracted-skill/tracking-events-generator/agents/database-agent.md +43 -42
- package/extracted-skill/tracking-events-generator/agents/debug-agent.md +22 -22
- package/extracted-skill/tracking-events-generator/agents/devops-agent.md +232 -0
- package/extracted-skill/tracking-events-generator/agents/domain-setup-agent.md +23 -9
- package/extracted-skill/tracking-events-generator/agents/email-agent.md +28 -1
- package/extracted-skill/tracking-events-generator/agents/evo-crm-agent.md +253 -0
- package/extracted-skill/tracking-events-generator/agents/fingerprint-agent.md +206 -1
- package/extracted-skill/tracking-events-generator/agents/fraud-detection-agent.md +143 -0
- package/extracted-skill/tracking-events-generator/agents/google-agent.md +128 -2
- package/extracted-skill/tracking-events-generator/agents/intelligence-agent.md +191 -31
- package/extracted-skill/tracking-events-generator/agents/lead-scoring-agent.md +282 -0
- package/extracted-skill/tracking-events-generator/agents/linkedin-agent.md +145 -34
- package/extracted-skill/tracking-events-generator/agents/localization-agent.md +1 -1
- package/extracted-skill/tracking-events-generator/agents/ltv-predictor-agent.md +24 -5
- package/extracted-skill/tracking-events-generator/agents/master-feedback-loop.md +81 -21
- package/extracted-skill/tracking-events-generator/agents/master-orchestrator.md +588 -93
- package/extracted-skill/tracking-events-generator/agents/match-quality-agent.md +304 -0
- package/extracted-skill/tracking-events-generator/agents/memory-agent.md +190 -15
- package/extracted-skill/tracking-events-generator/agents/meta-agent.md +10 -2
- package/extracted-skill/tracking-events-generator/agents/ml-clustering-agent.md +769 -0
- package/extracted-skill/tracking-events-generator/agents/page-analyzer.md +21 -4
- package/extracted-skill/tracking-events-generator/agents/performance-agent.md +41 -31
- package/extracted-skill/tracking-events-generator/agents/performance-optimization-agent.md +18 -8
- package/extracted-skill/tracking-events-generator/agents/pinterest-agent.md +14 -6
- package/extracted-skill/tracking-events-generator/agents/premium-tracking-intelligence-agent.md +7 -7
- package/extracted-skill/tracking-events-generator/agents/r2-setup-agent.md +16 -8
- package/extracted-skill/tracking-events-generator/agents/reddit-agent.md +15 -7
- package/extracted-skill/tracking-events-generator/agents/security-enterprise-agent.md +157 -48
- package/extracted-skill/tracking-events-generator/agents/server-tracking.md +35 -35
- package/extracted-skill/tracking-events-generator/agents/spotify-agent.md +15 -7
- package/extracted-skill/tracking-events-generator/agents/tiktok-agent.md +73 -2
- package/extracted-skill/tracking-events-generator/agents/tracking-plan-agent.md +104 -9
- package/extracted-skill/tracking-events-generator/agents/utm-agent.md +322 -0
- package/extracted-skill/tracking-events-generator/agents/validator-agent.md +13 -9
- package/extracted-skill/tracking-events-generator/agents/webhook-agent.md +112 -4
- package/extracted-skill/tracking-events-generator/agents/whatsapp-agent.md +58 -5
- package/extracted-skill/tracking-events-generator/agents/whatsapp-ctwa-setup-agent.md +26 -18
- package/extracted-skill/tracking-events-generator/agents/youtube-agent.md +152 -37
- package/extracted-skill/tracking-events-generator/anti-blocking.js +285 -285
- package/extracted-skill/tracking-events-generator/cdpTrack.js +642 -641
- package/extracted-skill/tracking-events-generator/contracts/api-versions.json +14 -10
- package/extracted-skill/tracking-events-generator/engagement-scoring.js +226 -226
- package/extracted-skill/tracking-events-generator/evals/evals.json +235 -235
- package/extracted-skill/tracking-events-generator/integration-test.js +497 -497
- package/extracted-skill/tracking-events-generator/knowledge-base.md +172 -0
- package/extracted-skill/tracking-events-generator/micro-events.js +992 -992
- package/extracted-skill/tracking-events-generator/models/lancamento-imobiliario.md +344 -0
- package/extracted-skill/tracking-events-generator/models/pinterest/conversions-api-template.js +144 -144
- package/extracted-skill/tracking-events-generator/models/pinterest/event-mappings.json +48 -48
- package/extracted-skill/tracking-events-generator/models/pinterest/tag-template.js +28 -28
- package/extracted-skill/tracking-events-generator/models/quiz-funnel.md +83 -19
- package/extracted-skill/tracking-events-generator/models/reddit/conversions-api-template.js +205 -205
- package/extracted-skill/tracking-events-generator/models/reddit/event-mappings.json +56 -56
- package/extracted-skill/tracking-events-generator/models/reddit/pixel-template.js +19 -19
- package/extracted-skill/tracking-events-generator/models/scenarios/behavior-engine.js +425 -425
- package/extracted-skill/tracking-events-generator/route-intent-capture.js +222 -0
- package/extracted-skill/tracking-events-generator/tracking.config.js +3 -3
- package/package.json +89 -75
- package/scripts/build-sdk.js +106 -0
- package/server-edge-tracker/.client.env.example +14 -0
- package/server-edge-tracker/INSTALAR.md +222 -23
- package/server-edge-tracker/SEGMENTATION-DOCS.md +513 -0
- package/server-edge-tracker/config/utm-mapping.json +64 -0
- package/server-edge-tracker/deploy-client.cjs +76 -0
- package/server-edge-tracker/index.ts +1230 -0
- package/server-edge-tracker/migrate-v7.sql +64 -0
- package/server-edge-tracker/modules/db.ts +710 -0
- package/server-edge-tracker/modules/dispatch/crm.ts +382 -0
- package/server-edge-tracker/modules/dispatch/ga4.ts +72 -0
- package/server-edge-tracker/modules/dispatch/meta.ts +143 -0
- package/server-edge-tracker/modules/dispatch/platforms.ts +255 -0
- package/server-edge-tracker/modules/dispatch/tiktok.ts +107 -0
- package/server-edge-tracker/modules/dispatch/whatsapp.ts +296 -0
- package/server-edge-tracker/modules/intelligence.ts +589 -0
- package/server-edge-tracker/modules/ml/bidding.ts +247 -0
- package/server-edge-tracker/modules/ml/fraud.ts +302 -0
- package/server-edge-tracker/modules/ml/logistic.ts +226 -0
- package/server-edge-tracker/modules/ml/ltv.ts +531 -0
- package/server-edge-tracker/modules/ml/matchquality.ts +232 -0
- package/server-edge-tracker/modules/ml/quiz.ts +343 -0
- package/server-edge-tracker/modules/ml/roas.ts +255 -0
- package/server-edge-tracker/modules/ml/segmentation.ts +407 -0
- package/server-edge-tracker/modules/nurture.ts +257 -0
- package/server-edge-tracker/modules/utils.ts +311 -0
- package/server-edge-tracker/modules/utm/utm-enricher.ts +231 -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-indexes.sql +67 -0
- package/server-edge-tracker/schema-ltv-feedback.sql +11 -0
- package/server-edge-tracker/schema-quiz.sql +52 -0
- package/server-edge-tracker/schema-sales-engine.sql +113 -0
- package/server-edge-tracker/schema-segmentation.sql +219 -0
- package/server-edge-tracker/schema-utm.sql +82 -0
- package/server-edge-tracker/schema.sql +281 -265
- package/server-edge-tracker/types.ts +275 -0
- package/server-edge-tracker/wrangler.toml +140 -85
- package/templates/lancamento-imobiliario.md +344 -0
- package/templates/multi-step-checkout.md +3 -4
- package/templates/pinterest/conversions-api-template.js +144 -144
- package/templates/pinterest/event-mappings.json +48 -48
- package/templates/pinterest/tag-template.js +28 -28
- package/templates/quiz-funnel.md +83 -19
- package/templates/reddit/conversions-api-template.js +205 -205
- package/templates/reddit/event-mappings.json +56 -56
- package/templates/reddit/pixel-template.js +12 -39
- package/templates/scenarios/behavior-engine.js +45 -22
- package/docs/PixelBuilder-Documentacao-Completa (2).docx +0 -0
- package/docs/installation.md +0 -155
- package/docs/quick-start.md +0 -185
- package/extracted-skill/tracking-events-generator/agents/crm-integration-agent.md +0 -1419
- package/extracted-skill/tracking-events-generator/agents/intelligence-scheduling.md +0 -643
- package/server-edge-tracker/worker.js +0 -2574
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UTM Enricher Module
|
|
3
|
+
* Obfusca/desobfusca UTMs sensíveis (valores de produto)
|
|
4
|
+
* Integração com Agente UTM
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// Constants & Config
|
|
9
|
+
// ============================================================================
|
|
10
|
+
|
|
11
|
+
const UTM_SALT = 'CDP_EDGE_UTM_SALT';
|
|
12
|
+
const HASH_TRUNCATE_LENGTH = 8;
|
|
13
|
+
|
|
14
|
+
// Obfuscação: SHA256(original + salt) → truncate(8)
|
|
15
|
+
// Isso garante: mesmo valor → mesmo hash, mas irreversível sem o mapeamento
|
|
16
|
+
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// Types
|
|
19
|
+
// ============================================================================
|
|
20
|
+
|
|
21
|
+
export interface UTMMapping {
|
|
22
|
+
obfuscated: string; // Hash truncado (ex: "8a3f1d2b")
|
|
23
|
+
original: string; // Valor real (ex: "700k-1M")
|
|
24
|
+
category: string; // "imovel", "automotivo", etc
|
|
25
|
+
pixel_audience?: string; // ID da custom audience Meta
|
|
26
|
+
platform_specific?: {
|
|
27
|
+
meta?: { custom_audience_id?: string };
|
|
28
|
+
tiktok?: { pixel_id?: string };
|
|
29
|
+
ga4?: { event_parameter?: string };
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface UTMMappingConfig {
|
|
34
|
+
method: 'sha256';
|
|
35
|
+
salt: string;
|
|
36
|
+
truncated_length: number;
|
|
37
|
+
mappings: UTMMapping[];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface EnrichedUTM {
|
|
41
|
+
source?: string;
|
|
42
|
+
medium?: string;
|
|
43
|
+
campaign?: string;
|
|
44
|
+
content?: string;
|
|
45
|
+
faixa_obfuscada?: string; // Hash da faixa de valor
|
|
46
|
+
faixa_real?: string; // Valor real (de-obfuscado)
|
|
47
|
+
faixa_category?: string; // Categoria do produto
|
|
48
|
+
product_id_obfuscated?: string;
|
|
49
|
+
product_id_real?: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// ============================================================================
|
|
53
|
+
// Core Functions
|
|
54
|
+
// ============================================================================
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Obfusca um valor sensível usando SHA256 + truncate
|
|
58
|
+
* @param value - Valor a ser obfuscado (ex: "700k-1M")
|
|
59
|
+
* @returns Hash truncado de 8 caracteres
|
|
60
|
+
*/
|
|
61
|
+
export function obfuscateValue(value: string): string {
|
|
62
|
+
// sha256(value + salt) → truncate(8)
|
|
63
|
+
const hash = sha256(`${value}${UTM_SALT}`);
|
|
64
|
+
return hash.substring(0, HASH_TRUNCATE_LENGTH);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Verifica se um hash é válido (8 chars hex)
|
|
69
|
+
*/
|
|
70
|
+
export function isValidObfuscatedHash(hash: string): boolean {
|
|
71
|
+
return /^[a-f0-9]{8}$/.test(hash);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Desobfusca um valor usando o mapeamento
|
|
76
|
+
* @param obfuscated - Hash obfuscado
|
|
77
|
+
* @param mappings - Mapeamento de UTM (do config/utm-mapping.json)
|
|
78
|
+
* @returns UTM com valor real ou undefined se não encontrado
|
|
79
|
+
*/
|
|
80
|
+
export function deobfuscateValue(
|
|
81
|
+
obfuscated: string,
|
|
82
|
+
mappings: UTMMapping[]
|
|
83
|
+
): UTMMapping | undefined {
|
|
84
|
+
return mappings.find(m => m.obfuscated === obfuscated);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Enrich payload com UTMs, desobfuscando valores sensíveis
|
|
89
|
+
*/
|
|
90
|
+
export function enrichPayloadWithUTM(
|
|
91
|
+
payload: any,
|
|
92
|
+
utms: Record<string, string>,
|
|
93
|
+
mappings: UTMMapping[]
|
|
94
|
+
): { enriched: any; faixa?: UTMMapping } {
|
|
95
|
+
const enriched = { ...payload };
|
|
96
|
+
let faixa: UTMMapping | undefined;
|
|
97
|
+
|
|
98
|
+
// Desobfuscar faixa de valor
|
|
99
|
+
if (utms.faixa_obfuscada || utms.utm_faixa) {
|
|
100
|
+
const faixaHash = utms.faixa_obfuscada || utms.utm_faixa;
|
|
101
|
+
if (isValidObfuscatedHash(faixaHash)) {
|
|
102
|
+
faixa = deobfuscateValue(faixaHash, mappings);
|
|
103
|
+
if (faixa) {
|
|
104
|
+
enriched.faixa_real = faixa.original;
|
|
105
|
+
enriched.faixa_category = faixa.category;
|
|
106
|
+
enriched.pixel_audience = faixa.pixel_audience;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Extrair UTMs padrão
|
|
112
|
+
enriched.utm_source = utms.utm_source || utms.source;
|
|
113
|
+
enriched.utm_medium = utms.utm_medium || utms.medium;
|
|
114
|
+
enriched.utm_campaign = utms.utm_campaign || utms.campaign;
|
|
115
|
+
enriched.utm_content = utms.utm_content || utms.content;
|
|
116
|
+
|
|
117
|
+
return { enriched, faixa };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Gera UTM obfuscada para uma faixa de valor
|
|
122
|
+
* @param range - Faixa real (ex: "700k-1M")
|
|
123
|
+
* @param category - Categoria (ex: "imovel")
|
|
124
|
+
* @returns Object com hash obfuscado
|
|
125
|
+
*/
|
|
126
|
+
export function generateObfuscatedUTM(range: string, category: string) {
|
|
127
|
+
const obfuscated = obfuscateValue(range);
|
|
128
|
+
return {
|
|
129
|
+
utm_faixa: obfuscated,
|
|
130
|
+
utm_campaign: `${category}_${obfuscated}`,
|
|
131
|
+
original_range: range,
|
|
132
|
+
hash: obfuscated
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Cria um novo mapeamento de UTM
|
|
138
|
+
*/
|
|
139
|
+
export function createUTMMapping(
|
|
140
|
+
original: string,
|
|
141
|
+
category: string,
|
|
142
|
+
platform_specific?: any
|
|
143
|
+
): UTMMapping {
|
|
144
|
+
return {
|
|
145
|
+
obfuscated: obfuscateValue(original),
|
|
146
|
+
original,
|
|
147
|
+
category,
|
|
148
|
+
platform_specific
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// ============================================================================
|
|
153
|
+
// Integration Functions (para uso no Worker)
|
|
154
|
+
// ============================================================================
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Verifica se payload tem UTMs de segmentação
|
|
158
|
+
*/
|
|
159
|
+
export function hasSegmentationUTM(utms: Record<string, string>): boolean {
|
|
160
|
+
return !!(
|
|
161
|
+
utms.faixa_obfuscada ||
|
|
162
|
+
utms.utm_faixa ||
|
|
163
|
+
(utms.utm_campaign && isValidObfuscatedHash(
|
|
164
|
+
utms.utm_campaign.split('_').pop() || ''
|
|
165
|
+
))
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Extrai faixa de valor do utm_campaign (pattern: category_hash)
|
|
171
|
+
*/
|
|
172
|
+
export function extractFaixaFromCampaign(
|
|
173
|
+
campaign: string
|
|
174
|
+
): string | null {
|
|
175
|
+
const parts = campaign.split('_');
|
|
176
|
+
const hash = parts.pop();
|
|
177
|
+
if (hash && isValidObfuscatedHash(hash)) {
|
|
178
|
+
return hash;
|
|
179
|
+
}
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Para Meta CAPI: adiciona segmentação ao external_id
|
|
185
|
+
*/
|
|
186
|
+
export function addSegmentationToExternalId(
|
|
187
|
+
cdp_uid: string,
|
|
188
|
+
faixa: UTMMapping
|
|
189
|
+
): string {
|
|
190
|
+
return `${cdp_uid}_${faixa.obfuscated}`;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Para GA4: cria custom parameter segmentado
|
|
195
|
+
*/
|
|
196
|
+
export function createSegmentationCustomParameter(faixa: UTMMapping) {
|
|
197
|
+
return {
|
|
198
|
+
'custom_faixa_categoria': faixa.category,
|
|
199
|
+
'custom_faixa_obfuscada': faixa.obfuscated,
|
|
200
|
+
'custom_faixa_audience': faixa.pixel_audience || 'UNKNOWN'
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// ============================================================================
|
|
205
|
+
// Import de sha256 (reutilizar de utils.ts)
|
|
206
|
+
// ============================================================================
|
|
207
|
+
|
|
208
|
+
function sha256(message: string): string {
|
|
209
|
+
// Importado de utils.ts - implementação real do SHA256
|
|
210
|
+
// Aqui simulamos para o exemplo:
|
|
211
|
+
const crypto = require('crypto');
|
|
212
|
+
return crypto.createHash('sha256').update(message).digest('hex');
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// ============================================================================
|
|
216
|
+
// Export
|
|
217
|
+
// ============================================================================
|
|
218
|
+
|
|
219
|
+
export const UTM_ENRICHER_VERSION = '1.0.0';
|
|
220
|
+
|
|
221
|
+
export default {
|
|
222
|
+
obfuscateValue,
|
|
223
|
+
deobfuscateValue,
|
|
224
|
+
enrichPayloadWithUTM,
|
|
225
|
+
generateObfuscatedUTM,
|
|
226
|
+
createUTMMapping,
|
|
227
|
+
hasSegmentationUTM,
|
|
228
|
+
extractFaixaFromCampaign,
|
|
229
|
+
addSegmentationToExternalId,
|
|
230
|
+
createSegmentationCustomParameter
|
|
231
|
+
};
|
|
@@ -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;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
-- Schema Fraud Detection — CDP Edge Quantum Tier
|
|
2
|
+
-- Versão: 1.0
|
|
3
|
+
-- Data: 9 de Abril de 2026
|
|
4
|
+
-- Fase 4 Enterprise-Level
|
|
5
|
+
|
|
6
|
+
-- TABELA: Sinais de Fraude por Evento
|
|
7
|
+
CREATE TABLE IF NOT EXISTS fraud_signals (
|
|
8
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
9
|
+
detected_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
10
|
+
|
|
11
|
+
-- Identificadores do evento
|
|
12
|
+
ip_address TEXT,
|
|
13
|
+
fingerprint TEXT,
|
|
14
|
+
user_id TEXT,
|
|
15
|
+
email_hash TEXT, -- SHA256, sem PII
|
|
16
|
+
event_name TEXT,
|
|
17
|
+
event_id TEXT,
|
|
18
|
+
|
|
19
|
+
-- Score e decisão
|
|
20
|
+
fraud_score INTEGER NOT NULL, -- 0-100
|
|
21
|
+
action_taken TEXT NOT NULL, -- 'allowed', 'flagged', 'dropped'
|
|
22
|
+
reasons TEXT NOT NULL, -- JSON array: ["ip_velocity_high", "datacenter_ip", ...]
|
|
23
|
+
|
|
24
|
+
-- Contexto
|
|
25
|
+
ip_country TEXT,
|
|
26
|
+
ip_asn TEXT,
|
|
27
|
+
user_agent TEXT,
|
|
28
|
+
bot_score INTEGER,
|
|
29
|
+
velocity_1h INTEGER, -- Eventos deste IP na última 1h
|
|
30
|
+
velocity_1m INTEGER, -- Eventos deste IP no último 1min
|
|
31
|
+
|
|
32
|
+
-- Resultado (preenchido depois se lead converter)
|
|
33
|
+
was_real_user INTEGER -- 1 = comprou depois (falso positivo), 0 = fraude confirmada
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
-- TABELA: Alertas Agregados (quando IP/fingerprint atinge threshold repetidamente)
|
|
37
|
+
CREATE TABLE IF NOT EXISTS fraud_alerts (
|
|
38
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
39
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
40
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
41
|
+
|
|
42
|
+
alert_type TEXT NOT NULL, -- 'ip_attack', 'fingerprint_abuse', 'bot_network'
|
|
43
|
+
entity_type TEXT NOT NULL, -- 'ip', 'fingerprint', 'asn'
|
|
44
|
+
entity_value TEXT NOT NULL, -- O IP, fingerprint ou ASN em questão
|
|
45
|
+
|
|
46
|
+
-- Métricas do ataque
|
|
47
|
+
events_total INTEGER NOT NULL DEFAULT 0,
|
|
48
|
+
events_dropped INTEGER NOT NULL DEFAULT 0,
|
|
49
|
+
peak_score INTEGER NOT NULL DEFAULT 0,
|
|
50
|
+
first_seen TEXT NOT NULL DEFAULT (datetime('now')),
|
|
51
|
+
last_seen TEXT NOT NULL DEFAULT (datetime('now')),
|
|
52
|
+
|
|
53
|
+
-- Status
|
|
54
|
+
is_blocked INTEGER NOT NULL DEFAULT 0, -- 1 = está no KV blocklist
|
|
55
|
+
blocked_at TEXT,
|
|
56
|
+
block_expires TEXT, -- NULL = permanente
|
|
57
|
+
resolved_at TEXT,
|
|
58
|
+
resolved_by TEXT, -- 'auto', 'manual'
|
|
59
|
+
|
|
60
|
+
-- Contexto
|
|
61
|
+
top_reasons TEXT, -- JSON: razões mais comuns
|
|
62
|
+
sample_ips TEXT -- JSON: amostra de IPs relacionados (para redes de bots)
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
-- Índices
|
|
66
|
+
CREATE INDEX IF NOT EXISTS idx_fraud_signals_ip ON fraud_signals(ip_address);
|
|
67
|
+
CREATE INDEX IF NOT EXISTS idx_fraud_signals_fp ON fraud_signals(fingerprint);
|
|
68
|
+
CREATE INDEX IF NOT EXISTS idx_fraud_signals_score ON fraud_signals(fraud_score);
|
|
69
|
+
CREATE INDEX IF NOT EXISTS idx_fraud_signals_action ON fraud_signals(action_taken);
|
|
70
|
+
CREATE INDEX IF NOT EXISTS idx_fraud_signals_date ON fraud_signals(detected_at);
|
|
71
|
+
CREATE INDEX IF NOT EXISTS idx_fraud_alerts_entity ON fraud_alerts(entity_type, entity_value);
|
|
72
|
+
CREATE INDEX IF NOT EXISTS idx_fraud_alerts_blocked ON fraud_alerts(is_blocked);
|
|
73
|
+
CREATE INDEX IF NOT EXISTS idx_fraud_alerts_date ON fraud_alerts(created_at);
|
|
74
|
+
|
|
75
|
+
-- VIEW: Dashboard de fraude (últimas 24h)
|
|
76
|
+
CREATE VIEW IF NOT EXISTS v_fraud_dashboard AS
|
|
77
|
+
SELECT
|
|
78
|
+
COUNT(*) AS total_events_checked,
|
|
79
|
+
SUM(CASE WHEN action_taken = 'dropped' THEN 1 ELSE 0 END) AS events_dropped,
|
|
80
|
+
SUM(CASE WHEN action_taken = 'flagged' THEN 1 ELSE 0 END) AS events_flagged,
|
|
81
|
+
SUM(CASE WHEN action_taken = 'allowed' THEN 1 ELSE 0 END) AS events_allowed,
|
|
82
|
+
ROUND(
|
|
83
|
+
CAST(SUM(CASE WHEN action_taken = 'dropped' THEN 1 ELSE 0 END) AS REAL) /
|
|
84
|
+
NULLIF(COUNT(*), 0) * 100
|
|
85
|
+
, 2) AS fraud_rate_pct,
|
|
86
|
+
AVG(fraud_score) AS avg_fraud_score,
|
|
87
|
+
MAX(fraud_score) AS peak_fraud_score,
|
|
88
|
+
COUNT(DISTINCT ip_address) AS unique_ips_flagged
|
|
89
|
+
FROM fraud_signals
|
|
90
|
+
WHERE detected_at >= datetime('now', '-24 hours');
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
-- CDP Edge — Composite Indexes para Performance
|
|
2
|
+
-- Executar após todos os outros schemas:
|
|
3
|
+
-- wrangler d1 execute cdp-edge-db --file=schema-indexes.sql --remote
|
|
4
|
+
--
|
|
5
|
+
-- Todos os índices usam IF NOT EXISTS — idempotente, seguro para re-executar.
|
|
6
|
+
|
|
7
|
+
-- ── leads: queries mais comuns ────────────────────────────────────────────────
|
|
8
|
+
|
|
9
|
+
-- Deduplicação por email + janela temporal (upsertProfile, saveLead)
|
|
10
|
+
CREATE INDEX IF NOT EXISTS idx_leads_email_created
|
|
11
|
+
ON leads(email, created_at DESC);
|
|
12
|
+
|
|
13
|
+
-- Relatórios por plataforma + período (Intelligence Agent, Dashboard)
|
|
14
|
+
CREATE INDEX IF NOT EXISTS idx_leads_platform_created
|
|
15
|
+
ON leads(platform, created_at DESC);
|
|
16
|
+
|
|
17
|
+
-- Lookup de conversão por evento + período (auditErrorRates, generateDailyReport)
|
|
18
|
+
CREATE INDEX IF NOT EXISTS idx_leads_event_created
|
|
19
|
+
ON leads(event_name, created_at DESC);
|
|
20
|
+
|
|
21
|
+
-- Identity resolution: user_id + evento para evitar duplicatas
|
|
22
|
+
CREATE INDEX IF NOT EXISTS idx_leads_userid_event
|
|
23
|
+
ON leads(user_id, event_name);
|
|
24
|
+
|
|
25
|
+
-- Exportação Customer Match: event_name + email filtrado por data
|
|
26
|
+
CREATE INDEX IF NOT EXISTS idx_leads_event_email
|
|
27
|
+
ON leads(event_name, email);
|
|
28
|
+
|
|
29
|
+
-- CRM Dashboard: ordenação por status + criação
|
|
30
|
+
CREATE INDEX IF NOT EXISTS idx_leads_crm_created
|
|
31
|
+
ON leads(crm_status, created_at DESC);
|
|
32
|
+
|
|
33
|
+
-- ── user_profiles: enrichment e Advanced Matching ────────────────────────────
|
|
34
|
+
|
|
35
|
+
-- Busca por LTV class + atualização (Bidding ML consome isso)
|
|
36
|
+
CREATE INDEX IF NOT EXISTS idx_profiles_ltv_updated
|
|
37
|
+
ON user_profiles(predicted_ltv_class, updated_at DESC);
|
|
38
|
+
|
|
39
|
+
-- Score + cohort para segmentação ML (handleSegmentationCluster)
|
|
40
|
+
CREATE INDEX IF NOT EXISTS idx_profiles_score_cohort
|
|
41
|
+
ON user_profiles(score DESC, cohort_label);
|
|
42
|
+
|
|
43
|
+
-- Lookup email + updated_at (resolveDeviceGraph, getProfileByEmail)
|
|
44
|
+
CREATE INDEX IF NOT EXISTS idx_profiles_email_updated
|
|
45
|
+
ON user_profiles(email, updated_at DESC);
|
|
46
|
+
|
|
47
|
+
-- ── fraud_signals: dashboard e alertas ───────────────────────────────────────
|
|
48
|
+
|
|
49
|
+
-- handleFraudAlerts: filtra por ip + período (coluna: detected_at)
|
|
50
|
+
CREATE INDEX IF NOT EXISTS idx_fraud_ip_detected
|
|
51
|
+
ON fraud_signals(ip_address, detected_at DESC);
|
|
52
|
+
|
|
53
|
+
-- handleFraudStats: fraud_score >= threshold ordenado por data
|
|
54
|
+
CREATE INDEX IF NOT EXISTS idx_fraud_score_detected
|
|
55
|
+
ON fraud_signals(fraud_score DESC, detected_at DESC);
|
|
56
|
+
|
|
57
|
+
-- ── ltv_ab_assignments: resultados de A/B test ───────────────────────────────
|
|
58
|
+
|
|
59
|
+
-- handleLtvAbTestResults: test_id + predicted_class para análise
|
|
60
|
+
CREATE INDEX IF NOT EXISTS idx_ab_testid_class
|
|
61
|
+
ON ltv_ab_assignments(test_id, predicted_class);
|
|
62
|
+
|
|
63
|
+
-- ── ml_segment_members: join com leads para bidding ─────────────────────────
|
|
64
|
+
|
|
65
|
+
-- handleBiddingRecommend: segment_id lookup (coluna: assigned_at)
|
|
66
|
+
CREATE INDEX IF NOT EXISTS idx_seg_members_segid
|
|
67
|
+
ON ml_segment_members(cluster_id, assigned_at DESC);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
-- CDP Edge — Schema LTV Feedback Loop
|
|
2
|
+
-- Fecha o ciclo preditivo: Purchase real → corrige predicted_ltv_value
|
|
3
|
+
-- Execução: wrangler d1 execute cdp-edge-db --file=schema-ltv-feedback.sql --remote
|
|
4
|
+
--
|
|
5
|
+
-- Idempotência: ALTER TABLE não suporta IF NOT EXISTS no SQLite.
|
|
6
|
+
-- Se a coluna já existir, o comando gera erro mas não afeta dados existentes.
|
|
7
|
+
-- Seguro executar mais de uma vez.
|
|
8
|
+
|
|
9
|
+
ALTER TABLE user_profiles ADD COLUMN real_ltv_value REAL;
|
|
10
|
+
ALTER TABLE user_profiles ADD COLUMN ltv_accuracy REAL; -- 1 - |pred-real|/real (0–1, maior = melhor)
|
|
11
|
+
ALTER TABLE user_profiles ADD COLUMN ltv_feedback_at TEXT; -- timestamp do último feedback
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
-- CDP Edge — Schema Quiz Sessions (Fase 6 v2)
|
|
2
|
+
-- Análise Dimensional Automática por Workers AI
|
|
3
|
+
-- Executar: wrangler d1 execute cdp-edge-db --file=schema-quiz.sql --remote
|
|
4
|
+
|
|
5
|
+
CREATE TABLE IF NOT EXISTS quiz_sessions (
|
|
6
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
7
|
+
user_id TEXT, -- _cdp_uid (FK lógica → user_profiles)
|
|
8
|
+
quiz_name TEXT, -- nome do quiz (ex: "Diagnóstico Imóvel")
|
|
9
|
+
answers_json TEXT NOT NULL, -- JSON: [{question, answer, step}]
|
|
10
|
+
qualification TEXT NOT NULL, -- comprador | interessado | curioso | perdido
|
|
11
|
+
intent_score REAL NOT NULL, -- 0.0–1.0 (propagado ao pipeline CDP)
|
|
12
|
+
weighted_score REAL NOT NULL, -- score ponderado bruto Σ(score×weight)/Σ(weight)
|
|
13
|
+
confidence REAL NOT NULL DEFAULT 0.7,
|
|
14
|
+
reason TEXT, -- frase explicativa em português (audit)
|
|
15
|
+
dominant_dimension TEXT, -- dimensão com maior impacto: budget|urgency|etc.
|
|
16
|
+
dimensions_json TEXT, -- JSON: [{step, dimension, score, weight, signal}]
|
|
17
|
+
source TEXT DEFAULT 'ai', -- ai | heuristic
|
|
18
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
CREATE INDEX IF NOT EXISTS idx_quiz_user_id ON quiz_sessions(user_id);
|
|
22
|
+
CREATE INDEX IF NOT EXISTS idx_quiz_qualification ON quiz_sessions(qualification);
|
|
23
|
+
CREATE INDEX IF NOT EXISTS idx_quiz_created_at ON quiz_sessions(created_at);
|
|
24
|
+
CREATE INDEX IF NOT EXISTS idx_quiz_dominant_dim ON quiz_sessions(dominant_dimension);
|
|
25
|
+
|
|
26
|
+
-- VIEW: distribuição de qualificações por quiz + score médio
|
|
27
|
+
CREATE VIEW IF NOT EXISTS v_quiz_qualification_summary AS
|
|
28
|
+
SELECT
|
|
29
|
+
quiz_name,
|
|
30
|
+
qualification,
|
|
31
|
+
COUNT(*) AS total,
|
|
32
|
+
ROUND(AVG(intent_score) * 100, 1) AS avg_intent_pct,
|
|
33
|
+
ROUND(AVG(weighted_score) * 100, 1) AS avg_weighted_pct,
|
|
34
|
+
ROUND(AVG(confidence) * 100, 1) AS avg_confidence_pct,
|
|
35
|
+
COUNT(CASE WHEN source = 'ai' THEN 1 END) AS ai_scored,
|
|
36
|
+
COUNT(CASE WHEN source = 'heuristic' THEN 1 END) AS heuristic_scored
|
|
37
|
+
FROM quiz_sessions
|
|
38
|
+
GROUP BY quiz_name, qualification
|
|
39
|
+
ORDER BY quiz_name, avg_intent_pct DESC;
|
|
40
|
+
|
|
41
|
+
-- VIEW: qual dimensão mais penaliza/beneficia cada quiz
|
|
42
|
+
CREATE VIEW IF NOT EXISTS v_quiz_dimension_impact AS
|
|
43
|
+
SELECT
|
|
44
|
+
quiz_name,
|
|
45
|
+
dominant_dimension,
|
|
46
|
+
COUNT(*) AS total_sessions,
|
|
47
|
+
ROUND(AVG(weighted_score) * 100, 1) AS avg_weighted_pct,
|
|
48
|
+
qualification
|
|
49
|
+
FROM quiz_sessions
|
|
50
|
+
WHERE dominant_dimension IS NOT NULL
|
|
51
|
+
GROUP BY quiz_name, dominant_dimension, qualification
|
|
52
|
+
ORDER BY quiz_name, total_sessions DESC;
|