💾Widget builder docs

Program custom widgets through the KickBot widget builder. Use HTML, CSS, and Javascript to build anything you can dream of. Easily integrate with stream events through the KickBot library.

Before you get started

The KickBot widget builder is an advanced tool that requires some basic programming knowledge. If you are looking to use already made widgets, check out the widget library.

Creating a new widget

Once you have navigated to the widget builder page, the first step is creating a new widget. You can either create a widget from a blank template, or you can start from an existing preset. Starting from an existing preset is a great way to get started and an easy starting point if you want to create something similar.

Widget builder sidebar

The left sidebar of the widget builder controls a few different aspects of the widget.

Basic settings

Name - The name of the widget

Dimensions - The pixel dimensions that the widget will be displayed as. It is recommended to use the default 800x600px resolution unless your widget benefits from a different size.

User variables

Custom variables that the end user can adjust without needing to interact with the code. These can be accessed through userVariable.variable_name.value in your Javascript. As a widget developer there are several fields to configure when creating a variable: Title - The name of this field that is displayed to the end user.

Variable name - The name of the variable that you use in your code. No spaces or special characters allowed.

Tooltip - Extra information that should be shown to the user via a tooltip that appears when hovered over.

Variable type - The type of input for this variable. Options are text, number, color, dropdown, toggle, image/GIF, video, and audio. Do note that image, video, and audio values will return a URL to the media that is hosted in our storage.

Default value - The default value of this variable, this can be empty.

Required - Is the user required to enter a value.

Send test events

Send test events to your widget to simulate stream events. These events have the same structure as actual events but may use fake data.

Code editor

This code editor gives you full control over the HTML, CSS, and Javascript of the widget. This code will be run in a sandboxed environment, so you may not have access to some advanced browser functionality. You can move and resize this editor, or change the layout with the buttons on the top right.

Preview

The preview shows a realtime view of your widget. This automatically reloads based on code updates and is rendered in the resolution you defined for your widget, although it may be at a different scale. You also have the option to reload the preview, or pop out the widget into a new browser window.

TIP: To view the console of your widget, pop out the preview and inspect the new tab.

Events

You can easily listen to events through our simplified event system. Through a single event listener you are able to receive all relevant events from a stream such as chat messages, sub, follows, viewer count updates, raids, and more.

Example event usage

document.addEventListener('widgetEvent', handleWidgetEvent);

const eventHandlers = {
    followEvent: function(event) {
        updateFollowerGoal(event.data.followers_count);
    },
    unfollowEvent: function(event) {
        updateFollowerGoal(event.data.followers_count);
    },
    followerCountUpdatedEvent: function(event) {
        updateFollowerGoal(event.data.followersCount);
    }
};

function handleWidgetEvent(event) {
    const eventName = event.detail.event_name;
    if (eventHandlers[eventName]) {
        eventHandlers[eventName](event.detail);
    }
}

function updateFollowerGoal(followersCount) {
    const progressBar = document.getElementById('progress-bar');
    const currentFollowersElem = document.getElementById('current-followers');
      let goalFollowers = userVariables.follower_goal.value;

    currentFollowersElem.textContent = followersCount;
    const progressPercent = (followersCount / goalFollowers) * 100;
    progressBar.style.width = `${Math.min(progressPercent, 100)}%`;
}

Event examples

subEvent

{
    event_name: 'subEvent',
    source: 'kick',
    data: {
	months: 1,
	username: 'henryk89',
	chatroom_id: 3847194
    }
}

subGiftEvent

{
    event_name: 'subGiftEvent',
    source: 'kick',
    data: {
	chatroom_id: 1,
	gifted_usernames: ['henryk89', 'KickBot', 'AdinRoss'],
	gifter_username: 'Eddie'
    }
}

followEvent

{
    event_name: 'followEvent',
    source: 'kick',
    data: {
	id: 'd4e5f6a7-89b0-12c3-d456-78901e2f3a4b',
	channel: { id: 3984507, slug: 'henryk89' },
	user: { id: 14873539, slug: 'henryalt89', username: 'henryalt89' },
        followers_count: 36,
        created_at: '2024-05-13T22:19:07+00:00'
    }
}

