Initial commit: Proyecto Portal ePromos completo con documentación unificada y seguridad base
This commit is contained in:
+118
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/admin/db.php';
|
||||
require_once __DIR__ . '/lib/landing_helpers.php';
|
||||
|
||||
$slug = trim($_GET['slug'] ?? '');
|
||||
if ($slug==='') { http_response_code(404); echo "Landing no encontrada."; exit; }
|
||||
|
||||
$st = $conn->prepare("SELECT * FROM landing_pages WHERE slug=? AND estado IN ('publicado','borrador') LIMIT 1");
|
||||
$st->bind_param('s',$slug);
|
||||
$st->execute();
|
||||
$landing = $st->get_result()->fetch_assoc();
|
||||
if(!$landing){ http_response_code(404); echo "Landing no encontrada."; exit; }
|
||||
|
||||
$landing_id = (int)$landing['id'];
|
||||
|
||||
// validar schedule
|
||||
if ($landing['estado']!=='publicado' || !lp_schedule_active($conn, $landing_id)) {
|
||||
http_response_code(404); echo "Landing no publicada."; exit;
|
||||
}
|
||||
|
||||
// variante A/B
|
||||
$variant = lp_pick_variant($conn, $landing_id); // null = base
|
||||
// contenido final = variante override o base
|
||||
$hero = $variant['hero_image'] ?? ($landing['hero_image'] ?? '');
|
||||
$html = $variant['contenido_html'] ?? ($landing['contenido_html'] ?? '');
|
||||
$css = ($landing['css_inline'] ?? '') . "\n" . ($variant['css_inline'] ?? '');
|
||||
$js = ($landing['js_inline'] ?? '') . "\n" . ($variant['js_inline'] ?? '');
|
||||
|
||||
// bloques
|
||||
$bloques = lp_load_blocks($conn, $landing_id);
|
||||
|
||||
// tracking impresión
|
||||
$session_id = session_id() ?: bin2hex(random_bytes(8));
|
||||
$vid = $variant['id'] ?? null;
|
||||
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'] ?? null;
|
||||
$ua = $_SERVER['HTTP_USER_AGENT'] ?? null;
|
||||
$ins = $conn->prepare("INSERT INTO landing_variant_stats (landing_id, variant_id, event_type, session_id, ip_address, user_agent)
|
||||
VALUES (?,?,?,?,?,?)");
|
||||
$evt='impression';
|
||||
$ins->bind_param('iissss',$landing_id,$vid,$evt,$session_id,$ip,$ua);
|
||||
$ins->execute();
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title><?= htmlspecialchars($landing['meta_title'] ?: $landing['titulo']) ?></title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<?php if(!empty($landing['meta_desc'])): ?>
|
||||
<meta name="description" content="<?= htmlspecialchars($landing['meta_desc']) ?>">
|
||||
<?php endif; ?>
|
||||
<?php if(!empty($landing['canonical_url'])): ?>
|
||||
<link rel="canonical" href="<?= htmlspecialchars($landing['canonical_url']) ?>">
|
||||
<?php endif; ?>
|
||||
<style>
|
||||
body{margin:0;font-family:system-ui,-apple-system,Segoe UI,Roboto;line-height:1.5;color:#222}
|
||||
.hero{min-height:50vh;display:flex;align-items:center;justify-content:center;background-size:cover;background-position:center;text-align:center;padding:4rem 1rem}
|
||||
.container{max-width:980px;margin:0 auto;padding:2rem 1rem}
|
||||
.btn{display:inline-block;padding:.75rem 1.25rem;border-radius:.5rem;background:#0d6efd;color:#fff;text-decoration:none}
|
||||
<?= $css ?>
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header class="hero" style="background-image:url('<?= htmlspecialchars($hero) ?>');">
|
||||
<div class="container">
|
||||
<h1><?= htmlspecialchars($landing['titulo']) ?></h1>
|
||||
<p><?= htmlspecialchars($landing['meta_desc'] ?? '') ?></p>
|
||||
<a class="btn" href="#form">Quiero más info</a>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="container">
|
||||
<!-- Bloques zona=header -->
|
||||
<?php if(!empty($bloques['header'])): foreach($bloques['header'] as $b): ?>
|
||||
<?php if($b['tipo']==='html') echo $b['contenido']; ?>
|
||||
<?php endforeach; endif; ?>
|
||||
|
||||
<!-- Contenido administrable (base/variante) -->
|
||||
<?= $html ?>
|
||||
|
||||
<!-- Bloques zona=main -->
|
||||
<?php if(!empty($bloques['main'])): foreach($bloques['main'] as $b): ?>
|
||||
<?php if($b['tipo']==='html') echo $b['contenido']; ?>
|
||||
<?php endforeach; endif; ?>
|
||||
|
||||
<hr id="form">
|
||||
<h3>Contáctanos</h3>
|
||||
<form method="post" action="landing_form.php" onsubmit="lpConv();">
|
||||
<input type="hidden" name="landing_id" value="<?= (int)$landing_id ?>">
|
||||
<input type="hidden" name="variant_id" value="<?= (int)($variant['id'] ?? 0) ?>">
|
||||
<div><input name="nombre" placeholder="Nombre" style="width:100%;padding:.6rem;margin:.25rem 0"></div>
|
||||
<div><input name="email" placeholder="Email" style="width:100%;padding:.6rem;margin:.25rem 0"></div>
|
||||
<div><input name="telefono" placeholder="Teléfono" style="width:100%;padding:.6rem;margin:.25rem 0"></div>
|
||||
<div><textarea name="mensaje" placeholder="Mensaje" rows="4" style="width:100%;padding:.6rem;margin:.25rem 0"></textarea></div>
|
||||
<button class="btn">Enviar</button>
|
||||
</form>
|
||||
|
||||
<!-- Bloques zona=footer -->
|
||||
<?php if(!empty($bloques['footer'])): foreach($bloques['footer'] as $b): ?>
|
||||
<?php if($b['tipo']==='html') echo $b['contenido']; ?>
|
||||
<?php endforeach; endif; ?>
|
||||
</main>
|
||||
|
||||
<script>
|
||||
// registra conversión al enviar (fire-and-forget)
|
||||
function lpConv(){
|
||||
navigator.sendBeacon('landing_track.php', new URLSearchParams({
|
||||
landing_id: '<?= (int)$landing_id ?>',
|
||||
variant_id: '<?= (int)($variant['id'] ?? 0) ?>',
|
||||
event_type: 'conversion',
|
||||
session_id: '<?= htmlspecialchars($session_id) ?>'
|
||||
}));
|
||||
}
|
||||
<?= $js ?>
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user