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) ===
|
=== WEB SEARCH RESULTS (use to find contacts, verify business identity) ===
|
||||||
{(search_results or "No results.")[:600]}
|
{(search_results or "No results.")[:600]}
|
||||||
|
|
||||||
=== INSTRUCTIONS ===
|
=== WHO WE ARE ===
|
||||||
The client sells: web redesign, SEO, hosting migration, SSL renewal,
|
We are a full-service digital agency. We handle EVERYTHING web-related for SMEs:
|
||||||
security audits, GDPR compliance, accessibility fixes, Google Ads,
|
new website builds, redesigns, landing pages, e-commerce, CMS migrations, speed
|
||||||
maintenance contracts, AI tools for SMEs, GMB setup, social media management.
|
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:
|
=== ASSESSMENT RULES ===
|
||||||
1. A placeholder / minimal / blank site (few words, no images, no CMS) is one of
|
Look at EVERY aspect of the site — quality, age, CMS, performance, SEO, GDPR,
|
||||||
the BEST leads — they need a complete website build + all digital services.
|
social presence, GMB, contacts, hosting — and identify ALL the problems AND
|
||||||
Score it lead_quality=HOT or WARM and write an enthusiastic pitch.
|
opportunities. Then build the pitch around the most compelling angle for THIS
|
||||||
2. pitch_angle is MANDATORY. Never leave it empty. Write 1 punchy Spanish sentence
|
specific business.
|
||||||
tailored to the business type. Even "Hola, su web necesita una renovación
|
|
||||||
completa — podemos tenerla lista en 2 semanas." is better than nothing.
|
Lead scoring guide:
|
||||||
3. services_needed must list at LEAST 2 services. For a blank/placeholder site
|
• HOT — blank/placeholder site, or ≥3 serious issues (expired SSL, no SEO,
|
||||||
always include "diseño web" and "posicionamiento SEO".
|
no mobile, lorem ipsum, non-EU hosting, no GDPR, no social, site >3 yrs old)
|
||||||
4. Use the WEB SEARCH RESULTS to find the real phone/email — put the best one
|
• WARM — functional but clearly outdated or missing 1-2 key services
|
||||||
in best_contact_value.
|
• COLD — modern, well-maintained site with few obvious gaps
|
||||||
5. Use copyright_year + Last-Modified to estimate site_last_updated.
|
|
||||||
6. Keep every string value SHORT (≤ 15 words). Arrays: max 4 items.
|
MANDATORY for EVERY assessment — no exceptions:
|
||||||
This keeps the JSON small and avoids truncation.
|
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:
|
Respond ONLY with valid JSON, no markdown fences, no text outside the JSON:
|
||||||
{{
|
{{
|
||||||
"lead_quality": "HOT|WARM|COLD",
|
"lead_quality": "HOT|WARM|COLD",
|
||||||
"lead_reasoning": "1-2 sentences why",
|
"lead_reasoning": "1-2 sentences",
|
||||||
"pitch_angle": "1 punchy cold-outreach sentence in Spanish — NEVER empty",
|
"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"],
|
"services_needed": ["service1","service2"],
|
||||||
"best_contact_channel": "email|phone|whatsapp|social|web_form|unknown",
|
"best_contact_channel": "email|phone|whatsapp|social|web_form|unknown",
|
||||||
"best_contact_value": "real email/phone from page or search results",
|
"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,
|
"top_p": 0.9,
|
||||||
"temperature": 0.2,
|
"temperature": 0.2,
|
||||||
"thinking_level": "low",
|
"thinking_level": "low",
|
||||||
"max_output_tokens": 4096,
|
"max_output_tokens": 6000,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -237,10 +237,16 @@ tr:hover td{background:rgba(255,255,255,.025)}
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Pitch -->
|
<!-- Outreach email -->
|
||||||
<div style="background:#6c63ff15;border:1px solid #6c63ff33;border-radius:6px;padding:10px;margin:8px 0">
|
<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="display:flex;justify-content:space-between;align-items:center;margin-bottom:6px">
|
||||||
<div style="font-size:13px;font-style:italic;color:var(--accent2)" x-text="modal.ai.pitch_angle||'—'"></div>
|
<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>
|
</div>
|
||||||
|
|
||||||
<!-- Accessibility issues -->
|
<!-- 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(); },
|
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 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 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(); },
|
async pauseEnrich() { await fetch('/api/enrich/pause',{method:'POST'}); this.notify('Worker paused','success'); await this.loadQueue(); },
|
||||||
|
|||||||
Reference in New Issue
Block a user