unfollowEvent

{
    event_name: 'unfollowEvent',
    source: 'kick',
    data: {
        id: 'f746861e-1114-43eb-b079-a1e119c8becd',
	channel: { id: 3984507, slug: 'henryk89' },
	user: { id: 14873539, slug: 'henryalt89', username: 'henryalt89' },
	followers_count: 35,
	created_at: '2024-05-13T22:26:45+00:00'
    }
}

chatMessageEvent

{
    event_name: 'chatMessageEvent',
    source: 'kick',
    data: {
	id: '85c884b3-7377-478c-b6aa-22b7db752b93',
	chatroom_id: 3974112,
	content: 'test',
	type: 'message',
	created_at: '2024-05-13T22:29:52+00:00',
	sender: {
		id: 4063326,
		username: 'henryk89',
		slug: 'henryk89',
		identity: {
			color: '#72ACED',
			badges: [{ type: 'broadcaster', text: 'Broadcaster' }]
		}
	}
    }
}

chatMessageDeletedEvent

{
    event_name: 'chatMessageDeletedEvent',
    source: 'kick',
    data: {
	id: '9cd3788a-ecd2-4051-a162-a7ea9be8ce7a',
	message: { id: '89d6be86-63db-4581-922e-14a6c4a9c2e6' }
    }
}

chatMessagePinnedEvent

{
    event_name: 'chatMessagePinnedEvent',
    source: 'kick',
    data: {
	message: {
		id: '5d798a38-ad17-45e4-8169-bda2faa85b79',
		chatroom_id: 3974112,
		content: 'This is a pinned message!',
		type: 'message',
		created_at: '2024-05-13T22:30:41+00:00',
		sender: {
			id: 4063326,
			username: 'henryk89',
			slug: 'henryk89',
			identity: {
				color: '#72ACED',
				badges: [{ type: 'broadcaster', text: 'Broadcaster' }]
			}
		}
	}
    }
}

chatClearedEvent

{
    event_name: 'chatClearedEvent',
    source: 'kick',
    data: {
	id: '47e3596f-0274-46e0-85b1-029fa3bfc5ea'
    }
}

followerCountUpdatedEvent

{
    event_name: 'followerCountUpdatedEvent',
    source: 'kick',
    data: {
	followersCount: 252545,
	channel_id: 4599,
	created_at: 1715639984
    }
}

viewerCountUpdatedEvent

{
    event_name: 'viewerCountUpdatedEvent',
    source: 'kick',
    data: {
	id: 28346454,
	viewer_count: 3204,
	channel_id: 5937485
    }
}

raidEvent

{
    event_name: 'raidEvent',
    source: 'kick',
    data: {
        chatroom_id: 839485,
	optional_message: 'pog stream',
	number_viewers: 19384,
	host_username: 'xQc'
    }
}

streamOnline

{
    event_name: 'streamOnline',
    source: 'kick',
    data: {
 	livestream: {
            id: 3984507,
	    channel_id: 3984507,
	    session_title: 'Test stream!',
	    created_at: '2024-05-13T22:30:41+00:00'
        }
    }
}

streamOffline

{
    event_name: 'streamOnline',
    source: 'kick',
    data: {
	livestream: {
		id: 3984507,
		channel: {
			id: 3984507,
			is_banned: false
		}
	}
    }
}

Global values

Global values provide you with information relevant to the streamer and stream. These values are automatically updated based on events, giving you an easily accessible global state for things like the current follower count. These values are initialized on page load, allowing you to populate your widget before any events are received. These can be accessed in Javascript through globalValues.valueName Values such as lastFollower, lastSub, lastGiftedSub, and chatMessages are set to that value's recent event(s).

