Skip to content

How to Create a Live Sports Data Billboard

This guide walks through creating a digital billboard that displays live sports data — betting odds, live game scores, or game status. These creatives update in real time as the data changes, making them highly relevant during game-day windows.


Prerequisites

  • A Lucit account with access to the Template Designer
  • A live sports data source (odds API, scores API, or a regularly updated spreadsheet)
  • Familiarity with the Template Designer canvas
  • For sports betting creatives: geo rules configured to target only screens in legal sports betting states

Compliance Note: Sports betting advertising is regulated at the state level. Configure geo rules to suppress betting-specific creative (odds, "Bet Now" CTAs, spread messaging) in states where sports betting is not legal. A general brand awareness creative should serve in non-permitted states.


What You'll Build

This guide covers three variations:

  1. Live Betting Odds Display — Shows current spread, moneyline, and over/under for a game
  2. Live Score Ticker — Shows current score and game status (quarter, period, half)
  3. Game Phase Creative — Switches creative content based on whether the game is pre-game, in-game, halftime, or post-game

Architecture Overview

Live sports data billboards require an external data feed connected to Lucit. The creative template reads from this feed every time it renders.

Two supported feed approaches:

  1. Google Sheets (recommended for simpler setups): Manually or automatically update a Google Sheet with current odds/scores. The template reads from the sheet. Refresh interval depends on how often the sheet is updated.

  2. API-Connected Feed (advanced): A server-side integration pulls from a live sports data API (e.g., The Odds API, Sportradar, StatMuse) and writes to a format readable by Lucit templates. Enables true real-time data.


Variation 1: Betting Odds Display

Step 1: Set Up Your Data Source

Create a Google Sheet with the following columns:

Column Description Example
home_team Home team name or abbreviation Chiefs
away_team Away team name or abbreviation Eagles
spread_home Home team spread -3.5
spread_away Away team spread +3.5
over_under Game total 49.5
moneyline_home Home moneyline -175
moneyline_away Away moneyline +145
game_time Kickoff time 6:30 PM ET
is_active Whether to show this game true

Connect this sheet to your template using the Google Sheets app in Lucit: 1. Go to Apps & Data → ADD NEW 2. Select Google Sheets 3. Authorize and paste your Sheet ID 4. Map the column names to data variables in the template


Step 2: Build the Creative Template

Design a template with text elements for each data point. Suggested layout:

[GAME TIME]          [SPONSOR LOGO]
[AWAY TEAM]  vs.  [HOME TEAM]
[AWAY SPREAD]     [HOME SPREAD]
O/U: [OVER_UNDER]

Give each text element an ID matching its data variable: - #game-time - #home-team, #away-team - #spread-home, #spread-away - #over-under


Step 3: Add Odds Formatting JavaScript

Use a registerDesignerFunction to format the spread value with a + prefix where appropriate:

registerDesignerFunction('formatSpread', function(params, data) {
  // params[0] = the raw spread value (e.g., "-3.5" or "3.5")
  var spread = params[0];

  if (!spread || spread === '') {
    return 'EVEN';
  }

  var num = parseFloat(spread);

  if (isNaN(num)) {
    return spread;
  }

  if (num > 0) {
    return '+' + num.toFixed(1);
  } else {
    return num.toFixed(1);
  }
});
registerDesignerFunction('formatMoneyline', function(params, data) {
  // params[0] = the raw moneyline value (e.g., "-175" or "145")
  var ml = params[0];

  if (!ml || ml === '') {
    return '';
  }

  var num = parseInt(ml);

  if (isNaN(num)) {
    return ml;
  }

  if (num > 0) {
    return '+' + num;
  } else {
    return '' + num;
  }
});

Connect each function to the appropriate text element via its Custom Field selector.


Variation 2: Live Score Ticker

Step 1: Data Source Setup

Create a Google Sheet with scoring columns. Update this sheet during the game (manually, or via an automated integration):

Column Description Example
home_team Home team Chiefs
away_team Away team Eagles
home_score Home team score 17
away_score Away team score 14
game_period Period/quarter/half Q3
clock Game clock remaining 4:22
game_status Status in-progress / halftime / final

Step 2: Score Display JavaScript

registerDesignerFunction('getScoreDisplay', function(params, data) {
  // Reads from data object — field names match Google Sheet column headers
  var homeScore = data['home_score'] || '0';
  var awayScore = data['away_score'] || '0';
  var period = data['game_period'] || '';
  var clock = data['clock'] || '';
  var status = data['game_status'] || '';

  if (status === 'final') {
    return 'FINAL';
  }

  if (status === 'halftime') {
    return 'HALFTIME';
  }

  if (status === 'pre-game') {
    return 'Kickoff Coming Up';
  }

  // Build period + clock display
  if (clock && period) {
    return period + '  ' + clock;
  }

  return period || 'In Progress';
});
registerDesignerFunction('getScoreString', function(params, data) {
  var home = data['home_score'] || '0';
  var away = data['away_score'] || '0';
  var homeTeam = data['home_team'] || 'Home';
  var awayTeam = data['away_team'] || 'Away';

  return awayTeam + '  ' + away + '  –  ' + home + '  ' + homeTeam;
});

Variation 3: Game Phase Creative Switcher

This is the most sophisticated pattern — the creative changes its entire messaging approach based on which phase of game day it is.

registerDesignerFormattingFunction(
  'applyGamePhaseCreative',
  function(element, dataValue, dataObject, elementSettings, cssSelector) {
    var gameStatus = dataObject['game_status'] || 'pre-game';
    var homeTeam = dataObject['home_team'] || 'Home';
    var awayTeam = dataObject['away_team'] || 'Away';
    var homeScore = dataObject['home_score'] || '0';
    var awayScore = dataObject['away_score'] || '0';
    var kickoffTime = dataObject['game_time'] || 'Tonight';

    var doc = element.ownerDocument;

    // Target the headline element
    var headline = doc.querySelector('#game-headline');
    if (!headline) return;

    if (gameStatus === 'pre-game') {
      headline.textContent = awayTeam + ' at ' + homeTeam + ' — Kickoff ' + kickoffTime;
      headline.style.color = '#ffffff';
    }

    else if (gameStatus === 'in-progress') {
      headline.textContent = awayTeam + ' ' + awayScore + ' – ' + homeScore + ' ' + homeTeam;
      headline.style.color = '#ffff00';  // yellow for live
    }

    else if (gameStatus === 'halftime') {
      headline.textContent = 'HALFTIME: ' + awayTeam + ' ' + awayScore + ' – ' + homeScore + ' ' + homeTeam;
      headline.style.color = '#ff6600';  // orange for halftime
    }

    else if (gameStatus === 'final') {
      var winner = parseInt(homeScore) > parseInt(awayScore) ? homeTeam : awayTeam;
      headline.textContent = 'FINAL: ' + winner + ' wins! ' + awayScore + ' – ' + homeScore;
      headline.style.color = '#00ff88';  // green for final
    }
  },
  ['game_status', 'home_team', 'away_team', 'home_score', 'away_score', 'game_time']
);

Geo Rules for Betting Compliance

For any creative that displays odds, spreads, or betting CTAs:

  1. Go to your Campaign → Screen Rules
  2. Add a State geo rule: include only states where sports betting is legal in your campaign window
  3. Create a second creative (general brand awareness) with no betting content
  4. Apply that secondary creative to screens in non-legal states

This setup ensures compliance without requiring manual screen-by-screen management.