Extending Daily Prebuilt video calls with a custom button


At Daily, our mission is to help developers build flexible, scalable WebRTC video call functionality into their applications. We offer a range of solutions for this, from our fully customizable Client SDK to Daily Prebuilt, which you can include in your application with just a few lines of code.

Quite often, our customers opt for something in the middle: the ease of Daily Prebuilt with a bit of custom functionality on top. There are numerous events and instance methods that developers can utilize to extend their Daily-powered video application to fit their needs.

While we have comprehensive styling options for Daily Prebuilt, developers have expressed that it can still be a little challenging to match the style of the surrounding UI to the embedded UI of Prebuilt. They want to be able to add custom controls to the embedded call frame itself as opposed to just outside of it.

Our new custom button feature, which allows developers to add custom controls within their Daily Prebuilt call frame, allows Daily devs to do just that!

In this post, we'll go through an example of a use case for the custom Daily Prebuilt button by converting our Electron virtual backgrounds demo from using an application menu to a fancy new integrated button.

What we're building

A few weeks ago, we posted a tutorial on extending our Electron application built with Daily Prebuilt with custom virtual backgrounds. At that time, we used a top level application menu item to open the background selection window:

Setting a custom background in a Daily video call through an application menu item
Setting a custom background in a Daily video call through an application menu item

In this tutorial, we'll walk through converting this UI to instead use a seamlessly integrated button in the Prebuilt call frame itself:

Setting a custom background in a Daily video call through a custom Daily Prebuilt button
Setting a custom background in a Daily video call through a custom Daily Prebuilt button

By including our own button alongside the rest of the call frame controls, we can offer users a more cohesive experience instead of forcing them into a separate menu flow to use our custom functionality.

Getting started

If you haven't read our previous post about extending a Daily Prebuilt Electron app with custom virtual backgrounds, we recommend you do so as it covers the initial addition of the virtual backgrounds feature which we'll be discussing here.

To run the demo locally, create a free Daily account and a room.

Next, clone the demo repository and check out the relevant tag:

git clone git@github.com:daily-demos/electron-prebuilt.git
cd electron-prebuilt
git checkout v2.0

In renderer/call/daily.js, replace the placeholder room URL with that of the room you just created.

Finally, install relevant dependencies and run the app:

npm i && npm run start

How to add a custom button to Daily Prebuilt

At the root of the button is a new customTrayButtons property set as part of the call to createFrame(), which is the function used to create the call frame. This property allows us to add a new button with its own icon, label, and tooltip to the call frame as follows:

  callFrame = DailyIframe.createFrame(container, {
    showLeaveButton: true,
    // Specify a custom button for background controls
    customTrayButtons: {
      backgrounds: {
        iconPath: url.href,
        label: "Background",
        tooltip: "Set Custom Background",

But how do we have it actually... do something?

This is where the new "custom-button-click" event comes in. We add a handler for this new event to the call frame:

    callFrame.on("custom-button-click", (ev) => {
      // If the event is triggered by clicking
      // our background button, show the
      // background selection window
      if (ev.button_id === "backgrounds") {

Above, when the custom button with the ID of "background" is clicked, we call our api.tryEnableBackground() method. This method opens our background selection window, enabling the user to set their background. We covered the details of this method in our previous tutorial about this feature.

Fun fact: custom buttons are responsive with the rest of the Daily Prebuilt UI. In smaller call frame windows, our new button automatically gets collapsed into the “More” menu in the bottom right hand corner.
Custom buttons being hidden on window resize
Custom buttons being hidden on window resize

With these two elements, we can go ahead and rip out our old menu from the Electron main process! You can check out the full diff of this change to see exactly what we removed.

All we need in the main process now is a boolean which is toggled when the background selection window is opened or closed:

// Whether the backgrounds window is open
let backgroundsWindowOpen = false;

function createBackgroundSelectionWindow() {
  if (backgroundsWindowOpen) return;

  backgroundsWindowOpen = true;
  // ...the rest of the window creation function here...
  win.on("close", () => {
    backgroundsWindowOpen = false;

The above prevents duplicate instances of the background selection windows from being created.

And just like that, with a small code refactor, we've gone from an external dropdown menu for our custom functionality to a fully integrated button that is cohesive with the rest of the call frame.

Custom "Background" button in Daily Prebuilt
Custom "Background" button in Daily Prebuilt

What about conditional buttons?

For this demo, we wanted to unconditionally show our custom virtual backgrounds button for participants. Our new custom button feature also supports more conditional use cases, though. You can retrieve existing custom buttons via the customTrayButtons() call frame instance method, and update them by using the updateCustomTrayButtons() method.

Note that custom buttons are only shown once the user has joined the call. They cannot be used in the Daily Prebuilt prejoin UI.

Wrapping up

We hope you enjoy experimenting with our new custom button beta feature. Please contact us with any questions or feedback on our custom Daily Prebuilt button.

Never miss a story

Get the latest direct to your inbox.