Documento funcional para implementar un dashboard que, dado ?curso_id=###
, genera
vistas previas por red social, permite compartir/publicar mediante servicios externos por red
y registra histórico. Todo lo “social” vive dentro de /social/
. La raíz solo contiene
el dashboard principal.
Centralizar la operación de difusión de cursos: vista previa realista, generación de URLs con UTM, publicación directa (cuando la red lo permite) vía servicios externos y auditoría mediante histórico.
?curso_id
OG/Twitter listos
UTM por red/medio
Servicios externos por red
Histórico auditable
/ ← raíz del sitio └─ dashboard_publicaciones.php ← Único archivo en raíz └─ /social/ ← Todo lo del proyecto vive aquí ├─ /config/ ← variables y credenciales (protegido) │ ├─ env.example │ └─ env.local ← valores reales (producción) ├─ /storage/ ← archivos de soporte (protegido) │ ├─ /logs/ ← trazas, auditoría simple (txt/json) │ └─ /tmp/ ← temporales / caché de imágenes ├─ /shared/ ← utilidades comunes (helpers) ├─ /fb/ ← servicio Facebook Pages ├─ /ig/ ← servicio Instagram Business ├─ /li/ ← servicio LinkedIn Pages ├─ /x/ ← servicio X (Twitter) ├─ /tg/ ← servicio Telegram ├─ /slack/ ← opcional └─ /discord/ ← opcional
El dashboard, al iniciar, verifica y crea (si faltan) estas carpetas dentro de /social/
y valida permisos de escritura en /social/storage/
.
/dashboard_publicaciones.php?curso_id=44
.curso_id
, crea estructura de /social/
si falta y consulta el curso./social/{red}/publish
.curso_id
.Campo | Tipo | Descripción |
---|---|---|
curso_id | number | ID del curso. |
network | string | facebook | instagram | linkedin | twitter | telegram | slack | discord |
medium | string | organic | story_sticker | bio | dm | paid_social | … |
campaign | string | p.ej. curso_44_lanzamiento_2025w40 |
utm_content | string? | p.ej. sticker_v1 , profile_link |
link_url | string | URL canónica + UTM. |
caption | string | Texto ya limpio y ≤ 250 con sufijo. |
image_url | string? | Imagen OG o creativa (según red). |
requested_by | string | Usuario operador. |
Cada servicio gestiona sus tokens/IDs y devuelve un JSON con ok
, permalink
, external_post_id
y message
.
/social/config
.permalink_url
, post_id
.id
y permalink
.caption + link_url
.tweet_id
y URL del tuit.message_id
y enlace del canal (si público).1) Histórico de publicaciones
CREATE TABLE IF NOT EXISTS social_posts_log ( id BIGINT AUTO_INCREMENT PRIMARY KEY, curso_id BIGINT NOT NULL, network VARCHAR(32) NOT NULL, -- facebook | instagram | linkedin | twitter | telegram | slack | discord | ... medium VARCHAR(32) NOT NULL, -- organic | story_sticker | bio | dm | paid_social | ... campaign VARCHAR(128) NOT NULL, -- ej: curso_44_lanzamiento_2025w40 content_tag VARCHAR(64) NULL, -- ej: sticker_v1, profile_link, feed_ad, reel_ad shared_url TEXT NOT NULL, -- URL final con UTM caption TEXT NULL, -- texto usado external_post_id VARCHAR(128) NULL, -- id del post/mensaje en la plataforma permalink TEXT NULL, -- url pública del post si aplica published_by VARCHAR(128) NULL, -- usuario operador status VARCHAR(24) NOT NULL DEFAULT 'publicado', -- publicado | programado | borrador error_message TEXT NULL, -- si falló la publicación created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, INDEX idx_curso (curso_id), INDEX idx_network (network), INDEX idx_created_at (created_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2) (Opcional) Integraciones por red si decides persistir tokens/IDs en BD
CREATE TABLE IF NOT EXISTS social_integrations ( id BIGINT AUTO_INCREMENT PRIMARY KEY, network VARCHAR(32) NOT NULL, -- facebook | instagram | linkedin | twitter | telegram | ... account_label VARCHAR(128) NOT NULL, -- nombre legible de la cuenta/página config_json JSON NOT NULL, -- { page_id, access_token, ig_business_id, org_id, bot_token, chat_id, ... } is_active TINYINT(1) NOT NULL DEFAULT 1, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, UNIQUE KEY uk_network_label (network, account_label) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
La tabla de cursos ya existe (cursos_sence
). Se consumen nombre_actividad, fundamentacion_tecnica, imagen_curso, id.
Red | UTM sugerida |
---|---|
Facebook orgánico | ?utm_source=facebook&utm_medium=organic&utm_campaign=curso_{id} |
LinkedIn orgánico | ?utm_source=linkedin&utm_medium=organic&utm_campaign=curso_{id} |
X (Twitter) | ?utm_source=twitter&utm_medium=organic&utm_campaign=curso_{id} |
Telegram | ?utm_source=telegram&utm_medium=share&utm_campaign=curso_{id} |
WhatsApp (manual) | ?utm_source=whatsapp&utm_medium=share&utm_campaign=curso_{id} |
Instagram Bio | ?utm_source=instagram&utm_medium=bio&utm_campaign=curso_{id}&utm_content=profile_link |
Instagram Story | ?utm_source=instagram&utm_medium=story_sticker&utm_campaign=curso_{id}&utm_content=sticker_v1 |
Paid Social | ?utm_source={red}&utm_medium=paid_social&utm_campaign=curso_{id}&utm_content={ubicacion} |
curso_id
leído del GET./social/
./social/{red}/publish
)/social/config
y /social/storage
(reglas servidor)./social/storage/logs
./social/*/publish
(CSRF simple o API key interna)./social/
.social_posts_log
y opcional social_integrations
)./social/config/
.social_posts_log
.Cada paso se entrega como bloque independiente para pruebas supervisadas.
Con esta propuesta, un desarrollador puede montar el proyecto sin ambigüedades: carpetas, tablas, contratos, flujos y reglas de negocio están definidos.
¿Listo para avanzar? Cuando digas “autorizar paso 1”, te entrego el primer bloque de código (dashboard base) para pegar y probar.