Skip to main content

How to Build a Customer Call (Queue) Display

Completion Time: 45 minutes

This guide shows you how to build a ticket-calling display: a large panel shows the customer being called now, and a table below lists the last few tickets. In a demo, a button adds new tickets. In production, your ticket kiosks add them through a webhook.

How it works​

PartWhat it does
Internal datasourceHolds the queue as a list of tickets
Table Widget (5 rows)Shows the newest tickets
Table Widget (1 row)Shows only the newest ticket, as the featured "now calling" panel
Button (demo)Adds a random ticket with an action batch
Webhook (production)Lets each kiosk add a ticket from outside Wallboard

Both tables read the same list, sorted newest first. When a ticket is added, both tables show it without any extra setup. ❓ Confirm how quickly the change reaches a device that did not make it (the Notion notes say sub-second, over WebSocket).

Step 1: Create the queue datasource​

  1. Go to Datasources and click Add internal datasource.
  2. Set Structure type to Custom.
  3. Enter the queue as a list. Seed it with about ten tickets, so the demo has something to show from the start:
{
"customer_queue": [
{ "customer_number": "001", "kiosk_number": 1, "timestamp": "2026-04-22T14:02:15Z" },
{ "customer_number": "002", "kiosk_number": 3, "timestamp": "2026-04-22T14:03:40Z" }
]
}
  1. Turn on Allow displays to update data.
  2. Save.
Allow displays to update data

The button in Step 4 runs on the display. Without Allow displays to update data, the server rejects every insert and nothing happens on the screen.

Learn more: Internal Custom Datasources

Step 2: Add the queue table​

  1. Add a Table Widget and bind it to the queue datasource. Select the customer_queue list, so each ticket becomes a row.
  2. Choose the columns: customer_number, kiosk_number and timestamp. Rename the headers as you like, for example Ticket, Desk and Time.
  3. In the data picker, open Table level settings:
    • Order: set Column to timestamp and switch the order to descending with the Change order type button.
    • Limit: set Only display to 5.

Learn more: Table Widget

  1. Duplicate the queue table.
  2. In the copy, set Only display to 1.
  3. Make it large and style it as the featured panel.

Because the copy is sorted newest first and shows one row, it always shows the most recent ticket. There is nothing to rebind when new tickets arrive.

Step 4: Add a "Call new customer" button (demo)​

For a demo, a button creates a random ticket and inserts it at the top of the queue.

  1. Add a button, select it, and open Edit touch events on its Other tab.
  2. Add the action Execute action batch:
    • Actions origin: Local
    • Sent fields: add one field. Set its type to Call function, its Name to receivedData, and its Value to this function:
(receivedValue) => {
const customer_number = String(Math.floor(Math.random() * 999) + 1).padStart(3, '0');
const kiosk_number = Math.floor(Math.random() * 4) + 1;
const timestamp = new Date().toISOString().split('.')[0] + 'Z';
return { customer_number, kiosk_number, timestamp };
}
  1. Inside the batch, add the action Insert to internal datasource array:
FieldValue
DatasourceYour queue datasource, with customer_queue selected
Index0 (insert at the top)
Max element countEmpty, or a cap such as 50 (see below)
Rotate enabledOn, if you set a cap
Value originProperty of received value
Value property namereceivedData
Max element count without Rotate enabled stops the queue

Max element count on its own does not trim the list. When the list is full, new tickets are silently skipped. Turn on Rotate enabled as well: with Index 0, the oldest tickets are then dropped from the end, and the list keeps the newest ones.

❓ Call function values are blocked in sessions where custom scripts are not allowed. Confirm that this does not affect a normal device.

Learn more: Sent Fields Explained

Learn more: Insert To Array

Step 5: Test​

Open the Content in preview and click the button. The new ticket appears at the top of the table and in the featured panel at the same time.

Going live: tickets from the kiosks​

In production, the button is replaced by the ticket kiosks themselves. Each kiosk calls a Wallboard webhook when a customer takes a ticket, and the webhook inserts the ticket into the same list.

  1. Go to the Integration menu, open the API Keys tab, and click Add API key.
  2. Open the Actions tab and click Add action. Give it an Event ID and choose the action type Insert to internal datasource array. Select the queue datasource and the customer_queue list, and set Index, Max element count and Rotate as in Step 4.
  3. Use Generate example link (with Copy link) or Test to check the action, then give the kiosk vendor the webhook address, the API key and the Event ID.
  4. The kiosk sends the new ticket in the data field of the request, for example:
{
"eventId": "new-ticket",
"data": { "customer_number": "043", "kiosk_number": 2, "timestamp": "2026-04-22T14:05:02Z" }
}

The request can also send index, maxElementCount and rotateEnabled; when it does, they override the action's own settings.

❓ The webhook is authenticated by the API key, not by a display, so Allow displays to update data should not be needed for this path. Confirm before telling a customer they can turn it off.

Learn more: Datasource actions

Learn more: API keys

Serving the next customer​

A second button (for example on a clerk's tablet) can take a ticket off the list with the action Remove from internal datasource array. Set Index to the position to remove. With an empty Index, the last item in the list is removed, which is the oldest ticket when new tickets are inserted at 0.

Learn more: Remove From Array

Where should the data live?​

This example keeps the queue in Wallboard. That is one of two ways to connect a queue system:

The queue lives in…How it worksChoose it when
Wallboard (this guide)The kiosk system calls Wallboard's webhook and pushes each new ticket into an internal datasourceThe kiosks can send an HTTP request, and Wallboard only needs to display the queue
The external systemWallboard reads the queue from the system's own API, for example as a JSON datasource, or sends changes to itThe queue system already holds the data, or other systems also need to change it

Decide which system owns the source of truth before you build: whether the external system already has the data, and whether Wallboard only shows the queue or also changes it.