How to Create Day & Night Time-of-Day Creatives¶
A time-of-day billboard creative automatically changes its messaging based on the time of day — showing a morning breakfast promotion in the AM, a lunch deal at midday, and an evening entertainment message at night. The most sophisticated version uses actual sunrise and sunset times for the screen's location, creating a natural environmental alignment rather than fixed hour cutoffs.
Prerequisites¶
- A Lucit account with access to the Template Designer
- Familiarity with the Template Designer canvas and JavaScript tab
- For sunrise/sunset approach: the screen's latitude and longitude (automatically available from screen location)
What You'll Build¶
This guide covers three patterns:
- Fixed Hour Splits — Simple AM/PM or morning/afternoon/evening splits based on clock time
- Sunrise/Sunset Aware — Creative switches based on actual astronomical sunrise and sunset for the screen's location
- Multi-Daypart with Product Rotation — Different products or messages per daypart, fully automated
Pattern 1: Fixed Hour Splits (Simplest)¶
This approach divides the day into time windows based on clock hour and serves different creative content per window.
JavaScript¶
registerDesignerFunction('getDaypartMessage', function(params, data) {
// =====================================================
// CONFIGURATION
// =====================================================
// Define time windows and messages
// Hours in 24-hour format (0 = midnight, 12 = noon, 23 = 11 PM)
var DAYPARTS = [
{ startHour: 5, endHour: 10, message: 'Start your morning with [Brand]' },
{ startHour: 10, endHour: 14, message: 'Lunch time — [Brand] has you covered' },
{ startHour: 14, endHour: 18, message: 'Afternoon pick-me-up — [Brand]' },
{ startHour: 18, endHour: 22, message: 'End your day the right way — [Brand]' },
{ startHour: 22, endHour: 24, message: '[Brand] — Late night, great choice' },
{ startHour: 0, endHour: 5, message: '[Brand] — Always open' }
];
// =====================================================
var now = new Date();
var currentHour = now.getHours();
for (var i = 0; i < DAYPARTS.length; i++) {
var part = DAYPARTS[i];
if (currentHour >= part.startHour && currentHour < part.endHour) {
return part.message;
}
}
return '[Brand]'; // fallback
});
How to Use¶
- Open the JS tab in your template's Code Editor
- Paste the function above, editing the messages and hours to fit your brand
- Select the Text element where the message should appear
- In the Custom Field selector, choose getDaypartMessage
Pattern 2: Sunrise/Sunset Aware Creative¶
This approach computes the actual sunrise and sunset time for the screen's latitude/longitude using astronomical formulas — no external API required.
Rather than switching at a fixed hour (e.g., always at 7 AM), this switches at the actual sunrise time for each day and location. A screen in Phoenix in summer sees a 5:30 AM sunrise; the same screen in winter sees 7:20 AM. The creative adapts automatically.
Why Use This Instead of Fixed Hours¶
- Daylight changes by 2+ hours between winter and summer across the US
- "Morning" and "evening" are experiential and environmental — fixed hours create mismatches
- Advertising a hot coffee at sunset feels right; advertising it after dark feels wrong
- Environmental alignment makes the creative feel more considered and contextual
JavaScript¶
registerDesignerFunction('getDayNightMessage', function(params, data) {
// =====================================================
// CONFIGURATION
// =====================================================
var DAY_MESSAGE = 'Enjoy the sunshine with [Brand]';
var NIGHT_MESSAGE = '[Brand] — Perfect for tonight';
var DAWN_MESSAGE = 'Good morning — [Brand] starts your day';
var DUSK_MESSAGE = 'Golden hour and [Brand] go together';
// Twilight buffer in minutes before sunrise and after sunset
var DAWN_BUFFER_MINUTES = 45;
var DUSK_BUFFER_MINUTES = 45;
// Screen coordinates (auto-populated from Lucit screen data)
var lat = parseFloat(data['digital_board.location.lat']);
var lng = parseFloat(data['digital_board.location.lng']);
// =====================================================
if (isNaN(lat) || isNaN(lng)) {
// Fallback if location unavailable — use simple AM/PM split
var hour = new Date().getHours();
return hour >= 6 && hour < 19 ? DAY_MESSAGE : NIGHT_MESSAGE;
}
var times = getSunriseSunset(lat, lng, new Date());
var now = new Date();
var nowMin = now.getHours() * 60 + now.getMinutes();
var sunriseMin = times.sunrise;
var sunsetMin = times.sunset;
// Dawn window: DAWN_BUFFER_MINUTES before sunrise
if (nowMin >= (sunriseMin - DAWN_BUFFER_MINUTES) && nowMin < sunriseMin) {
return DAWN_MESSAGE;
}
// Day window: after sunrise, before sunset
if (nowMin >= sunriseMin && nowMin < sunsetMin) {
return DAY_MESSAGE;
}
// Dusk window: DUSK_BUFFER_MINUTES after sunset
if (nowMin >= sunsetMin && nowMin < (sunsetMin + DUSK_BUFFER_MINUTES)) {
return DUSK_MESSAGE;
}
// Night: after dusk window
return NIGHT_MESSAGE;
});
// =====================================================
// Sunrise/Sunset calculation (Julian Day / NOAA formula)
// Returns { sunrise: minutesSinceMidnight, sunset: minutesSinceMidnight }
// =====================================================
function getSunriseSunset(lat, lng, date) {
var RAD = Math.PI / 180;
var DEG = 180 / Math.PI;
var dayOfYear = getDayOfYear(date);
var b = (360 / 365) * (dayOfYear - 81) * RAD;
var eqTime = 9.87 * Math.sin(2 * b) - 7.53 * Math.cos(b) - 1.5 * Math.sin(b);
var decl = 23.45 * Math.sin(b) * RAD;
var latRad = lat * RAD;
var cosCosHourAngle = -Math.tan(latRad) * Math.tan(decl);
// Clamp to [-1, 1] to handle polar extremes
cosCosHourAngle = Math.max(-1, Math.min(1, cosCosHourAngle));
var hourAngle = Math.acos(cosCosHourAngle) * DEG;
var solarNoon = 720 - 4 * lng - eqTime;
var sunriseMin = solarNoon - 4 * hourAngle;
var sunsetMin = solarNoon + 4 * hourAngle;
// Adjust for timezone offset
var tzOffset = -date.getTimezoneOffset();
sunriseMin += tzOffset;
sunsetMin += tzOffset;
return {
sunrise: Math.round(sunriseMin),
sunset: Math.round(sunsetMin)
};
}
function getDayOfYear(date) {
var start = new Date(date.getFullYear(), 0, 0);
var diff = date - start;
return Math.floor(diff / 86400000);
}
Pattern 3: Multi-Daypart Product Rotation¶
For brands with different products at different times of day (coffee, QSR, spirits), this pattern maps a product image and message to each time window.
registerDesignerFunction('getDaypartProduct', function(params, data) {
// =====================================================
// CONFIGURATION — Map dayparts to product keys
// The key becomes the data-value — connect it to a
// Custom Field or use it to select from a data source
// =====================================================
var DAYPARTS = [
{ startHour: 5, endHour: 10, product: 'morning-coffee', label: 'Start your day' },
{ startHour: 10, endHour: 14, product: 'lunch-sandwich', label: 'Lunch is ready' },
{ startHour: 14, endHour: 17, product: 'afternoon-snack', label: 'Afternoon snack' },
{ startHour: 17, endHour: 21, product: 'dinner-special', label: 'Dinner\'s on us' },
{ startHour: 21, endHour: 24, product: 'evening-dessert', label: 'End it sweet' },
{ startHour: 0, endHour: 5, product: 'late-night-special', label: 'Night owl special' }
];
// =====================================================
// params[0] = 'product' or 'label' — which value to return
var returnType = params[0] || 'label';
var now = new Date();
var currentHour = now.getHours();
for (var i = 0; i < DAYPARTS.length; i++) {
var part = DAYPARTS[i];
if (currentHour >= part.startHour && currentHour < part.endHour) {
return returnType === 'product' ? part.product : part.label;
}
}
return returnType === 'product' ? 'default-product' : '[Brand]';
});
How to use params[0]:
- Create one Custom Field calling getDaypartProduct with param product → use as image selector
- Create another calling getDaypartProduct with param label → display as text
Combining Day/Night with a Countdown¶
For the most sophisticated approach, combine a time-of-day split with a countdown — for example:
- Morning: "Christmas is 12 Days Away — Start shopping with [Brand]"
- Evening: "12 Days Until Christmas — Treat them tonight at [Brand]"
registerDesignerFunction('getDaypartCountdown', function(params, data) {
var TARGET_DATE_STR = '2025-12-25T00:00:00';
var now = new Date();
var target = new Date(TARGET_DATE_STR);
var diff = target - now;
var days = diff > 0 ? Math.floor(diff / 86400000) : 0;
var countdownStr = days > 0 ? days + ' days until Christmas' : 'Merry Christmas!';
var hour = now.getHours();
var isDay = hour >= 7 && hour < 19;
if (diff <= 0) {
return 'Merry Christmas from [Brand]!';
}
if (isDay) {
return countdownStr + ' — Time to shop [Brand]';
} else {
return countdownStr + ' — Celebrate tonight with [Brand]';
}
});
Related Guides¶
- How to Create a Countdown Ad — Standalone countdown guide
- JavaScript Guide — Full function reference
- Holiday Season Campaigns — Day/night holiday campaign ideas
- Food, Beverage & CPG — Dayparting for beverage brands
- QSR & Restaurant campaigns — Daypart menu promotions