[2ff88f42] feat(GTM-Engine): Implement Dual Opener Strategy & Harden Analysis
Completed the GTM engine setup:\n\n- Implemented 'Dual Opener' generation (Primary/Secondary) in ClassificationService.\n- Migrated DB to support two opener fields.\n- Updated API and Frontend to handle and display both openers.\n- Fixed bug creating duplicate website_scrape entries.\n- Hardened metric extraction by improving the LLM prompt and adding content length checks.
This commit is contained in:
@@ -57,6 +57,10 @@ type CompanyDetail = {
|
||||
// Industry Strategy (V2)
|
||||
industry_details?: IndustryDetails
|
||||
|
||||
// Marketing AI (V3)
|
||||
ai_opener: string | null
|
||||
ai_opener_secondary: string | null
|
||||
|
||||
// NEU v0.7.0: Quantitative Metrics
|
||||
calculated_metric_name: string | null
|
||||
calculated_metric_value: number | null
|
||||
@@ -453,6 +457,43 @@ export function Inspector({ companyId, initialContactId, onClose, apiBase }: Ins
|
||||
)
|
||||
}
|
||||
|
||||
// Marketing AI Card Renderer
|
||||
const renderMarketingCard = () => {
|
||||
if (!data?.ai_opener && !data?.ai_opener_secondary) return null;
|
||||
|
||||
return (
|
||||
<div className="bg-orange-50 dark:bg-orange-900/10 rounded-xl p-5 border border-orange-100 dark:border-orange-900/50 mb-6">
|
||||
<h3 className="text-sm font-semibold text-orange-700 dark:text-orange-300 uppercase tracking-wider mb-3 flex items-center gap-2">
|
||||
<Bot className="h-4 w-4" /> Marketing AI (Openers)
|
||||
</h3>
|
||||
|
||||
<div className="space-y-4">
|
||||
{data.ai_opener && (
|
||||
<div className="p-3 bg-white dark:bg-slate-900 rounded border border-orange-200 dark:border-orange-800">
|
||||
<div className="flex justify-between items-center mb-1">
|
||||
<div className="text-[10px] text-orange-600 dark:text-orange-400 uppercase font-bold tracking-tight">Primary: Infrastructure/Cleaning</div>
|
||||
</div>
|
||||
<div className="text-sm text-slate-700 dark:text-slate-200 leading-relaxed italic">"{data.ai_opener}"</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{data.ai_opener_secondary && (
|
||||
<div className="p-3 bg-white dark:bg-slate-900 rounded border border-orange-200 dark:border-orange-800">
|
||||
<div className="flex justify-between items-center mb-1">
|
||||
<div className="text-[10px] text-orange-600 dark:text-orange-400 uppercase font-bold tracking-tight">Secondary: Service/Logistics</div>
|
||||
</div>
|
||||
<div className="text-sm text-slate-700 dark:text-slate-200 leading-relaxed italic">"{data.ai_opener_secondary}"</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<p className="text-[10px] text-slate-500 text-center">
|
||||
These sentences are statically pre-calculated for the "First Sentence Matching" strategy.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// CRM Comparison and Data Quality Renderer
|
||||
const renderDataQualityCard = () => {
|
||||
if (!data) return null;
|
||||
@@ -754,6 +795,7 @@ export function Inspector({ companyId, initialContactId, onClose, apiBase }: Ins
|
||||
|
||||
{renderDataQualityCard()}
|
||||
{renderStrategyCard()}
|
||||
{renderMarketingCard()}
|
||||
|
||||
<div className="bg-slate-50 dark:bg-slate-950 rounded-lg p-4 border border-slate-200 dark:border-slate-800 flex flex-col gap-2">
|
||||
<div className="flex items-center justify-between mb-1">
|
||||
|
||||
Reference in New Issue
Block a user