feat: full-service agency pitch — outreach email + subject, richer Gemini brief
- Prompt now describes complete agency capabilities (everything web-related) - Concrete pitch examples with business name + specific problem references - New mandatory output fields: outreach_email (3-4 sentence ready-to-send ES) and email_subject (specific subject line) - HOT/WARM/COLD scoring guide based on site deficiency count - Modal: pitch box replaced with full outreach email + subject + Copy button - max_output_tokens raised to 6000 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -141,31 +141,57 @@ Profiles found on site: {social_str}
|
||||
=== WEB SEARCH RESULTS (use to find contacts, verify business identity) ===
|
||||
{(search_results or "No results.")[:600]}
|
||||
|
||||
=== INSTRUCTIONS ===
|
||||
The client sells: web redesign, SEO, hosting migration, SSL renewal,
|
||||
security audits, GDPR compliance, accessibility fixes, Google Ads,
|
||||
maintenance contracts, AI tools for SMEs, GMB setup, social media management.
|
||||
=== WHO WE ARE ===
|
||||
We are a full-service digital agency. We handle EVERYTHING web-related for SMEs:
|
||||
new website builds, redesigns, landing pages, e-commerce, CMS migrations, speed
|
||||
optimisation, mobile responsiveness, SSL/security, SEO (on-page + technical +
|
||||
local), Google Ads, Google My Business setup & optimisation, social media
|
||||
management (Instagram, Facebook, LinkedIn, TikTok), GDPR compliance, cookie
|
||||
banners, accessibility fixes, hosting migrations, email setup, maintenance
|
||||
contracts, and AI-powered tools. No job is too small or too large.
|
||||
|
||||
RULES — you MUST follow all of these:
|
||||
1. A placeholder / minimal / blank site (few words, no images, no CMS) is one of
|
||||
the BEST leads — they need a complete website build + all digital services.
|
||||
Score it lead_quality=HOT or WARM and write an enthusiastic pitch.
|
||||
2. pitch_angle is MANDATORY. Never leave it empty. Write 1 punchy Spanish sentence
|
||||
tailored to the business type. Even "Hola, su web necesita una renovación
|
||||
completa — podemos tenerla lista en 2 semanas." is better than nothing.
|
||||
3. services_needed must list at LEAST 2 services. For a blank/placeholder site
|
||||
always include "diseño web" and "posicionamiento SEO".
|
||||
4. Use the WEB SEARCH RESULTS to find the real phone/email — put the best one
|
||||
in best_contact_value.
|
||||
5. Use copyright_year + Last-Modified to estimate site_last_updated.
|
||||
6. Keep every string value SHORT (≤ 15 words). Arrays: max 4 items.
|
||||
This keeps the JSON small and avoids truncation.
|
||||
=== ASSESSMENT RULES ===
|
||||
Look at EVERY aspect of the site — quality, age, CMS, performance, SEO, GDPR,
|
||||
social presence, GMB, contacts, hosting — and identify ALL the problems AND
|
||||
opportunities. Then build the pitch around the most compelling angle for THIS
|
||||
specific business.
|
||||
|
||||
Lead scoring guide:
|
||||
• HOT — blank/placeholder site, or ≥3 serious issues (expired SSL, no SEO,
|
||||
no mobile, lorem ipsum, non-EU hosting, no GDPR, no social, site >3 yrs old)
|
||||
• WARM — functional but clearly outdated or missing 1-2 key services
|
||||
• COLD — modern, well-maintained site with few obvious gaps
|
||||
|
||||
MANDATORY for EVERY assessment — no exceptions:
|
||||
1. pitch_angle: A single, compelling cold-outreach sentence in Spanish, personalised
|
||||
to this specific business name/type and its biggest weakness. Reference the actual
|
||||
problem. Examples of good pitches:
|
||||
- "Hola Salom Manacor, su web lleva sin actualizarse desde 2019 — en 3 semanas
|
||||
le entregamos una nueva web con ficha en Google, redes sociales y posicionamiento
|
||||
incluidos."
|
||||
- "Detectamos que la web de [Negocio] no aparece en Google Maps ni tiene perfil
|
||||
en Instagram — podemos solucionarlo esta semana."
|
||||
- "Su certificado SSL vence en 12 días y su web no tiene aviso de cookies legal —
|
||||
evite multas y pérdida de visitas con nuestro plan de mantenimiento."
|
||||
2. outreach_email: A 3-4 sentence ready-to-send email in Spanish. First sentence
|
||||
names the business and the most urgent problem. Second sentence explains the
|
||||
impact (losing clients, Google ranking, legal risk). Third sentence introduces us
|
||||
as the solution. Close with a call to action (llamada de 15 min, presupuesto
|
||||
gratuito). Sign off: "Un saludo, [Agencia Digital]".
|
||||
3. email_subject: A short, specific Spanish email subject line referencing the
|
||||
business name and main issue (e.g. "Web de Salom Manacor — propuesta de mejora").
|
||||
4. services_needed: At least 2 specific services from our catalogue.
|
||||
5. Use WEB SEARCH RESULTS to find real phone/email for best_contact_value.
|
||||
6. Use copyright_year + Last-Modified to estimate site_last_updated.
|
||||
7. Keep all string values concise (≤ 20 words each). Arrays: max 4 items.
|
||||
|
||||
Respond ONLY with valid JSON, no markdown fences, no text outside the JSON:
|
||||
{{
|
||||
"lead_quality": "HOT|WARM|COLD",
|
||||
"lead_reasoning": "1-2 sentences why",
|
||||
"pitch_angle": "1 punchy cold-outreach sentence in Spanish — NEVER empty",
|
||||
"lead_reasoning": "1-2 sentences",
|
||||
"pitch_angle": "1 punchy sentence in Spanish referencing the specific business problem",
|
||||
"outreach_email": "ready-to-send 3-4 sentence email in Spanish",
|
||||
"email_subject": "specific Spanish subject line",
|
||||
"services_needed": ["service1","service2"],
|
||||
"best_contact_channel": "email|phone|whatsapp|social|web_form|unknown",
|
||||
"best_contact_value": "real email/phone from page or search results",
|
||||
@@ -239,7 +265,7 @@ async def assess_domain(analysis: dict) -> dict:
|
||||
"top_p": 0.9,
|
||||
"temperature": 0.2,
|
||||
"thinking_level": "low",
|
||||
"max_output_tokens": 4096,
|
||||
"max_output_tokens": 6000,
|
||||
}
|
||||
}
|
||||
try:
|
||||
|
||||
@@ -237,10 +237,16 @@ tr:hover td{background:rgba(255,255,255,.025)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Pitch -->
|
||||
<!-- Outreach email -->
|
||||
<div style="background:#6c63ff15;border:1px solid #6c63ff33;border-radius:6px;padding:10px;margin:8px 0">
|
||||
<div style="font-size:10px;color:var(--muted);text-transform:uppercase;margin-bottom:4px">Cold Pitch (ES)</div>
|
||||
<div style="font-size:13px;font-style:italic;color:var(--accent2)" x-text="modal.ai.pitch_angle||'—'"></div>
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:6px">
|
||||
<div style="font-size:10px;color:var(--muted);text-transform:uppercase">Outreach Email (ES)</div>
|
||||
<button class="btn bg sm" @click="copyEmail()" style="font-size:10px;padding:2px 8px">📋 Copy</button>
|
||||
</div>
|
||||
<div x-show="modal.ai.email_subject" style="font-size:11px;color:var(--muted);margin-bottom:4px">
|
||||
<b>Subject:</b> <span x-text="modal.ai.email_subject"></span>
|
||||
</div>
|
||||
<div style="font-size:12px;font-style:italic;color:var(--accent2);line-height:1.5;white-space:pre-wrap" x-text="modal.ai.outreach_email || modal.ai.pitch_angle || '—'"></div>
|
||||
</div>
|
||||
|
||||
<!-- Accessibility issues -->
|
||||
@@ -657,6 +663,15 @@ function app() {
|
||||
},
|
||||
|
||||
async restartAiWorker() { await fetch('/api/ai/worker/restart',{method:'POST'}); this.notify('AI worker restarted','info'); await this.loadAiStatus(); },
|
||||
copyEmail() {
|
||||
const subj = this.modal.ai.email_subject ? `Subject: ${this.modal.ai.email_subject}\n\n` : '';
|
||||
const body = this.modal.ai.outreach_email || this.modal.ai.pitch_angle || '';
|
||||
navigator.clipboard.writeText(subj + body).then(
|
||||
() => this.notify('Email copied to clipboard', 'success'),
|
||||
() => this.notify('Copy failed — select text manually', 'error'),
|
||||
);
|
||||
},
|
||||
|
||||
async resetAiStuck() { const r=await fetch('/api/ai/reset',{method:'POST'}); const d=await r.json(); this.notify(`Reset ${d.reset} stuck jobs → pending`,'success'); await this.loadAiStatus(); },
|
||||
async startEnrich() { await fetch('/api/enrich/resume',{method:'POST'}); this.notify('Worker started','success'); await this.loadQueue(); },
|
||||
async pauseEnrich() { await fetch('/api/enrich/pause',{method:'POST'}); this.notify('Worker paused','success'); await this.loadQueue(); },
|
||||
|
||||
Reference in New Issue
Block a user