Configura tu API key
const PAGESPEED_KEY = 'AIzaSyD6dVPMqQPMxmOA9VxHkzExmLbN2YH_J6A'; let canal = 'WhatsApp'; let history = JSON.parse(localStorage.getItem('wpr_history') || '[]'); let lastChecks = []; let lastUrl = ''; let lastNombre = ''; let lastNegocio = '';
// Canal chips document.querySelectorAll('#canal-chips .chip').forEach(c => { c.addEventListener('click', () => { document.querySelectorAll('#canal-chips .chip').forEach(x => x.classList.remove('on')); c.classList.add('on'); canal = c.dataset.v; guardarCampos(); }); });
function checkApiKey() { const key = document.getElementById('api-key').value.trim(); const dot = document.getElementById('api-dot'); const status = document.getElementById('api-status'); const warn = document.getElementById('api-warn'); if (key.startsWith('sk-ant')) { dot.style.background = 'var(--green)'; status.textContent = 'API conectada'; warn.style.display = 'none'; } else { dot.style.background = 'var(--amber)'; status.textContent = 'API key requerida'; warn.style.display = 'block'; } }
function toast(msg) { const t = document.getElementById('toast'); t.textContent = msg; t.classList.add('show'); setTimeout(() => t.classList.remove('show'), 2500); }
function setStepState(steps, idx, state) { const icons = { done: '✓', running: '↻', pending: '·' }; const el = document.getElementById('step-' + idx); if (!el) return; el.querySelector('.step-icon').className = 'step-icon ' + state; el.querySelector('.step-icon').textContent = icons[state]; el.querySelector('.step-label').className = 'step-label' + (state === 'pending' ? ' pending' : ''); }
const STEPS = [ 'Consultando PageSpeed API (mobile)...', 'Analizando HTML y metadatos...', 'Detectando Schema, og:image, teléfono...', 'Evaluando WooCommerce y seguridad...', 'Verificando indexación Google, sitemap y robots.txt...', 'Calculando paquete recomendado...', 'Generando mensaje con IA...' ];
async function iniciarAnalisis() { let url = document.getElementById('url-in').value.trim(); if (!url) { toast('Ingresa una URL para analizar'); return; } const apiKey = document.getElementById('api-key').value.trim(); if (!apiKey.startsWith('sk-ant')) { toast('Ingresa tu API key de Anthropic primero'); document.getElementById('api-warn').style.display='block'; return; } if (!url.startsWith('http')) url = 'https://' + url;
lastUrl = url; lastNombre = document.getElementById('nombre-in').value.trim() || 'el equipo'; lastNegocio = document.getElementById('negocio-in').value.trim() || new URL(url).hostname.replace('www.', '');
const btn = document.getElementById('scan-btn'); btn.disabled = true; btn.innerHTML = '
Analizando...'; document.getElementById('empty-state').style.display = 'none'; document.getElementById('results-area').style.display = 'none'; document.getElementById('seo-snapshot').style.display = 'none'; const pw = document.getElementById('prog-wrap'); pw.style.display = 'block'; document.getElementById('prog-url').textContent = '→ ' + url;
const stepsEl = document.getElementById('prog-steps'); stepsEl.innerHTML = STEPS.map((s, i) => `
`).join('');
const checks = []; let titleMatch, titleTag, titleOk, titleGeneric, metaMatch, metaDesc, metaOk; let hasSitemap = false, sitemapUrl = ''; let robotsTxt = '', robotsOk = false, robotsBlocking = false; let indexSignal = null;
// Step 0: PageSpeed setStepState(STEPS, 0, 'running'); let lcp = null, score = null; try { const ps = await fetch(`https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=${encodeURIComponent(url)}&strategy=mobile&key=${PAGESPEED_KEY}`); const psd = await ps.json(); score = Math.round((psd.lighthouseResult?.categories?.performance?.score || 0) * 100); const audits = psd.lighthouseResult?.audits; lcp = audits?.['largest-contentful-paint']?.displayValue || null; const fcp = audits?.['first-contentful-paint']?.displayValue || '—'; const cls = audits?.['cumulative-layout-shift']?.displayValue || '—'; const tbt = audits?.['total-blocking-time']?.displayValue || '—'; const lcpNum = parseFloat((lcp || '99').replace(/[^0-9.]/g, '')); checks.push({ key: 'lcp', title: 'Velocidad de carga mobile (LCP)', tag: 'tag-mobile', tagLabel: 'Mobile', status: lcpNum <= 2.5 ? 'ok' : lcpNum <= 4 ? 'warn' : 'err', detail: `LCP: ${lcp || 'No disponible'} · FCP: ${fcp} · CLS: ${cls} · TBT: ${tbt} · Score mobile: ${score}/100`, problema: lcpNum > 2.5 ? `el sitio carga en ${lcp} en mobile — Google penaliza sitios con LCP >2.5s y los usuarios abandonan` : null }); } catch (e) { checks.push({ key: 'lcp', title: 'Velocidad de carga mobile (LCP)', tag: 'tag-mobile', tagLabel: 'Mobile', status: 'skip', detail: 'No se pudo consultar PageSpeed. Verificar en pagespeed.web.dev manualmente.', problema: null }); } setStepState(STEPS, 0, 'done');
// Step 1-2: HTML analysis setStepState(STEPS, 1, 'running'); let body = ''; try { const r = await fetch(`https://api.allorigins.win/get?url=${encodeURIComponent(url)}`); const d = await r.json(); body = d.contents || ''; } catch (e) { body = ''; } setStepState(STEPS, 1, 'done');
setStepState(STEPS, 2, 'running');
// Schema const hasSchema = /application\/ld\+json|itemtype.*schema\.org/i.test(body); const schemaTypes = []; if (/LocalBusiness/i.test(body)) schemaTypes.push('LocalBusiness'); if (/Product[^s]/i.test(body)) schemaTypes.push('Product'); if (/FAQPage/i.test(body)) schemaTypes.push('FAQPage'); if (/Organization/i.test(body)) schemaTypes.push('Organization'); checks.push({ key: 'schema', title: 'Schema markup activo', tag: 'tag-seo', tagLabel: 'SEO', status: !hasSchema ? 'err' : schemaTypes.length >= 2 ? 'ok' : 'warn', detail: hasSchema ? `Schema detectado: ${schemaTypes.length > 0 ? schemaTypes.join(', ') : 'tipo no identificado'}. Validar en search.google.com/test/rich-results.` : 'No se detectó Schema markup (JSON-LD) en el sitio.', problema: !hasSchema ? 'no tiene Schema markup — sin rich snippets posibles en Google (Product, LocalBusiness, FAQ)' : schemaTypes.length < 2 ? `Schema limitado (${schemaTypes.join(', ') || 'básico'}) — faltan tipos clave para máxima visibilidad` : null }); // og:image const hasOg = /og:image/i.test(body); const ogUrl = (body.match(/og:image[^>]*content=["']([^"']+)/i) || body.match(/content=["']([^"']+)["'][^>]*og:image/i) || [])[1] || null; const genericOg = ogUrl && /logo|default|placeholder|icon/i.test(ogUrl); checks.push({ key: 'og', title: 'og:image configurada', tag: 'tag-seo', tagLabel: 'SEO', status: !hasOg ? 'err' : genericOg ? 'warn' : 'ok', detail: hasOg ? `og:image: ${ogUrl ? ogUrl.substring(0, 70) + '...' : 'URL detectada'}${genericOg ? ' (puede ser genérica)' : ''}` : 'No se detectó og:image — el sitio aparece sin imagen al compartir en redes sociales.', problema: !hasOg ? 'sin og:image configurada — aspecto sin imagen al compartir en WhatsApp, redes y correo' : genericOg ? 'la og:image parece ser el logo genérico, no una imagen atractiva del negocio' : null });
// Teléfono y WhatsApp const hasTel = /href=["']tel:/i.test(body); const hasWA = /wa\.me|api\.whatsapp|whatsapp\.com/i.test(body); checks.push({ key: 'tel', title: 'Teléfono y WhatsApp clickeables', tag: 'tag-mobile', tagLabel: 'Mobile', status: hasTel && hasWA ? 'ok' : hasTel || hasWA ? 'warn' : 'err', detail: `Teléfono (href=tel:): ${hasTel ? '✓ Detectado' : '✗ No encontrado'} · WhatsApp: ${hasWA ? '✓ Detectado' : '✗ No encontrado'}`, problema: !hasTel && !hasWA ? 'el teléfono y WhatsApp no son clickeables — desde mobile el usuario no puede contactar con un toque' : !hasTel ? 'el teléfono no tiene href=tel: — no es clickeable en mobile' : !hasWA ? 'no hay botón de WhatsApp visible en el sitio' : null }); setStepState(STEPS, 2, 'done');
// Step 3: WooCommerce + Seguridad setStepState(STEPS, 3, 'running');
const isWoo = /woocommerce|\/shop\/|\/tienda\//i.test(body); checks.push({ key: 'woo', title: 'WooCommerce y categorías SEO', tag: 'tag-woo', tagLabel: 'WooCommerce', status: isWoo ? 'warn' : 'skip', detail: isWoo ? 'WooCommerce detectado. Verificar manualmente: slugs de categoría limpios (/tienda/categoria/ vs /product-category/cat1/) y precios consistentes en listado vs producto.' : 'WooCommerce no detectado — puede ser un sitio de servicios o requiere acceso autenticado.', problema: isWoo ? 'las categorías de WooCommerce requieren verificación manual de estructura SEO (slugs y consistencia de precios)' : null });
const hasWPGen = /generator[^>]*WordPress|WordPress[^>]*generator/i.test(body); const wpV = (body.match(/WordPress\s*([\d.]+)/i) || [])[1] || ''; checks.push({ key: 'seg', title: 'Versión WordPress no expuesta', tag: 'tag-seg', tagLabel: 'Seguridad', status: hasWPGen ? 'err' : 'ok', detail: hasWPGen ? `WordPress ${wpV || 'versión'} visible en el código fuente — facilita ataques dirigidos.` : 'La versión de WordPress no es visible en el código fuente. Correcto.', problema: hasWPGen ? `la versión de WordPress (${wpV || 'expuesta'}) aparece en el código fuente, facilitando ataques automatizados` : null }); setStepState(STEPS, 3, 'done');
lastChecks = checks;
// Step 4: Indexación Google, sitemap, robots, title/meta setStepState(STEPS, 4, 'running');
// Title tag titleMatch = body.match(/
// Step 6: AI message setStepState(STEPS, 6, 'running'); const msgText = await generarMensajeIA(checks, url, lastNombre, lastNegocio, canal, apiKey); setStepState(STEPS, 6, 'done');
pw.style.display = 'none';
// Render stats document.getElementById('stats-row').innerHTML = `
`;
// Package banner const pb = document.getElementById('pkg-banner'); pb.className = 'pkg-banner ' + pkgClass; pb.innerHTML = ` Paquete recomendado: ${pkg} · ${errs.length} problema(s) grave(s) · ${warns.length} advertencia(s)`;
// SEO Visibility snapshot const titleChk = checks.find(c => c.key === 'title'); const sitemapChk = checks.find(c => c.key === 'sitemap'); const robotsChk = checks.find(c => c.key === 'robots'); const indexChk = checks.find(c => c.key === 'index');
const snapshotColor = { ok: 'var(--green)', warn: 'var(--amber)', err: 'var(--red)', skip: 'var(--muted)' }; const snapshotIcon = { ok: '✓', warn: '!', err: '✗', skip: '—' };
const titleTagDisplay = titleMatch ? `"${titleTag.substring(0,55)}${titleTag.length>55?'…':''}"` : 'No detectado'; const metaDisplay = metaDesc ? `"${metaDesc.substring(0,70)}…" (${metaDesc.length} car.)` : 'No detectada';
const snapshotHtml = `
`;
document.getElementById('seo-snapshot').innerHTML = snapshotHtml; document.getElementById('seo-snapshot').style.display = 'block';
// Checks list const iconMap = { ok: '✓', warn: '!', err: '✗', skip: '—' }; const iconCls = { ok: 'ci-ok', warn: 'ci-warn', err: 'ci-err', skip: 'ci-skip' }; const badgeCls = { ok: 'cb-ok', warn: 'cb-warn', err: 'cb-err', skip: 'cb-skip' }; const badgeLbl = { ok: 'OK', warn: 'Advertencia', err: 'Problema grave', skip: 'Manual' };
document.getElementById('checks-list').innerHTML = checks.map((c, i) => `
${badgeLbl[c.status]}
`).join('');
// Message document.getElementById('canal-badge').textContent = canal; document.getElementById('msg-body').textContent = msgText; const words = msgText.trim().split(/\s+/).length; document.getElementById('word-count').textContent = `${words} palabras · ${msgText.length} caracteres`;
document.getElementById('btn-email').style.display = canal === 'Email' ? 'flex' : 'none'; document.getElementById('btn-wa').style.display = canal === 'WhatsApp' ? 'flex' : 'none';
const ra = document.getElementById('results-area'); ra.style.display = 'flex';
// History const entry = { url, nombre: lastNombre, negocio: lastNegocio, canal, errCount: errs.length, warnCount: warns.length, okCount: oks.length, ts: new Date().toLocaleTimeString('es-CL', { hour: '2-digit', minute: '2-digit' }), msg: msgText, checks: lastChecks }; history.unshift(entry); if (history.length > 20) history.pop(); localStorage.setItem('wpr_history', JSON.stringify(history)); renderHistory();
btn.disabled = false; btn.innerHTML = ' Analizar y generar reporte'; }
async function generarMensajeIA(checks, url, nombre, negocio, canal, apiKey) { const canalInstr = { 'WhatsApp': 'máximo 100 palabras, tono directo y cercano, tuteo natural, sin asunto, sin saludos genéricos', 'Email': 'máximo 150 palabras, incluye al inicio "Asunto: [texto impactante]", tono profesional directo', 'LinkedIn': 'máximo 120 palabras, tono profesional, sin tuteo, sin asunto' }; const problemas = checks.filter(c => c.problema); const problemasTexto = problemas.length > 0 ? problemas.map(p => `- ${p.problema}`).join('\n') : '- el sitio parece sin errores graves, pero hay oportunidades de optimización SEO y conversión';
// ── Top 3 errores críticos para mensaje y PDF ── const top3 = checks .filter(c => c.status === 'err' || c.status === 'warn') .slice(0, 3); const top3Texto = top3.length > 0 ? top3.map((p, i) => `${i+1}. ${p.problema || p.title}: ${p.detail}`).join('\n') : '1. Velocidad crítica en mobile — clientes abandonan antes de ver precios\n2. Sin schema de negocio — Google no sabe qué ofreces\n3. Imágenes sin optimizar — pérdida directa de conversión'; window._lastTop3 = top3;
const prompt = `Eres un copywriter B2B experto en ventas de servicios WordPress para el mercado chileno. Escribes mensajes directos que suenan humanos. NUNCA uses "espero que estés bien", "me pongo en contacto" ni frases genéricas.
Escribe UN mensaje de prospección para: - Canal: ${canal} (${canalInstr[canal]}) - Contacto: ${nombre} - Negocio/sitio: ${negocio} (${url})
Detectamos estas 3 fugas de conversión en su sitio: ${top3Texto}
Estructura obligatoria: 1. Abre directo con una observación específica del sitio de ${negocio} — nada genérico 2. Nombra las 3 fugas en lenguaje de NEGOCIO (no técnico): qué dinero o clientes está perdiendo HOY. Ejemplo: no "LCP alto" sino "los clientes abandonan antes de ver sus precios" 3. Presenta WP Repair Pro en 2 líneas: auditoría + reparación WordPress con evidencia técnica. Caso real GlobalKlima.cl: 147 errores eliminados, de 16 a 43+ URLs indexadas, +22% conversión mobile 4. CTA de bajo compromiso: diagnóstico gratuito con informe técnico escrito adjunto
Entrega SOLO el mensaje listo para enviar. Sin explicaciones, sin comillas envolventes.`;
try { const resp = await fetch('https://api.anthropic.com/v1/messages', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': apiKey, 'anthropic-version': '2023-06-01', 'anthropic-dangerous-direct-browser-access': 'true' }, body: JSON.stringify({ model: 'claude-sonnet-4-20250514', max_tokens: 1000, messages: [{ role: 'user', content: prompt }] }) }); const d = await resp.json(); return d.content?.find(b => b.type === 'text')?.text || 'Error al generar el mensaje. Verifica tu API key.'; } catch (e) { return 'Error de conexión con la API de Claude. Verifica tu API key y conexión a internet.'; } }
async function regenerarMensaje() { if (!lastUrl) return; const apiKey = document.getElementById('api-key').value.trim(); const mb = document.getElementById('msg-body'); mb.textContent = 'Generando nuevo mensaje...'; const msg = await generarMensajeIA(lastChecks, lastUrl, lastNombre, lastNegocio, canal, apiKey); mb.textContent = msg; const words = msg.trim().split(/\s+/).length; document.getElementById('word-count').textContent = `${words} palabras · ${msg.length} caracteres`; toast('Mensaje regenerado'); }
function toggleCheck(i) { const el = document.getElementById('cb-' + i); el.classList.toggle('open'); }
function copiarMensaje() { const t = document.getElementById('msg-body').textContent; navigator.clipboard.writeText(t).then(() => toast('Mensaje copiado al portapapeles ✓')); }
function abrirCorreo() { const msg = document.getElementById('msg-body').textContent; const lines = msg.split('\n'); const subject = lines[0].replace(/^Asunto:\s*/i, '').trim(); const body = lines.slice(1).join('\n').trim(); window.location.href = `mailto:?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`; }
function abrirWhatsApp() { const msg = document.getElementById('msg-body').textContent; window.open(`https://wa.me/?text=${encodeURIComponent(msg)}`, '_blank'); }
function renderHistory() { const el = document.getElementById('history-list'); if (history.length === 0) { el.innerHTML = '
'; return; } el.innerHTML = history.slice(0, 8).map((h, i) => `
`).join(''); }
function cargarHistorial(i) { const h = history[i]; // Reload all form fields document.getElementById('url-in').value = h.url || ''; document.getElementById('nombre-in').value = h.nombre || ''; document.getElementById('negocio-in').value = h.negocio || ''; // Set canal chip document.querySelectorAll('#canal-chips .chip').forEach(c => { c.classList.toggle('on', c.dataset.v === h.canal); }); canal = h.canal || 'WhatsApp'; // Restore last vars lastUrl = h.url || ''; lastNombre = h.nombre || ''; lastNegocio = h.negocio || ''; lastChecks = h.checks || []; guardarCampos(); // Restore results if available if (h.msg) { document.getElementById('msg-body').textContent = h.msg; document.getElementById('canal-badge').textContent = h.canal; const words = h.msg.trim().split(/\s+/).length; document.getElementById('word-count').textContent = `${words} palabras`; document.getElementById('btn-email').style.display = h.canal === 'Email' ? 'flex' : 'none'; document.getElementById('btn-wa').style.display = h.canal === 'WhatsApp' ? 'flex' : 'none'; document.getElementById('results-area').style.display = 'flex'; document.getElementById('empty-state').style.display = 'none'; document.getElementById('seo-snapshot').style.display = 'none'; document.getElementById('checks-list').innerHTML = ''; document.getElementById('stats-row').innerHTML = ''; document.getElementById('pkg-banner').innerHTML = ''; } toast('Prospecto cargado: ' + (h.negocio || h.url)); }
function descargarPDF() { const url = lastUrl || '—'; const negocio = lastNegocio || '—'; const nombre = lastNombre || '—'; const msg = document.getElementById('msg-body').textContent || ''; const canalActual = document.getElementById('canal-badge').textContent || canal; const pkg = document.getElementById('pkg-banner').textContent.trim() || ''; const fecha = new Date().toLocaleDateString('es-CL', {day:'2-digit', month:'long', year:'numeric'}); const checks = lastChecks || []; const statusIcon = {ok:'✓', warn:'⚠', err:'✗', skip:'—'}; const statusLabel = {ok:'Sin problema', warn:'Advertencia', err:'Problema grave', skip:'Verificar manual'}; const statusColor = {ok:'#22c97a', warn:'#f0a030', err:'#ff4545', skip:'#7a7884'}; const errs = checks.filter(c=>c.status==='err').length; const warns = checks.filter(c=>c.status==='warn').length; const oks = checks.filter(c=>c.status==='ok').length;
const checksRows = checks.map(c => `
`).join('');
// ── Score WP Repair™ — calculado desde checks reales ── const scoreMap = { seo: ['schema','title','sitemap','robots','index','ogimage','woocommerce'], performance:['lcp'], conversion: ['phone','ogimage','woocommerce'], security: ['wp-version'] }; function calcScore(category) { const keys = scoreMap[category]; const relevant = checks.filter(c => keys.includes(c.key)); if (!relevant.length) return 5; const pts = relevant.reduce((acc, c) => { if (c.status === 'ok') return acc + 10; if (c.status === 'warn') return acc + 5; return acc; // err or skip = 0 }, 0); return Math.min(10, Math.max(1, Math.round(pts / relevant.length))); } const wpScore = { seo: calcScore('seo'), performance:calcScore('performance'), conversion: calcScore('conversion'), security: calcScore('security') }; const totalScore = Math.round((wpScore.seo + wpScore.performance + wpScore.conversion + wpScore.security) / 4);
function scoreColor(s) { if (s >= 8) return '#22c97a'; if (s >= 5) return '#f0a030'; return '#e74c3c'; } function scoreLabel(s) { if (s >= 8) return 'Saludable'; if (s >= 5) return 'En riesgo'; return 'Crítico'; } function scoreBar(s) { const pct = (s / 10) * 100; const col = scoreColor(s); return `
`; }
const scoreCardHtml = `
${scoreBar(s)}
`; }).join('')}
`;
// ── Compute top3 cards for PDF ── const _t3 = (window._lastTop3 && window._lastTop3.length > 0) ? window._lastTop3.slice(0,3) : [ {problema:'Velocidad crítica en mobile',detail:'Los usuarios abandonan antes de ver precios o productos'}, {problema:'Sin Schema de negocio local',detail:'Google no identifica qué ofrece el sitio'}, {problema:'Imágenes sin optimizar',detail:'Aumentan el tiempo de carga y reducen conversión'} ]; const top3Cards = _t3.map((e,i) => `
`).join('');
const reportHtml = `
${fecha}
WP Repair Pro Framework
|
Contacto
${nombre}
|
Negocio
${negocio}
|
|
URL analizada
${url}
|
|
|
${checks.length}
Revisados
|
${errs}
Problemas
|
${warns}
Advertencias
|
${oks}
Sin problema
|
${scoreCardHtml}
${top3Cards}
`;
// Create overlay in current page const overlay = document.createElement('div'); overlay.id = 'pdf-overlay'; overlay.style.cssText = 'position:fixed;inset:0;background:#fff;z-index:9999;overflow-y:auto;padding:40px 20px;';
const closeBtn = document.createElement('button'); closeBtn.innerHTML = '✕ Cerrar vista previa'; closeBtn.style.cssText = 'position:fixed;top:16px;right:16px;padding:8px 16px;background:#111;color:#fff;border:none;border-radius:100px;font-size:12px;cursor:pointer;z-index:10000;font-family:monospace;'; closeBtn.onclick = () => { overlay.remove(); };
const printBtn = document.createElement('button'); printBtn.innerHTML = '⬇ Guardar como PDF'; printBtn.style.cssText = 'position:fixed;top:16px;right:170px;padding:8px 16px;background:#3d6fff;color:#fff;border:none;border-radius:100px;font-size:12px;cursor:pointer;z-index:10000;font-family:monospace;'; printBtn.onclick = () => { window.print(); };
overlay.innerHTML = reportHtml; overlay.appendChild(closeBtn); overlay.appendChild(printBtn); document.body.appendChild(overlay); toast('Vista previa lista — haz clic en "Guardar como PDF"'); }
async function autodetectar() { let url = document.getElementById('url-in').value.trim(); if (!url) { toast('Ingresa una URL primero'); return; } if (!url.startsWith('http')) url = 'https://' + url; document.getElementById('url-in').value = url;
const btn = document.getElementById('btn-auto'); const status = document.getElementById('auto-status'); btn.disabled = true; btn.innerHTML = '
'; status.style.color = 'var(--muted)'; status.textContent = 'Leyendo sitio...';
try { const r = await fetch(`https://api.allorigins.win/get?url=${encodeURIComponent(url)}`); const d = await r.json(); const body = d.contents || '';
// Extract business name — priority: og:site_name > title > domain let negocio = ''; let telefono = ''; let email = ''; let desc = '';
// og:site_name const ogSite = body.match(/og:site_name[^>]*content=["']([^"']{1,80})["']/i) || body.match(/content=["']([^"']{1,80})["'][^>]*og:site_name/i); if (ogSite) negocio = ogSite[1].trim();
// og:title fallback if (!negocio) { const ogTitle = body.match(/og:title[^>]*content=["']([^"']{1,80})["']/i) || body.match(/content=["']([^"']{1,80})["'][^>]*og:title/i); if (ogTitle) negocio = ogTitle[1].replace(/\s*[|\-–—].*$/, '').trim(); }
//
// domain fallback if (!negocio) { negocio = new URL(url).hostname.replace('www.', '').split('.')[0]; negocio = negocio.charAt(0).toUpperCase() + negocio.slice(1); }
// Phone const telMatch = body.match(/href=["']tel:([+\d\s\-().]{6,20})["']/i); if (telMatch) telefono = telMatch[1].trim();
// Email const emailMatch = body.match(/href=["']mailto:([^"'?&\s]{4,60})["']/i); if (emailMatch) { const em = emailMatch[1]; if (!em.includes('ejemplo') && !em.includes('example') && !em.includes('@sentry')) email = em; }
// Meta description const metaDesc = body.match(/name=["']description["'][^>]*content=["']([^"']{10,200})["']/i) || body.match(/content=["']([^"']{10,200})["'][^>]*name=["']description["']/i); if (metaDesc) desc = metaDesc[1].trim().substring(0, 120);
// Fill fields if (negocio) { document.getElementById('negocio-in').value = negocio; }
// Build status message const found = []; if (negocio) found.push('negocio'); if (telefono) found.push('tel: ' + telefono); if (email) found.push('email: ' + email);
status.style.color = 'var(--green)'; status.textContent = found.length > 0 ? '✓ Detectado: ' + found.join(' · ') : '— Sin datos adicionales detectados';
// Store extra for message generation window._autoPhone = telefono; window._autoEmail = email; window._autoDesc = desc;
guardarCampos(); document.getElementById('nombre-in').focus(); toast('Datos detectados — ingresa el nombre del contacto');
} catch(e) { status.style.color = 'var(--amber)'; status.textContent = '⚠ No se pudo leer el sitio — ingresa los datos manualmente'; }
btn.disabled = false; btn.innerHTML = ''; }
function nuevoCliente() { document.getElementById('url-in').value = ''; document.getElementById('nombre-in').value = ''; document.getElementById('negocio-in').value = ''; document.querySelectorAll('#canal-chips .chip').forEach((c,i) => c.classList.toggle('on', i===0)); canal = 'WhatsApp'; lastUrl = ''; lastNombre = ''; lastNegocio = ''; lastChecks = []; document.getElementById('results-area').style.display = 'none'; document.getElementById('seo-snapshot').style.display = 'none'; document.getElementById('empty-state').style.display = 'flex'; document.getElementById('prog-wrap').style.display = 'none'; guardarCampos(); document.getElementById('url-in').focus(); toast('Formulario limpio — listo para nuevo cliente'); }
function guardarCampos() { localStorage.setItem('wpr_campos', JSON.stringify({ url: document.getElementById('url-in').value, nombre: document.getElementById('nombre-in').value, negocio: document.getElementById('negocio-in').value, canal: canal, apiKey: document.getElementById('api-key').value })); }
function cargarCamposGuardados() { try { const saved = JSON.parse(localStorage.getItem('wpr_campos') || '{}'); if (saved.url) document.getElementById('url-in').value = saved.url; if (saved.nombre) document.getElementById('nombre-in').value = saved.nombre; if (saved.negocio) document.getElementById('negocio-in').value = saved.negocio; if (saved.apiKey) { document.getElementById('api-key').value = saved.apiKey; checkApiKey(); } if (saved.canal) { canal = saved.canal; document.querySelectorAll('#canal-chips .chip').forEach(c => c.classList.toggle('on', c.dataset.v === saved.canal)); } } catch(e) {} }
// Init renderHistory(); checkApiKey(); cargarCamposGuardados();