Dashboard Estratégico — TheFittClub
Meta mes 6: 109 clientas activas · 17.300€/mes Actualizado:
$= dv.date("today").toFormat("dd/MM/yyyy")
Resumen ejecutivo
const notas = dv.pages('"40_Contenido_Redes/Publicado_IG"').array();
const conDatos = notas.filter(p => p.alcance_total > 0);
const total = notas.length;
const totalAlcance = conDatos.reduce((a, p) => a + (p.alcance_total || 0), 0);
const totalGuardados = notas.reduce((a, p) => a + (p.guardados || 0), 0);
const totalCompartidos = notas.reduce((a, p) => a + (p.compartidos || 0), 0);
const topAlcance = conDatos.slice().sort((a, b) => (b.alcance_total||0) - (a.alcance_total||0))[0];
const topGuardados = notas.slice().sort((a, b) => (b.guardados||0) - (a.guardados||0))[0];
const topCompartidos = notas.filter(p => p.compartidos > 0).sort((a, b) => (b.compartidos||0) - (a.compartidos||0))[0];
dv.paragraph(`
| Señal | Valor | Qué significa |
|---|---|---|
| Posts con métricas | ${conDatos.length} / ${total} | — |
| Alcance histórico total | ${totalAlcance.toLocaleString()} | Impacto acumulado |
| Guardados totales | ${totalGuardados.toLocaleString()} | Autoridad generada |
| Compartidos totales | ${totalCompartidos.toLocaleString()} | Crecimiento orgánico |
| Mejor post (alcance) | ${topAlcance ? topAlcance.titulo?.slice(0,35) + "…" : "—"} | ${topAlcance ? topAlcance.alcance_total?.toLocaleString() + " alcance" : ""} |
| Mejor post (guardados) | ${topGuardados ? topGuardados.titulo?.slice(0,35) + "…" : "—"} | ${topGuardados ? topGuardados.guardados?.toLocaleString() + " guardados" : ""} |
`);Panel de acción rápida (esta semana)
Qué repetir (ganadores)
const notas = dv.pages('"40_Contenido_Redes/Publicado_IG"').filter(p => p.alcance_total > 0).array();
const ganadores = notas
.filter(p => (p.guardados || 0) >= 120 || (p.compartidos || 0) >= 25)
.sort((a, b) => ((b.guardados || 0) + (b.compartidos || 0) * 3) - ((a.guardados || 0) + (a.compartidos || 0) * 3))
.slice(0, 8)
.map(p => [
p.fecha || "—",
p.categoria || "sin_categoria",
p.hook_tipo || "sin_hook",
p.guardados || 0,
p.compartidos || 0,
(p.titulo || "").slice(0, 60)
]);
if (ganadores.length === 0) {
dv.paragraph("Aún no hay suficientes datos para recomendar repetición.");
} else {
dv.table(["Fecha", "Categoría", "Hook", "Guard.", "Comp.", "Tema"], ganadores);
}Qué parar o reformular (señal débil)
const notas = dv.pages('"40_Contenido_Redes/Publicado_IG"').filter(p => p.alcance_total > 0).array();
const flojos = notas
.filter(p => (p.alcance_total || 0) < 2000 && (p.guardados || 0) < 40 && (p.compartidos || 0) < 8)
.sort((a, b) => (a.alcance_total || 0) - (b.alcance_total || 0))
.slice(0, 8)
.map(p => [
p.fecha || "—",
p.categoria || "sin_categoria",
p.hook_tipo || "sin_hook",
p.alcance_total || 0,
p.guardados || 0,
p.compartidos || 0,
"Reformular hook + CTA"
]);
if (flojos.length === 0) {
dv.paragraph("No hay piezas claramente flojas con datos suficientes.");
} else {
dv.table(["Fecha", "Categoría", "Hook", "Alcance", "Guard.", "Comp.", "Acción"], flojos);
}KPI de negocio (prioridad semanal)
Este dashboard ayuda con contenido. La decisión semanal final se toma con
00_Home/Semanal.mdy estos 4 KPI.
| KPI | Conservador | Moderado | Alto |
|---|---|---|---|
| Signup Cápsula / semana | < 20 | 40-60 | > 80 |
| Completado Cápsula | < 40% | 55-65% | > 70% |
| Conversión Cápsula → Ritual | < 3% | 5-6% | > 7% |
| Retención trimestral | < 60% | 68-72% | > 75% |
Trigger de acción si estás por debajo del moderado:
- Signup bajo → revisar blast, asunto y segundo envío a no-abiertos.
- Completado bajo → revisar UX sesión 1 + timing email día 1.
- Conversión baja → reforzar testimonials en día 3 + oferta 72h en día 4.
- Retención baja → activar email semana 8-10 con progreso real.
1 · MOTOR DE CRECIMIENTO — Qué contenido atrae seguidoras nuevas
Estos son los posts que más han llegado a personas que no te seguían. Son tu materia prima para crecer: recíclalos, adáptalos, hazlos Reels nuevos.
1a · Top por ALCANCE TOTAL (cuántas personas te vieron)
TABLE
fecha as "Fecha",
tipo as "Tipo",
alcance_total as "Alcance",
compartidos as "Compart.",
likes as "Likes",
titulo as "Tema"
FROM "40_Contenido_Redes/Publicado_IG"
WHERE alcance_total > 5000
SORT alcance_total DESC
LIMIT 151b · Top por COMPARTIDOS (cuántas personas te recomendaron)
Un compartido vale más que 10 likes: alguien mandó tu contenido a otra persona que no te conoce.
TABLE
fecha as "Fecha",
tipo as "Tipo",
compartidos as "Compartidos",
alcance_total as "Alcance",
likes as "Likes",
titulo as "Tema"
FROM "40_Contenido_Redes/Publicado_IG"
WHERE compartidos > 0
SORT compartidos DESC
LIMIT 151c · Patrón ganador — ¿Qué CATEGORÍA de contenido crece más?
Clasifica cada post con
categoria:en la nota. A medida que lo rellenas, esta tabla se vuelve tu brújula de producción.
const notas = dv.pages('"40_Contenido_Redes/Publicado_IG"').filter(p => p.alcance_total > 0);
const porCat = {};
const etiquetas = {
rutina: "💪 Rutina",
explicacion: "🧠 Explicación",
gancho_estetico: "✨ Gancho estético",
detras_camaras: "🎬 Detrás de cámaras",
testimonial: "💬 Testimonial",
};
for (const p of notas) {
const cat = p.categoria || "sin_clasificar";
if (!porCat[cat]) porCat[cat] = { posts: 0, alcance: 0, compartidos: 0, guardados: 0 };
porCat[cat].posts++;
porCat[cat].alcance += p.alcance_total || 0;
porCat[cat].compartidos += p.compartidos || 0;
porCat[cat].guardados += p.guardados || 0;
}
const filas = Object.entries(porCat)
.map(([cat, d]) => {
const label = etiquetas[cat] || cat;
const alcMed = Math.round(d.alcance / d.posts);
const guarMed = Math.round(d.guardados / d.posts);
const compMed = Math.round(d.compartidos / d.posts * 10) / 10;
return [label, d.posts, alcMed.toLocaleString(), guarMed, compMed];
})
.sort((a, b) => parseInt(b[2].replace(/\D/g,'')) - parseInt(a[2].replace(/\D/g,'')));
dv.table(["Categoría", "Posts", "Alcance medio", "Guardados medio", "Compart. medio"], filas);1d · Patrón ganador — ¿Qué HOOK abre más?
Rellena
hook_tipo:en las notas nuevas. Aquí verás qué gancho funciona mejor.
const notas = dv.pages('"40_Contenido_Redes/Publicado_IG"').filter(p => p.alcance_total > 0 && p.hook_tipo);
const porHook = {};
for (const p of notas) {
const h = p.hook_tipo;
if (!porHook[h]) porHook[h] = { posts: 0, alcance: 0, compartidos: 0 };
porHook[h].posts++;
porHook[h].alcance += p.alcance_total || 0;
porHook[h].compartidos += p.compartidos || 0;
}
const filas = Object.entries(porHook)
.map(([h, d]) => [h, d.posts, Math.round(d.alcance / d.posts).toLocaleString(), Math.round(d.compartidos / d.posts * 10) / 10])
.sort((a, b) => parseInt(b[2].replace(/\D/g,'')) - parseInt(a[2].replace(/\D/g,'')));
if (filas.length === 0) {
dv.paragraph("⚠️ Añade `hook_tipo:` en las notas para activar este análisis.");
} else {
dv.table(["Hook", "Posts", "Alcance medio", "Compart. medio"], filas);
}1e · Distribución por PILAR (sistema GEO)
Esta tabla mide qué pilar aporta más alcance medio para equilibrar la estrategia semanal. Distribución objetivo inicial: 35% método · 30% ciencia · 25% filosofía · 10% transformación.
const notas = dv.pages('"40_Contenido_Redes/Publicado_IG"').filter(p => p.alcance_total > 0 && p.pilar).array();
const porPilar = {};
const etiquetas = {
ciencia: "Ciencia",
metodo: "Método",
filosofia: "Filosofía",
transformacion: "Transformación",
};
for (const p of notas) {
const k = (p.pilar || "").toString().trim().toLowerCase();
if (!k) continue;
if (!porPilar[k]) porPilar[k] = { posts: 0, alcance: 0, guardados: 0, compartidos: 0 };
porPilar[k].posts++;
porPilar[k].alcance += p.alcance_total || 0;
porPilar[k].guardados += p.guardados || 0;
porPilar[k].compartidos += p.compartidos || 0;
}
const filas = Object.entries(porPilar)
.map(([k, d]) => {
const label = etiquetas[k] || k;
const alcanceMedio = Math.round(d.alcance / d.posts);
const guardadosMedio = Math.round(d.guardados / d.posts);
const compartidosMedio = Math.round((d.compartidos / d.posts) * 10) / 10;
return [label, d.posts, alcanceMedio.toLocaleString(), guardadosMedio, compartidosMedio];
})
.sort((a, b) => parseInt(b[2].replace(/\D/g, "")) - parseInt(a[2].replace(/\D/g, "")));
if (filas.length === 0) {
dv.paragraph("⚠️ Añade `pilar:` en las notas de Publicado_IG para activar este análisis.");
} else {
dv.table(["Pilar", "Posts", "Alcance medio", "Guardados medio", "Compart. medio"], filas);
}2 · DECISIÓN DE PRODUCTO — Qué Cápsula crear primero
Las dolencias que más aparecen en comentarios = demanda real con dinero sobre la mesa. Rellena
pain_flagscada vez que publicas — es el dato más valioso del sistema.
const notas = dv.pages('"40_Contenido_Redes/Publicado_IG"');
const contador = {};
for (const nota of notas) {
const flags = nota.pain_flags;
if (!flags) continue;
const lista = Array.isArray(flags) ? flags : [flags];
for (const flag of lista) {
const f = flag.trim().toLowerCase();
if (!f || f === "") continue;
contador[f] = (contador[f] || 0) + 1;
}
}
const mapaProducto = {
diastasis: "Módulo Core (97€)",
cesarea: "Cápsula Cicatriz (67€)",
suelo_pelvico: "Módulo Pélvico (97€)",
incontinencia: "Cápsula Piso Pélvico (47€)",
dolor_pelvico: "Cápsula Dolor Pélvico (47€)",
dolor_lumbar: "Cápsula Lumbar (47€)",
recuperacion_postparto: "Ritual Trimestral (147€)",
falta_tiempo: "Ritual Trimestral (147€)",
barriga_postparto: "Cápsula Estética (47€)",
hipopresivos: "Cápsula Hipopresivos (67€)",
};
const ranking = Object.entries(contador).sort((a, b) => b[1] - a[1]);
if (ranking.length === 0) {
dv.paragraph("⚠️ Aún no hay pain_flags registrados. Añádelos en cada nota tras leer los comentarios.");
} else {
dv.table(
["Dolencia", "Menciones", "Prioridad", "Producto sugerido"],
ranking.map(([f, n]) => [f, n, "⭐".repeat(Math.min(n, 5)), mapaProducto[f] || "—"])
);
}3 · AUTORIDAD — Qué contenido convierte al Ritual Trimestral (147€)
Posts con muchos guardados = tu audiencia los usa como referencia → mayor intención de compra. Úsalos en Stories de venta, emails y como “prueba social” en la landing.
TABLE
fecha as "Fecha",
tipo as "Tipo",
guardados as "Guardados",
alcance_total as "Alcance",
titulo as "Tema"
FROM "40_Contenido_Redes/Publicado_IG"
WHERE guardados > 200
SORT guardados DESC
LIMIT 154 · Tracción Externa — Ganchos para Cápsula Cero (0€)
Posts que más alcanzan a no seguidoras → reciclar como gancho de captación de tráfico frío.
TABLE
fecha as "Fecha",
tipo as "Tipo",
round((alcance_no_seguidores / alcance_total) * 100, 1) + "%" as "Tracción %",
alcance_no_seguidores as "No Seguidoras",
alcance_total as "Alcance",
choice(gancho_estetico, "✅", "—") as "Gancho"
FROM "40_Contenido_Redes/Publicado_IG"
WHERE alcance_no_seguidores > 0
SORT (alcance_no_seguidores / alcance_total) DESC
LIMIT 156 · Biblioteca de Ganchos Estéticos (listos para reciclar en Reels o Ads)
TABLE
fecha as "Fecha",
tipo as "Tipo",
alcance_total as "Alcance",
compartidos as "Compart.",
angulo as "Ángulo",
url as "URL"
FROM "40_Contenido_Redes/Publicado_IG"
WHERE gancho_estetico = true
SORT alcance_total DESC7 · Alertas — Posts sin clasificar
Añade
angulo,producto_objetivoypain_flagspara mantener el sistema útil.
TABLE
fecha as "Fecha",
tipo as "Tipo",
alcance_total as "Alcance",
guardados as "Guardados"
FROM "40_Contenido_Redes/Publicado_IG"
WHERE (producto_objetivo = "" OR producto_objetivo = null) AND alcance_total > 1000
SORT fecha DESC
LIMIT 20