globalValues = {
	followerCount: 8,
	viewerCount: 4,
	lastFollower: {},
	lastSub: {},
	lastGiftedSub: {},
	chatMessages: [],
	streamerInfo: {
		kick: {
			username: 'henryk89',
			slug: 'henryk89',
			profile_picture: 'https://files.kick.com/images/user/4063326/profile_image/conversion/9a52aab8-71ed-4434-bc8b-1f7ae450bfb3-fullsize.webp',
			user_id: '4063326',
			channel_id: '3984507',
			chatroom_id: '3974112',
			bio: 'Developer of KickBot (kickbot.app). Contact me on Discord @ henry.',
			subscriber_badges: []
		}
	},
	currentStream: {
		is_live: false,
		title: '',
		started_at: ''
	}
}

Example widget

An example follow goal widget is shown below. This widget uses events, global values, and user variables. This widget is available in the widget library and as a template when creating a new widget with the name "Simple follower goal".

HTML

<div class="follower-goal-widget">
    <div class="goal-text"><span id="follower-goal-text"></span> <span id="current-followers"></span>/<span id="goal-followers"></span></div>
    <div class="progress-bar">
        <div class="progress"></div>
    </div>
</div>

CSS

:root {
    --background-color: #100c28;
    --outline-color: #fff;
    --text-color: #fff;
    --bar-background-color: #3d3957;
    --bar-color: #57ee00;
    --text-size: 42px;
    --border-radius: 25px;
    --progress-height: 42px;
}

body {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
    font-family: Arial, sans-serif;
    background: #121212;
}

.follower-goal-widget {
    width: 98%;
    font-weight: bold;
    background-color: var(--background-color);
    border: 3px solid var(--outline-color);
    border-radius: var(--border-radius);
    padding: 12px;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.goal-text {
    color: var(--text-color);
    font-size: var(--text-size);
    white-space: nowrap;
    margin-right: 16px;
    padding-left: 8px;
}

.progress-bar {
    background-color: var(--bar-background-color);
    border-radius: var(--border-radius);
    overflow: hidden;
    flex-grow: 1;
    height: var(--progress-height);
    padding-right: 4px;
}

.progress {
    background-color: var(--bar-color);
    height: 100%;
    width: 0;
    transition: width 0.3s ease;
    border-radius: var(--border-radius);
}

Javascript

document.addEventListener('widgetEvent', handleWidgetEvent);

const eventHandlers = {
    followEvent: function(event) {
        updateFollowerGoal(event.data.followers_count);
    },
    unfollowEvent: function(event) {
        updateFollowerGoal(event.data.followers_count);
    },
    followerCountUpdatedEvent: function(event) {
        updateFollowerGoal(event.data.followersCount);
    }
};

function handleWidgetEvent(event) {
    const eventName = event.detail.event_name;
    if (eventHandlers[eventName]) {
        eventHandlers[eventName](event.detail);
    }
}

function updateFollowerGoal(followersCount) {
    const followerGoalTextElem = document.getElementById('follower-goal-text');
    const progressElem = document.querySelector('.progress');
    const currentFollowersElem = document.getElementById('current-followers');
    let goalFollowers = userVariables.follower_goal.value;

    document.documentElement.style.setProperty('--outline-color', userVariables.outline_color.value);
    document.documentElement.style.setProperty('--background-color', userVariables.background_color.value);
    document.documentElement.style.setProperty('--text-color', userVariables.text_color.value);
    document.documentElement.style.setProperty('--bar-background-color', userVariables.bar_background_color.value);
    document.documentElement.style.setProperty('--bar-color', userVariables.bar_color.value);

    followerGoalTextElem.textContent = userVariables.follower_goal_text.value;
    currentFollowersElem.textContent = followersCount;
    const progressPercent = (followersCount / goalFollowers) * 100;
    progressElem.style.width = `${Math.min(progressPercent, 100)}%`;
}

// Initialize widget with global values and user variables
const goalFollowersElem = document.getElementById('goal-followers');
goalFollowersElem.textContent = userVariables.follower_goal.value;
updateFollowerGoal(globalValues.followerCount);

Last updated