fix: menú SEO realista — paneles distintos y sin stubs Semrush vacíos
Recorta la suite a secciones con GSC/GA4 (overview, auditoría checklist, rankings con histórico, tendencia, páginas, keywords, insights, contenido). Competencia/backlinks quedan como “herramienta externa”. Ya no se reutiliza el mismo dashboard en ítems distintos. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -547,15 +547,12 @@ export default function OrganicoDashboard({
|
|||||||
<div className="space-y-4 min-w-0">
|
<div className="space-y-4 min-w-0">
|
||||||
<SectionHero section={section} />
|
<SectionHero section={section} />
|
||||||
|
|
||||||
{/* Paneles por sección (no el mismo dashboard en todos) */}
|
{/* Paneles SEO por sección */}
|
||||||
{section.id === 'seo-overview' && (
|
{section.id === 'seo-overview' && (
|
||||||
<>
|
<>
|
||||||
<div className="grid grid-cols-2 lg:grid-cols-4 gap-3">
|
<div className="grid grid-cols-2 lg:grid-cols-4 gap-3">
|
||||||
<Kpi label="Clics GSC" value={formatNum(totals.gscClicks)} />
|
<Kpi label="Clics GSC" value={formatNum(totals.gscClicks)} />
|
||||||
<Kpi
|
<Kpi label="Impresiones" value={formatNum(totals.gscImpressions)} />
|
||||||
label="Impresiones"
|
|
||||||
value={formatNum(totals.gscImpressions)}
|
|
||||||
/>
|
|
||||||
<Kpi label="CTR" value={formatPct(totals.gscCtr)} />
|
<Kpi label="CTR" value={formatPct(totals.gscCtr)} />
|
||||||
<Kpi
|
<Kpi
|
||||||
label="Posición media"
|
label="Posición media"
|
||||||
@@ -576,9 +573,9 @@ export default function OrganicoDashboard({
|
|||||||
value={formatNum(totals.ga4Conversions)}
|
value={formatNum(totals.ga4Conversions)}
|
||||||
/>
|
/>
|
||||||
<Kpi
|
<Kpi
|
||||||
label="Días con datos"
|
label="Días con histórico"
|
||||||
value={formatNum(totals.days)}
|
value={formatNum(totals.days)}
|
||||||
hint="Serie cargada"
|
hint="organic_daily"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{seoDaily.length > 0 && (
|
{seoDaily.length > 0 && (
|
||||||
@@ -589,16 +586,10 @@ export default function OrganicoDashboard({
|
|||||||
</p>
|
</p>
|
||||||
<div className="flex items-end gap-0.5 h-16">
|
<div className="flex items-end gap-0.5 h-16">
|
||||||
{seoDaily.map((d) => (
|
{seoDaily.map((d) => (
|
||||||
<div
|
<div key={`c-${d.day}`} className="flex-1" title={`${d.day}: ${d.clicks}`}>
|
||||||
key={`c-${d.day}`}
|
|
||||||
className="flex-1"
|
|
||||||
title={`${d.day}: ${d.clicks} clics`}
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
className="w-full rounded-t bg-emerald-400/80"
|
className="w-full rounded-t bg-emerald-400/80"
|
||||||
style={{
|
style={{ height: `${Math.max(3, (d.clicks / maxClicks) * 100)}%` }}
|
||||||
height: `${Math.max(3, (d.clicks / maxClicks) * 100)}%`,
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
@@ -610,16 +601,10 @@ export default function OrganicoDashboard({
|
|||||||
</p>
|
</p>
|
||||||
<div className="flex items-end gap-0.5 h-16">
|
<div className="flex items-end gap-0.5 h-16">
|
||||||
{seoDaily.map((d) => (
|
{seoDaily.map((d) => (
|
||||||
<div
|
<div key={`s-${d.day}`} className="flex-1" title={`${d.day}: ${d.sessions}`}>
|
||||||
key={`s-${d.day}`}
|
|
||||||
className="flex-1"
|
|
||||||
title={`${d.day}: ${d.sessions} sesiones`}
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
className="w-full rounded-t bg-sky-400/80"
|
className="w-full rounded-t bg-sky-400/80"
|
||||||
style={{
|
style={{ height: `${Math.max(3, (d.sessions / maxSessions) * 100)}%` }}
|
||||||
height: `${Math.max(3, (d.sessions / maxSessions) * 100)}%`,
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
@@ -628,7 +613,7 @@ export default function OrganicoDashboard({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{totals.days === 0 && (
|
{totals.days === 0 && (
|
||||||
<EmptyHint text="GSC/GA4 conectados pero sin filas en organic_daily. Lanza sync en Agencia o revisa property/URL-prefix." />
|
<EmptyHint text="Sin filas en organic_daily. Sync GA4/GSC en Agencia." />
|
||||||
)}
|
)}
|
||||||
<SeoTables
|
<SeoTables
|
||||||
queries={gscQueries.slice(0, 8)}
|
queries={gscQueries.slice(0, 8)}
|
||||||
@@ -638,22 +623,169 @@ export default function OrganicoDashboard({
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{(section.id === 'seo-keywords' ||
|
{section.live === 'seo-foundations' && (
|
||||||
section.id === 'seo-rankings' ||
|
<div className="space-y-3">
|
||||||
section.id === 'seo-keyword-magic' ||
|
<p className="text-xs text-gray-600">
|
||||||
section.id === 'seo-keyword-gap') && (
|
Checklist de auditoría operativa. El estado «OK» de medición
|
||||||
<SeoTables
|
refleja si GA4 + GSC están conectados; el resto lo cierra el equipo.
|
||||||
queries={gscQueries}
|
</p>
|
||||||
pages={[]}
|
<ul className="grid grid-cols-1 md:grid-cols-2 gap-2">
|
||||||
landings={[]}
|
{SEO_FOUNDATIONS.map((f) => {
|
||||||
focus="queries"
|
const ok =
|
||||||
/>
|
f.id === 'medicion' &&
|
||||||
|
ga4?.status === 'connected' &&
|
||||||
|
gsc?.status === 'connected';
|
||||||
|
return (
|
||||||
|
<li
|
||||||
|
key={f.id}
|
||||||
|
className={`rounded-lg border px-3 py-2.5 ${
|
||||||
|
ok
|
||||||
|
? 'border-emerald-200 bg-emerald-50'
|
||||||
|
: 'border-gray-200 bg-white'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<p className="text-sm font-semibold text-gray-900">
|
||||||
|
{f.title}
|
||||||
|
{ok ? (
|
||||||
|
<span className="ml-2 text-[10px] uppercase text-emerald-700">
|
||||||
|
OK
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<span className="ml-2 text-[10px] uppercase text-amber-700">
|
||||||
|
Revisar
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
<p className="text-[11px] text-gray-600 mt-0.5">{f.hint}</p>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
<div className="rounded-xl border border-gray-200 bg-white p-3 text-xs text-gray-700 space-y-1">
|
||||||
|
<p className="font-semibold text-gray-900">Estado conexiones</p>
|
||||||
|
<p>GSC: {gsc?.status === 'connected' ? 'conectado' : 'sin conectar'}{gsc?.external_account_id ? ` · ${gsc.external_account_id}` : ''}</p>
|
||||||
|
<p>GA4: {ga4?.status === 'connected' ? 'conectado' : 'sin conectar'}{ga4?.external_account_id ? ` · ${ga4.external_account_id}` : ''}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{(section.id === 'seo-pages' ||
|
{section.live === 'seo-rankings' && (
|
||||||
section.id === 'seo-organic' ||
|
<div className="space-y-4">
|
||||||
section.id === 'seo-traffic-insights' ||
|
<div className="rounded-xl border border-sky-200 bg-sky-50 px-3 py-2 text-xs text-sky-900">
|
||||||
section.id === 'seo-compare') && (
|
<strong>Sí hay histórico:</strong> posición media diaria en{' '}
|
||||||
|
<code className="text-[10px]">organic_daily</code> (acumulamos
|
||||||
|
nosotros). Las queries actuales vienen live de GSC (ventana ~28d).
|
||||||
|
No es un rank tracker de 10k KW tipo Semrush.
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-2 lg:grid-cols-3 gap-3">
|
||||||
|
<Kpi
|
||||||
|
label="Posición media (periodo)"
|
||||||
|
value={
|
||||||
|
totals.gscAvgPosition
|
||||||
|
? formatNum(totals.gscAvgPosition, 1)
|
||||||
|
: '—'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Kpi label="Queries con datos" value={formatNum(gscQueries.length)} />
|
||||||
|
<Kpi
|
||||||
|
label="Días históricos"
|
||||||
|
value={formatNum(totals.days)}
|
||||||
|
hint="organic_daily"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{seoDaily.length > 0 && (
|
||||||
|
<div className="rounded-xl border border-gray-200 bg-white p-3">
|
||||||
|
<p className="text-[10px] uppercase tracking-wider text-gray-500 mb-2">
|
||||||
|
Posición media GSC · histórico diario
|
||||||
|
</p>
|
||||||
|
<div className="flex items-end gap-0.5 h-20">
|
||||||
|
{organic
|
||||||
|
.filter((r) => r.day)
|
||||||
|
.sort((a, b) => String(a.day).localeCompare(String(b.day)))
|
||||||
|
.slice(-28)
|
||||||
|
.map((r) => {
|
||||||
|
const pos = Number(r.gsc_avg_position) || 0;
|
||||||
|
const h =
|
||||||
|
pos > 0 ? Math.max(8, Math.min(100, (1 / pos) * 100)) : 4;
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={`pos-${r.day}`}
|
||||||
|
className="flex-1"
|
||||||
|
title={`${String(r.day).slice(0, 10)}: pos ${pos || '—'}`}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="w-full rounded-t bg-violet-400/80"
|
||||||
|
style={{ height: `${h}%` }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
<p className="text-[10px] text-gray-500 mt-1">
|
||||||
|
Barras más altas ≈ mejor posición (inverso)
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<SeoTables
|
||||||
|
queries={[...gscQueries].sort((a, b) => a.position - b.position)}
|
||||||
|
pages={[]}
|
||||||
|
landings={[]}
|
||||||
|
focus="queries"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{section.live === 'seo-trend' && (
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="grid grid-cols-2 lg:grid-cols-4 gap-3">
|
||||||
|
<Kpi label="Clics" value={formatNum(totals.gscClicks)} />
|
||||||
|
<Kpi label="Impresiones" value={formatNum(totals.gscImpressions)} />
|
||||||
|
<Kpi label="CTR" value={formatPct(totals.gscCtr)} />
|
||||||
|
<Kpi
|
||||||
|
label="Sesiones orgánicas"
|
||||||
|
value={formatNum(totals.ga4Organic)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{seoDaily.length > 0 ? (
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
|
||||||
|
<div className="rounded-xl border border-gray-200 bg-white p-3">
|
||||||
|
<p className="text-[10px] uppercase tracking-wider text-gray-500 mb-2">
|
||||||
|
Clics · evolución
|
||||||
|
</p>
|
||||||
|
<div className="flex items-end gap-0.5 h-24">
|
||||||
|
{seoDaily.map((d) => (
|
||||||
|
<div key={`t-${d.day}`} className="flex-1" title={`${d.day}: ${d.clicks}`}>
|
||||||
|
<div
|
||||||
|
className="w-full rounded-t bg-emerald-500/80"
|
||||||
|
style={{ height: `${Math.max(3, (d.clicks / maxClicks) * 100)}%` }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="rounded-xl border border-gray-200 bg-white p-3">
|
||||||
|
<p className="text-[10px] uppercase tracking-wider text-gray-500 mb-2">
|
||||||
|
Sesiones orgánicas · evolución
|
||||||
|
</p>
|
||||||
|
<div className="flex items-end gap-0.5 h-24">
|
||||||
|
{seoDaily.map((d) => (
|
||||||
|
<div key={`u-${d.day}`} className="flex-1" title={`${d.day}: ${d.sessions}`}>
|
||||||
|
<div
|
||||||
|
className="w-full rounded-t bg-sky-500/80"
|
||||||
|
style={{ height: `${Math.max(3, (d.sessions / maxSessions) * 100)}%` }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<EmptyHint text="Sin serie diaria todavía." />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{section.live === 'seo-pages' && (
|
||||||
<SeoTables
|
<SeoTables
|
||||||
queries={[]}
|
queries={[]}
|
||||||
pages={gscPages}
|
pages={gscPages}
|
||||||
@@ -662,27 +794,45 @@ export default function OrganicoDashboard({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{section.id === 'seo-organic' && seoDaily.length > 0 && (
|
{section.live === 'seo-queries' && (
|
||||||
<div className="rounded-xl border border-gray-200 bg-white p-3">
|
<SeoTables
|
||||||
<p className="text-[10px] uppercase tracking-wider text-gray-500 mb-2">
|
queries={gscQueries}
|
||||||
Evolución clics orgánicos
|
pages={[]}
|
||||||
|
landings={[]}
|
||||||
|
focus="queries"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{section.live === 'seo-cross' && (
|
||||||
|
<div className="space-y-4">
|
||||||
|
<p className="text-xs text-gray-600">
|
||||||
|
Cruce: qué URLs rankean (GSC) vs qué landings reciben sesión
|
||||||
|
orgánica (GA4).
|
||||||
</p>
|
</p>
|
||||||
<div className="flex items-end gap-0.5 h-20">
|
<SeoTables
|
||||||
{seoDaily.map((d) => (
|
queries={[]}
|
||||||
<div
|
pages={gscPages}
|
||||||
key={`o-${d.day}`}
|
landings={ga4Landings}
|
||||||
className="flex-1"
|
focus="pages"
|
||||||
title={`${d.day}: ${d.clicks}`}
|
/>
|
||||||
>
|
</div>
|
||||||
<div
|
)}
|
||||||
className="w-full rounded-t bg-emerald-500/80"
|
|
||||||
style={{
|
{section.live === 'seo-content' && (
|
||||||
height: `${Math.max(3, (d.clicks / maxClicks) * 100)}%`,
|
<div className="space-y-3">
|
||||||
}}
|
<p className="text-xs text-gray-600">
|
||||||
/>
|
Ideas a partir de queries con impresiones altas y CTR bajo
|
||||||
</div>
|
(oportunidad de mejorar snippet / contenido).
|
||||||
))}
|
</p>
|
||||||
</div>
|
<SeoTables
|
||||||
|
queries={[...gscQueries]
|
||||||
|
.filter((q) => q.impressions >= 50)
|
||||||
|
.sort((a, b) => a.ctr - b.ctr)
|
||||||
|
.slice(0, 25)}
|
||||||
|
pages={[]}
|
||||||
|
landings={[]}
|
||||||
|
focus="queries"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -793,32 +943,6 @@ export default function OrganicoDashboard({
|
|||||||
<CategoryPanel latest={latestGeo} />
|
<CategoryPanel latest={latestGeo} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{section.live === 'seo-foundations' && (
|
|
||||||
<ul className="grid grid-cols-1 md:grid-cols-2 gap-2">
|
|
||||||
{SEO_FOUNDATIONS.map((f) => {
|
|
||||||
const ok =
|
|
||||||
f.id === 'medicion' &&
|
|
||||||
ga4?.status === 'connected' &&
|
|
||||||
gsc?.status === 'connected';
|
|
||||||
return (
|
|
||||||
<li
|
|
||||||
key={f.id}
|
|
||||||
className={`rounded-lg border px-3 py-2.5 ${
|
|
||||||
ok
|
|
||||||
? 'border-emerald-200 bg-emerald-50'
|
|
||||||
: 'border-gray-200 bg-white'
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<p className="text-sm font-semibold text-gray-900">
|
|
||||||
{f.title}
|
|
||||||
</p>
|
|
||||||
<p className="text-[11px] text-gray-600 mt-0.5">{f.hint}</p>
|
|
||||||
</li>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</ul>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Prioridades + notas solo en visión general SEO/GEO */}
|
{/* Prioridades + notas solo en visión general SEO/GEO */}
|
||||||
{(section.id === 'seo-overview' || section.id === 'geo-overview') && (
|
{(section.id === 'seo-overview' || section.id === 'geo-overview') && (
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||||
@@ -930,10 +1054,28 @@ export default function OrganicoDashboard({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{section.soon && (
|
{section.soon && (
|
||||||
<p className="text-xs text-amber-900 bg-amber-50 border border-amber-200 rounded-lg px-3 py-2">
|
<div className="rounded-xl border border-amber-200 bg-amber-50 p-4 space-y-2">
|
||||||
Disponible en breve: informes de ROI IA + tráfico/conversiones GA4
|
<p className="text-sm font-semibold text-amber-900">
|
||||||
en un clic.
|
Requiere herramienta externa
|
||||||
</p>
|
</p>
|
||||||
|
<p className="text-xs text-amber-800">
|
||||||
|
Competencia de dominio, keyword gap y backlinks no salen de
|
||||||
|
GSC/GA4. Hay que conectar Ahrefs/Semrush (o importar CSV) para
|
||||||
|
alimentar este panel. Mientras tanto usa las secciones con datos
|
||||||
|
reales: visión general, rankings, keywords y páginas.
|
||||||
|
</p>
|
||||||
|
<ul className="space-y-1.5 pt-1">
|
||||||
|
{section.actions.map((a) => (
|
||||||
|
<li
|
||||||
|
key={a}
|
||||||
|
className="flex items-start gap-2 text-xs text-amber-900"
|
||||||
|
>
|
||||||
|
<ArrowRight className="w-3.5 h-3.5 shrink-0 mt-0.5" />
|
||||||
|
{a}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!section.soon &&
|
{!section.soon &&
|
||||||
|
|||||||
@@ -213,7 +213,18 @@ export type OrganicoSection = {
|
|||||||
blurb: string;
|
blurb: string;
|
||||||
/** What the user should do next when empty. */
|
/** What the user should do next when empty. */
|
||||||
actions: string[];
|
actions: string[];
|
||||||
live?: 'seo-metrics' | 'geo-metrics' | 'geo-competitors' | 'geo-categories' | 'seo-foundations';
|
live?:
|
||||||
|
| 'seo-metrics'
|
||||||
|
| 'seo-foundations'
|
||||||
|
| 'seo-rankings'
|
||||||
|
| 'seo-trend'
|
||||||
|
| 'seo-pages'
|
||||||
|
| 'seo-queries'
|
||||||
|
| 'seo-cross'
|
||||||
|
| 'seo-content'
|
||||||
|
| 'geo-metrics'
|
||||||
|
| 'geo-competitors'
|
||||||
|
| 'geo-categories';
|
||||||
soon?: boolean;
|
soon?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -370,18 +381,18 @@ export const ORGANICO_SECTIONS: OrganicoSection[] = [
|
|||||||
soon: true,
|
soon: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
// ——— SEO ———
|
// ——— SEO (solo secciones con datos reales GSC/GA4 o checklist operable) ———
|
||||||
{
|
{
|
||||||
id: 'seo-overview',
|
id: 'seo-overview',
|
||||||
pillar: 'seo',
|
pillar: 'seo',
|
||||||
group: 'Rendimiento del sitio',
|
group: 'Rendimiento del sitio',
|
||||||
label: 'Visión general',
|
label: 'Visión general',
|
||||||
blurb:
|
blurb:
|
||||||
'Hazte visible donde busca tu audiencia. Serie diaria desde GA4/GSC — el portal guarda histórico propio (GSC solo ofrece ~16 meses en API).',
|
'KPIs diarios GA4 + GSC. El histórico vive en organic_daily (nosotros lo acumulamos; la API de GSC sola no basta).',
|
||||||
actions: [
|
actions: [
|
||||||
'Conectar Search Console y GA4',
|
'Conectar Search Console y GA4',
|
||||||
'Sincronizar (histórico acumulado en organic_daily)',
|
'Revisar serie 28d',
|
||||||
'Definir 3 prioridades del mes',
|
'Definir prioridades del mes',
|
||||||
],
|
],
|
||||||
live: 'seo-metrics',
|
live: 'seo-metrics',
|
||||||
},
|
},
|
||||||
@@ -391,11 +402,11 @@ export const ORGANICO_SECTIONS: OrganicoSection[] = [
|
|||||||
group: 'Rendimiento del sitio',
|
group: 'Rendimiento del sitio',
|
||||||
label: 'Auditoría del sitio',
|
label: 'Auditoría del sitio',
|
||||||
blurb:
|
blurb:
|
||||||
'Consulta problemas de SEO que limitan posicionamiento: salud, contenido y UX.',
|
'Checklist operativo de salud SEO (indexación, arquitectura, CWV, contenido, medición). No es un crawl Semrush: es la base que hay que cerrar con los datos conectados.',
|
||||||
actions: [
|
actions: [
|
||||||
'Auditar indexación y CWV',
|
'Marcar OK/KO por bloque',
|
||||||
'Corregir errores críticos',
|
'Priorizar indexación + medición',
|
||||||
'Plan de remediación por impacto',
|
'CWV en landings de conversión',
|
||||||
],
|
],
|
||||||
live: 'seo-foundations',
|
live: 'seo-foundations',
|
||||||
},
|
},
|
||||||
@@ -405,240 +416,97 @@ export const ORGANICO_SECTIONS: OrganicoSection[] = [
|
|||||||
group: 'Rendimiento del sitio',
|
group: 'Rendimiento del sitio',
|
||||||
label: 'Rastreo de posición',
|
label: 'Rastreo de posición',
|
||||||
blurb:
|
blurb:
|
||||||
'Rastrea posicionamiento en Google (y más adelante Bing / Modo IA) para keywords de alto valor.',
|
'Sí: posición media diaria en organic_daily (histórico nuestro) + ranking actual de queries GSC. No es un rank tracker de 10k KW tipo Semrush; es lo que GSC reporta para tus impresiones reales.',
|
||||||
actions: [
|
actions: [
|
||||||
'Definir cartera de keywords',
|
'Mirar tendencia de posición media',
|
||||||
'Registrar posición media GSC',
|
'Atacar queries en pos. 4–15 (quick wins)',
|
||||||
'Alertar caídas de top 10',
|
'Ampliar cartera vía contenido',
|
||||||
],
|
],
|
||||||
live: 'seo-metrics',
|
live: 'seo-rankings',
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'seo-competition',
|
|
||||||
pillar: 'seo',
|
|
||||||
group: 'Análisis de la competencia',
|
|
||||||
label: 'Visión general del dominio',
|
|
||||||
blurb:
|
|
||||||
'Supera a tu competencia con análisis SEO: tráfico, keywords y estrategias.',
|
|
||||||
actions: [
|
|
||||||
'Fijar 3 dominios rivales',
|
|
||||||
'Comparar autoridad y temáticas',
|
|
||||||
'Extraer oportunidades de contenido',
|
|
||||||
],
|
|
||||||
soon: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'seo-organic',
|
id: 'seo-organic',
|
||||||
pillar: 'seo',
|
pillar: 'seo',
|
||||||
group: 'Análisis de la competencia',
|
group: 'Tráfico y páginas',
|
||||||
label: 'Posicionamiento orgánico',
|
label: 'Posicionamiento orgánico',
|
||||||
blurb:
|
blurb:
|
||||||
'Mide visibilidad orgánica y evolución de clics/impresiones frente al mercado.',
|
'Evolución de clics e impresiones (visibilidad). Distinto de «Páginas principales».',
|
||||||
actions: [
|
actions: [
|
||||||
'Revisar serie GSC MoM',
|
'Leer tendencia MoM de clics',
|
||||||
'Identificar queries en ascenso/descenso',
|
'Cruzar con campañas de contenido',
|
||||||
'Alinear con objetivos de negocio',
|
'Alertar caídas bruscas',
|
||||||
],
|
],
|
||||||
live: 'seo-metrics',
|
live: 'seo-trend',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'seo-pages',
|
id: 'seo-pages',
|
||||||
pillar: 'seo',
|
pillar: 'seo',
|
||||||
group: 'Análisis de la competencia',
|
group: 'Tráfico y páginas',
|
||||||
label: 'Páginas principales',
|
label: 'Páginas principales',
|
||||||
blurb: 'Landings que concentran tráfico y conversión orgánica.',
|
|
||||||
actions: [
|
|
||||||
'Listar top páginas por clics',
|
|
||||||
'Optimizar títulos/meta y UX',
|
|
||||||
'Reforzar enlazado interno',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'seo-compare',
|
|
||||||
pillar: 'seo',
|
|
||||||
group: 'Análisis de la competencia',
|
|
||||||
label: 'Comparación de dominios',
|
|
||||||
blurb: 'Compara tu dominio con rivales en una sola vista.',
|
|
||||||
actions: [
|
|
||||||
'Elegir métricas comunes (tráfico, KW, backlinks)',
|
|
||||||
'Marcar gaps críticos',
|
|
||||||
'Asignar owners internos',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'seo-keyword-gap',
|
|
||||||
pillar: 'seo',
|
|
||||||
group: 'Análisis de la competencia',
|
|
||||||
label: 'Brecha de palabras clave',
|
|
||||||
blurb:
|
blurb:
|
||||||
'Keywords donde rivales rankean y tú no — hoja de ruta clara.',
|
'URLs que concentran clics GSC + landings orgánicas GA4. No es el mismo panel que posicionamiento.',
|
||||||
actions: [
|
actions: [
|
||||||
'Exportar gap vs top rivales',
|
'Optimizar top 10 URLs',
|
||||||
'Priorizar por intención de compra',
|
'Alinear title/H1/CTA',
|
||||||
'Crear o potenciar páginas',
|
'Enlazar desde hubs',
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'seo-backlink-gap',
|
|
||||||
pillar: 'seo',
|
|
||||||
group: 'Análisis de la competencia',
|
|
||||||
label: 'Brecha de backlinks',
|
|
||||||
blurb:
|
|
||||||
'Dominios que enlazan a rivales y no a ti: autoridad y confianza.',
|
|
||||||
actions: [
|
|
||||||
'Listar dominios de referencia únicos de rivales',
|
|
||||||
'Pitch / digital PR',
|
|
||||||
'Monitorizar nuevos enlaces',
|
|
||||||
],
|
],
|
||||||
|
live: 'seo-pages',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'seo-keywords',
|
id: 'seo-keywords',
|
||||||
pillar: 'seo',
|
pillar: 'seo',
|
||||||
group: 'Investigación de palabras clave',
|
group: 'Keywords',
|
||||||
label: 'Visión general de keywords',
|
label: 'Visión general de keywords',
|
||||||
blurb:
|
blurb:
|
||||||
'Palabras clave y prompts con intención de compra para Google y ChatGPT.',
|
'Queries reales con impresiones/clics/CTR/posición desde Search Console (28d).',
|
||||||
actions: [
|
actions: [
|
||||||
'Mapear KW → intención → URL',
|
'Mapear KW → URL',
|
||||||
'Detectar huecos de cobertura',
|
'Separar informativas vs compra',
|
||||||
'Alinear con calendario editorial',
|
'Priorizar quick wins',
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'seo-keyword-magic',
|
|
||||||
pillar: 'seo',
|
|
||||||
group: 'Investigación de palabras clave',
|
|
||||||
label: 'Keyword Magic / ideas',
|
|
||||||
blurb: 'Explora ideas de keywords y variantes semánticas.',
|
|
||||||
actions: [
|
|
||||||
'Sembrar seed keywords del negocio',
|
|
||||||
'Agrupar por clusters',
|
|
||||||
'Seleccionar quick wins',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'seo-strategy',
|
|
||||||
pillar: 'seo',
|
|
||||||
group: 'Investigación de palabras clave',
|
|
||||||
label: 'Keyword Strategy Builder',
|
|
||||||
blurb: 'Construye la estrategia de keywords del trimestre.',
|
|
||||||
actions: [
|
|
||||||
'Definir pilares y clusters',
|
|
||||||
'Asignar prioridad P1/P2/P3',
|
|
||||||
'Vincular a OKRs',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'seo-content-ideas',
|
|
||||||
pillar: 'seo',
|
|
||||||
group: 'Ideas de contenido',
|
|
||||||
label: 'Ideas de contenido',
|
|
||||||
blurb:
|
|
||||||
'Temas en tendencia, planes y briefings optimizados para posicionar.',
|
|
||||||
actions: [
|
|
||||||
'Topic research del mes',
|
|
||||||
'Briefs con outline + KW + FAQs',
|
|
||||||
'Publicar y medir en GSC',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'seo-writing',
|
|
||||||
pillar: 'seo',
|
|
||||||
group: 'Ideas de contenido',
|
|
||||||
label: 'SEO Writing Assistant',
|
|
||||||
blurb: 'Asistencia para redactar y optimizar on-page.',
|
|
||||||
actions: [
|
|
||||||
'Revisar densidad y entidades',
|
|
||||||
'Mejorar claridad y E-E-A-T',
|
|
||||||
'Checklist pre-publicación',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'seo-topics',
|
|
||||||
pillar: 'seo',
|
|
||||||
group: 'Ideas de contenido',
|
|
||||||
label: 'Topic Research',
|
|
||||||
blurb: 'Tendencias de temas que alimentan SEO y GEO.',
|
|
||||||
actions: [
|
|
||||||
'Cruzar topics con prompts IA',
|
|
||||||
'Detectar ángulos diferenciales',
|
|
||||||
'Planificar pieza pilar + satélites',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'seo-template',
|
|
||||||
pillar: 'seo',
|
|
||||||
group: 'Ideas de contenido',
|
|
||||||
label: 'SEO Content Template',
|
|
||||||
blurb: 'Plantillas de contenido basadas en lo que rankea.',
|
|
||||||
actions: [
|
|
||||||
'Analizar SERP / respuestas IA',
|
|
||||||
'Definir estructura ganadora',
|
|
||||||
'Reutilizar en el equipo',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'seo-backlinks',
|
|
||||||
pillar: 'seo',
|
|
||||||
group: 'Generación de enlaces',
|
|
||||||
label: 'Backlinks',
|
|
||||||
blurb:
|
|
||||||
'Gana autoridad con backlinks de calidad que impulsan confianza y SEO.',
|
|
||||||
actions: [
|
|
||||||
'Auditar perfil actual',
|
|
||||||
'Campañas de link earning',
|
|
||||||
'Desautorizar tóxicos',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'seo-refdomains',
|
|
||||||
pillar: 'seo',
|
|
||||||
group: 'Generación de enlaces',
|
|
||||||
label: 'Dominios de referencia',
|
|
||||||
blurb: 'Diversidad y calidad de dominios que te enlazan.',
|
|
||||||
actions: [
|
|
||||||
'Medir referidos únicos',
|
|
||||||
'Buscar nichos afines',
|
|
||||||
'Relaciones con medios / partners',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'seo-backlink-audit',
|
|
||||||
pillar: 'seo',
|
|
||||||
group: 'Generación de enlaces',
|
|
||||||
label: 'Backlink Audit',
|
|
||||||
blurb: 'Salud del perfil de enlaces y riesgo reputacional.',
|
|
||||||
actions: [
|
|
||||||
'Clasificar enlaces',
|
|
||||||
'Disavow si procede',
|
|
||||||
'Informe trimestral',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'seo-onpage',
|
|
||||||
pillar: 'seo',
|
|
||||||
group: 'Extras',
|
|
||||||
label: 'On Page SEO Checker',
|
|
||||||
blurb: 'Comprueba on-page en URLs prioritarias.',
|
|
||||||
actions: [
|
|
||||||
'Auditar top landings',
|
|
||||||
'Corregir title/H1/internal links',
|
|
||||||
'Re-crawl',
|
|
||||||
],
|
],
|
||||||
|
live: 'seo-queries',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'seo-traffic-insights',
|
id: 'seo-traffic-insights',
|
||||||
pillar: 'seo',
|
pillar: 'seo',
|
||||||
group: 'Extras',
|
group: 'Keywords',
|
||||||
label: 'Organic Traffic Insights',
|
label: 'Organic Traffic Insights',
|
||||||
blurb:
|
blurb:
|
||||||
'Cruza GSC + GA4: cómo el orgánico mueve tráfico y conversiones reales.',
|
'Cruce GSC (páginas) + GA4 (sesiones orgánicas / landings) para ver qué rankea y qué convierte.',
|
||||||
actions: [
|
actions: [
|
||||||
'Conectar GA4',
|
'Comparar top pages GSC vs landings GA4',
|
||||||
'Atribuir landings a leads/ventas',
|
'Detectar páginas con clics y poca conversión',
|
||||||
'Informar ROI orgánico',
|
'Informar ROI orgánico',
|
||||||
],
|
],
|
||||||
live: 'seo-metrics',
|
live: 'seo-cross',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'seo-competition',
|
||||||
|
pillar: 'seo',
|
||||||
|
group: 'Competencia y enlaces',
|
||||||
|
label: 'Competencia / backlinks',
|
||||||
|
blurb:
|
||||||
|
'Requiere Ahrefs/Semrush u otra fuente de backlinks y dominio rival. No está en GSC/GA4. Aquí solo el marco de trabajo hasta integrar una herramienta.',
|
||||||
|
actions: [
|
||||||
|
'Fijar 3 dominios rivales',
|
||||||
|
'Importar gap KW / backlinks desde herramienta externa',
|
||||||
|
'Priorizar 5 acciones/mes',
|
||||||
|
],
|
||||||
|
soon: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'seo-content-ideas',
|
||||||
|
pillar: 'seo',
|
||||||
|
group: 'Contenido',
|
||||||
|
label: 'Ideas de contenido',
|
||||||
|
blurb:
|
||||||
|
'Briefs a partir de queries GSC con tracción (clics o impresiones altas y CTR bajo).',
|
||||||
|
actions: [
|
||||||
|
'Partir de queries con CTR bajo',
|
||||||
|
'Crear/ampliar pieza',
|
||||||
|
'Medir de nuevo en 28d',
|
||||||
|
],
|
||||||
|
live: 'seo-content',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user