This will add the countdown timer and the redirect scripts to any (existing) landing page in Kajabi. This is the page with your time sensitive bonus offer.
<style>
/* Timeline countdown timer code for Kajabi landing pages */
#timer-table {
width: 100%;
border-collapse: collapse;
}
#timer-table td {
text-align: center;
padding: 0px;
}
#timer-table .timer-cell {
font-size: 50px;
font-weight: bold;
}
#timer-table .timer-cell .background-cell {
color: #39d4d4;
background-color: ;
border-radius: 50%;
width: 80px;
height: 80px;
display: flex;
justify-content: center;
align-items: center;
margin: auto;
}
#timer-table .label-cell {
font-size: 12px;
color: #29536b;
}
.timercontainer {padding: 20px; background-color: rgba(255, 255, 255, 0.9);}
.flip-card {
perspective: 1000px;
width: 80px;
height: 80px;
display: inline-block;
}
.flip-card-inner {
position: relative;
width: 100%;
height: 100%;
text-align: center;
transition: transform 0.6s;
transform-style: flat;
transform-origin: center center;
}
.flip-card-front, .flip-card-back {
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
display: flex;
justify-content: center;
align-items: center;
border-radius: 35%;
}
.flip-card-inner.flipped {
transform: rotateX(180deg);
}
</style>
<div id="timer" class="timercontainer">
<table id="timer-table">
<tr>
<td class="timer-cell"><div class="background-cell" id="dagen"></div></td>
<td class="timer-cell"><div class="background-cell" id="uren"></div></td>
<td class="timer-cell"><div class="background-cell" id="minuten"></div></td>
<td class="timer-cell"><div class="background-cell" id="seconden"></div></td>
</tr>
<tr>
<td class="label-cell" kjb-settings-id="sections_timeline_countdown_settings_days">DÍA(S)</td>
<td class="label-cell" kjb-settings-id="sections_timeline_countdown_settings_hours">HORA(S)</td>
<td class="label-cell" kjb-settings-id="sections_timeline_countdown_settings_minutes">MIN(S)</td>
<td class="label-cell" kjb-settings-id="sections_timeline_countdown_settings_seconds">SEG(S)</td>
</tr>
</table>
</div>
<script>
// Timeline script for landing page
function isInTestMode() {
const url = window.location.href;
const isKajabiAdmin = url.includes('app.kajabi.com/admin/themes/');
const previewParam = getQueryParam('preview_theme_id');
const hasPreviewParam = previewParam !== null && previewParam !== undefined && previewParam !== '';
return isKajabiAdmin || hasPreviewParam;
}
function getQueryParam(name) {
const params = new URLSearchParams(window.location.search);
return params.get(name);
}
function setCookie(name, value, days) {
let expires = "";
if (days) {
const date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toUTCString();
}
document.cookie = name + "=" + (value || "") + expires + "; path=/";
}
function getCookie(name) {
const nameEQ = name + "=";
const ca = document.cookie.split(';');
for (let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
}
return null;
}
function updateFlipCard(containerId, value) {
let container = document.getElementById(containerId);
if (!container.querySelector('.flip-card')) {
container.innerHTML = `
<div class="flip-card">
<div class="flip-card-inner">
<div class="flip-card-front"><div class="background-cell">${value}</div></div>
<div class="flip-card-back"><div class="background-cell">${value}</div></div>
</div>
</div>
`;
} else {
const flipCardInner = container.querySelector('.flip-card-inner');
const front = flipCardInner.querySelector('.flip-card-front .background-cell');
const back = flipCardInner.querySelector('.flip-card-back .background-cell');
if (front.innerText != value) {
flipCardInner.classList.add('flipped');
setTimeout(() => {
// Update the front with the new value after the flip animation
front.innerText = value;
flipCardInner.classList.remove('flipped');
// Reset the back's text to be ready for the next flip
back.innerText = front.innerText;
}, 200); // Matches the CSS transition time
}
}
}
const settings = {
setcookie: true,
setcookienumber: "1",
setcookiedays: 90,
tltimeendday: true,
tltimeday: 1,
tltimehour: 0,
tltimemin: 0,
tlenable_end_action: "redirect",
tlaction: "https://www.academiadebranding.net/acabo-oferta-cursoia",
useFlipAnimation: true
};
// Hoofdlogica
const encodedData = getQueryParam('t');
if (encodedData) {
if (settings.setcookie) {
setCookie(`timeline${settings.setcookienumber}`, encodedData, settings.setcookiedays);
}
process(encodedData);
} else {
const cookieData = getCookie(`timeline${settings.setcookienumber}`);
if (cookieData) {
process(cookieData);
} else {
process(null);
}
}
function process(encodedData) {
const isTestMode = isInTestMode(); // Testmode
let tlctmInt;
if (isTestMode) {
const nu = new Date().getTime();
tlctmInt = (settings.tltimeday * 86400000) + (settings.tltimehour * 3600000) + (settings.tltimemin * 60000);
var endday = 0;
if (settings.tltimeendday) {
endday = resterendeTijdTotEindeVanDag(nu);
}
var timeremaining = nu + tlctmInt + endday;
timelineCountdown(timeremaining, settings.useFlipAnimation);
voegResterendeTijdToe(timeremaining);
return;
} else if (encodedData) { // timer found
const tlcdt = encodedData.toString().split("").reverse().join("");
const tlcsomEnd = tlcdt.indexOf("dC");
const tlcsom = parseInt(tlcdt.substring(2, tlcsomEnd), 10);
const tlctmEnd = tlcdt.indexOf("Gt");
const tlctm = tlcdt.substring(tlcsomEnd + 6, tlctmEnd);
const tlctmInt = parseInt(tlctm);
const tlcalsom = [...tlctm].reduce((sum, num) => sum + parseInt(num, 10), 0);
const tlgrt = tlcdt.match(/Hrf(.+?)fU/)?.[1];
const tlgrtl = tlctm.length;
if (tlcdt.indexOf("R1969") !== -1 && tlcdt.indexOf("dC3729") !== -1 && tlcalsom == tlcsom && tlgrt == tlgrtl) {
var extra = settings.tltimeday * 86400000 + settings.tltimehour * 3600000 + settings.tltimemin * 60000;
var endday = 0;
if (settings.tltimeendday) {
endday = resterendeTijdTotEindeVanDag(tlctmInt);
}
var timelineDatum = tlctmInt + extra + endday;
var huidigeTijd = new Date().getTime();
if (timelineDatum > huidigeTijd) { // timer working
window.onload = function() {
timelineCountdown(timelineDatum, settings.useFlipAnimation);
voegResterendeTijdToe(timelineDatum);
};
} else { // timer ended
handleEndAction();
}
} else { // no legit code found
handleEndAction();
}
} else { // no timer at all
handleEndAction();
}
}
function handleEndAction() {
if (settings.tlenable_end_action === "redirect") {
window.location.replace(settings.tlaction);
}
}
function voegResterendeTijdToe(timelineDatum) {
var cardbonusElements = document.getElementsByClassName("cardbonus");
for (var i = 0; i < cardbonusElements.length; i++) {
var linkElement = cardbonusElements[i].querySelector("a.card__button");
if (linkElement) {
var expiratieDatum = new Date(timelineDatum).getTime().toString();
var url = linkElement.getAttribute("href");
var nieuweUrl = url + "?t=" + encodeURIComponent(expiratieDatum);
linkElement.setAttribute("href", nieuweUrl);
}
}
}
function timelineCountdown(enddate, useFlipAnimation) {
var timer = setInterval(function() {
var huidigeTijd = new Date().getTime();
var verschil = parseInt(enddate, 10) - parseInt(huidigeTijd, 10);
if (verschil >= 0) {
var dagen = Math.floor(verschil / (1000 * 60 * 60 * 24));
var uren = Math.floor((verschil % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minuten = Math.floor((verschil % (1000 * 60 * 60)) / (1000 * 60));
var seconden = Math.floor((verschil % (1000 * 60)) / 1000);
// Determine if flip animation should be used
if (useFlipAnimation) {
// Update using flip animation
updateFlipCard("dagen", dagen);
updateFlipCard("uren", uren);
updateFlipCard("minuten", minuten);
updateFlipCard("seconden", seconden);
} else {
// Directly update the numbers without flip animation
document.getElementById("dagen").innerHTML = dagen;
document.getElementById("uren").innerHTML = uren;
document.getElementById("minuten").innerHTML = minuten;
document.getElementById("seconden").innerHTML = seconden;
}
} else {
clearInterval(timer);
const isTestMode = isInTestMode(); // Testmode
if (!isTestMode) {
handleEndAction();
}
}
}, 1000);
}
function resterendeTijdTotEindeVanDag(tijdstempel) {
var eindeVanDag = new Date(tijdstempel);
eindeVanDag.setHours(23, 59, 59, 999);
var now = new Date().getTime();
return eindeVanDag.getTime() - now;
}
var url = window.location.href;
var newUrl = url.split('?')[0];
history.replaceState({}, document.title, newUrl);
</script>