Skip to content

Coming from StreamElements

Import your StreamElements commands as Bloopbot flows, map loyalty, timers and overlays onto Bloopbot, and switch over cleanly.

10 min readUpdated

Before you start

This guide maps what you already built in StreamElements onto the closest thing in Bloopbot. Your commands can come across automatically: see Import your commands. A command is a flow, and what you see in OBS is an overlay you build on its own page — Overlays, separate from the flow canvas, in the same Bloopbot dashboard.

Commands and permissions

StreamElements’ own default commands, such as !points, !raffle and !songrequest, are matched one by one in StreamElements commands and their Bloopbot equivalents.

StreamElements’ Custom Commands panel, its user level and its cooldowns become a flow with a trigger and, where you need one, a check node:

In StreamElementsIn BloopbotNotes
A custom commandA flow with a Chat command trigger (create your first chat command)The trigger’s Command field is the word without the prefix; Also responds to is the alias list.
Permission level: Everyone / Subscriber / VIP / Moderator / BroadcasterA Who can trigger check, At least set to the matching levelThat is Bloopbot’s full ladder for this check. Every level above the one you pick passes too, so the broadcaster always does; Broadcaster only keeps moderators out as well.
Permission level: RegularA Has a role check, Roles left at its default RegularsA different check node from Who can trigger: Has a role reads Viewers › Regulars (or any other role you name), and the broadcaster and moderators pass it by default too — see reward viewers and recognise regulars.
Global cooldown / user cooldownA Cooldown check with Whole channel and/or Per viewer durationsBoth bots let you set a channel-wide and a per-viewer cooldown on the same command; Bloopbot also lets moderators or you skip it. See add permissions and cooldowns.
TimersA flow with an On a timer triggerSee post a recurring chat message.
Spam filters (links, caps, symbols, blacklist/whitelist)The channel-wide filters on ModerationSettings applied to every message, not a flow you draw — see set up moderation helpers.
Loyalty points, earned by watchingBloopbot loyalty points, configured on Loyalty, read with !points/!watchtime/!topSeparate systems and separate balances — a viewer’s StreamElements points do not carry over. See reward viewers and recognise regulars.
The Stream Store (spend loyalty points on a streamer-defined reward)No catalogue equivalent — build the same shape as a flow, the way Bloopbot’s own !give doesBloopbot has no store record listing redeemable items. What it does have is the same underlying move: a Read points & watch time step, a check that the balance covers the cost, then a Set a variable step that subtracts loyalty_balance — exactly how the built-in !give flow spends points. A Giveaway with a ticket cost is the closest ready-made version of “spend points for something” — see run a giveaway in chat.
Overlays and alertsBloopbot overlays — each one you design once and add to OBS as its own Browser SourceAlerts are layers on an overlay you build; see add an overlay to OBS and show alerts on stream.
Song requestsThe Song requests flow pack, playing through your own linked Spotify accountSee let chat request songs. Song requests and overlays may not be available on your channel yet — check what your plan includes.

Variables

StreamElements documents $() and ${} as interchangeable — $(uptime shroud) and ${uptime shroud} are the same call — while Bloopbot only ever uses $(…):

StreamElementsBloopbotNotes
${user}, ${sender}, ${source}$(user) — a Chat command trigger’s “Who typed it”Whoever ran the command, by display name.
${user.name}, ${sender.name}$(userlogin)Their login name, in lowercase.
${touser}$(touser) — “First word, or the viewer”Also literally named touser in Bloopbot. It drops a leading @, which StreamElements keeps.
${1} … ${9} (positional arguments)$(1) … $(9) work the same way in any flow text field; the full remainder, ${1:}, is $(query)All nine work — the Starter pack’s own !deaths +5 counter reads the amount as $(3). Only $(1) and $(2) appear in the trigger’s own tray and Insert… menu; further words you type by hand.
${count} (the command’s own counter)A declared variable plus a Set a variable action, read back as $(var.name)Declare the variable once on Variables, then a Set a variable step adds to it — the Starter pack’s own !deaths counter is built exactly this way. See keep a counter with variables.
${count deaths}, ${getcount deaths} (a named counter)One variable, deaths_count, shared by every command that names the counter${count deaths} adds 1 and shows the new total, ${count deaths -1} takes one off, ${count deaths 0} resets it, and ${getcount deaths} only reads it.
${random}, ${random.1-6}, ${random.pick 'a' 'b' 'c'}, ${random.chatter}A Pick at random step: A number for a range, One from a list for a pick, Someone in chat for a chatterThe reply reads what was picked. The importer adds the step for you.
${user.points bob}, ${user.points_rank ${1}}, ${user.time_online ${1}}, ${user.name ${1}}A Read points & watch time step set to A named viewerThe reply reads that viewer’s points, rank, watch time or name from Bloopbot’s own loyalty points. The importer adds one step per viewer named.
${math ${user.points} * 2}A Do some maths stepOne operation on two numbers: add, subtract, multiply or divide. Anything math.js does beyond that, such as round(), has no direct equivalent.
${if ${random.pick 1,0} Heads Tails}A Switch on a word step with one Chat message for each answerThe first message is sent when the check is 1, t or true, the other otherwise. With no second answer, nothing is sent, as in StreamElements. One ${if} per reply comes across.
${uptime}, ${channel.uptime}$(data.stream.started_at_ago) — how long ago in the Stream groupA human string like “3 hours”. It keeps counting after the stream ends, so pair it with a Stream status check if you only want it while live. The importer does this for you.
${game}, ${channel.game}$(data.stream.category) — the Stream group’s Category in the Insert… menuYour current category, kept up to date whether you’re live or offline.
${title}, ${status}, ${channel.title}$(data.stream.title)Your current stream title.
${channel.viewers}$(data.stream.viewers)0 while you’re offline, where StreamElements said <not live>.
${channel.followers}, ${channel.subs}, ${channel.subpoints}, ${channel.chatters}$(data.channel.followers), $(data.channel.subscribers), $(data.channel.subscriber_points), $(data.chat.chatters)Your channel’s counts, from the Channel and Chat groups of the Insert… menu.
${channel}, ${channel.display_name}, ${provider}$(channel), and twitchYour channel’s login name.
${user.points}, ${user.points_rank}, ${user.time_online}, ${pointsname}$(points), $(rank), $(watchtime), $(currencies)Bloopbot’s own loyalty points, set up on Loyalty — a viewer’s StreamElements balance doesn’t carry over. $(rank) is a place such as 5, not 5/283.
${settitle …}, ${setgame …}A Set title or category stepThe reply reads the new title or category. Changing them may not be available on your channel yet — check what your plan includes.
$(customapi url) / ${customapi.url}A Web request action, whose answer becomes a value later steps can useNot an inline token — it’s a step on the canvas. Web requests may not be available on your channel yet — check what your plan includes. The importer does this for you when a reply has one ${customapi.https://…}.
${time}, ${repeat}, ${random.emote}, ${user.lastseen}, ${user.lastmessage}, ${quote}, ${weather}, and another channel’s info such as ${game shroud}No direct equivalentA shoutout that reads another channel’s game becomes Bloopbot’s own shoutout: the importer offers it on the review. For quotes, the importer offers Bloopbot’s Quotes instead.

A field that accepts variables shows an Insert… menu listing exactly what that step can read, so you don’t have to remember the exact token.

Import your commands

Bloopbot can read the commands on your channel’s public StreamElements command list and turn each one into a flow for you. You don’t sign in to StreamElements, and nothing changes in StreamElements.

  1. Open the importer. Set up your bot asks about them in its first step when it finds your StreamElements commands, and Bring your commands over is on Tutorials any time from Tutorials (it then asks which bot you used). Or go to Flows → Marketplace → From another bot. Or follow bring my StreamElements commands straight from here.
  2. Choose StreamElements. Bloopbot lists the commands StreamElements shows publicly for the Twitch account you signed in with.
  3. Read each row. It shows the command, who could use it, its cooldowns, and its reply as Bloopbot will send it. A warning line means something didn’t carry over exactly. Some rows offer Use Bloopbot’s shoutout (or clip, quote, giveaway entry) beside Keep your reply. Bloopbot picks one for you when it’s sure the command does that job; you can switch either way before you bring it over.
  4. Untick anything you don’t want. Tick Turn on now for a command you want answering chat straight away. Everything else arrives paused.
  5. Press Bring these over. Each command becomes its own flow called !command (from StreamElements) on your Flows page.
Pebble on the Bring commands from another bot page at step 1 of 4 of Bring your commands over: I found your Nightbot commands, with a Next button, and the importer dimmed behind.
Pebble’s Bring your commands over tutorial on the import page. It names the bot it found, or asks which one you used. Click to enlarge.
The Bring commands from another bot page listing four Nightbot commands, each ticked to bring over with a Turn on now box: !so with a choice between Use Bloopbot’s shoutout, selected, and Keep your reply, set to turn on; !uptime whose reply reads how long the stream has been live, with a note that it stays quiet offline; !lurk as a plain reply, set to turn on; and !discord.
The review: !so arrives as Bloopbot’s shoutout, !uptime reads how long you’ve been live, and !lurk stays your own reply. Click to enlarge.

What each command becomes:

  • The permission level becomes a Who can trigger check, or a Has a role check for Regular. The global and user cooldowns become a Cooldown check on Whole channel and Per viewer.
  • A command set to work only while you’re live, or only while you’re offline, gets a Stream status check.
  • The aliases carry over as Also responds to. A reply sent as a reply or a mention keeps that style in Chat message.
  • Every token in Variables with a Bloopbot equivalent becomes it, so Now playing ${game} says Now playing Minecraft.
  • ${count} becomes a counter variable named after the command. A named counter, such as ${count deaths} in !death and ${getcount deaths} in !deaths, becomes one variable both commands share. StreamElements doesn’t publish its counts, so every counter starts at 0. Set the old number on Variables if you want to keep it.
  • ${random…} gets a Pick at random step before the reply, ${user.points bob} a Read points & watch time step, ${math} a Do some maths step, and ${settitle} or ${setgame} a Set title or category step.
  • ${if} ends the flow in a Switch on a word step with one Chat message per answer, so ${user} flips: ${if ${random.pick 1,0} Heads Tails} says Heads or Tails just as before.
  • ${uptime} becomes how long the stream has been live. While you’re offline, the command stays quiet instead of saying so.
  • A reply with a single ${customapi.https://…} gets a Web request step that fetches the address first, and the Chat message puts the answer where the token was. Check the address before you turn it on.
  • A command switched off in StreamElements is listed as Switched off there and isn’t ticked.

Some rows can’t go live straight away. Their Turn on now box is greyed out, and the command is brought over paused, as written, for you to finish in the editor:

  • a token Bloopbot doesn’t have, such as ${time} or ${random.emote} (see Variables for what to use instead);
  • a ${settitle} or ${setgame}, which changes your stream when it runs: check who can use it before you turn it on;
  • a ${customapi}, which now arrives as a Web request step: check the address it calls before you turn it on;
  • a command that cost loyalty points, because Bloopbot doesn’t charge for it;
  • a command that also answered keywords or a pattern, because Bloopbot answers the command word only;
  • a whisper, which Bloopbot posts in chat instead.

The importer doesn’t bring over commands you hid from your public command list, or your timers, spam filters, Regulars list, quotes or loyalty points. Rebuild those as below. A Regular-level command still arrives with its Has a role check, so add your regulars on Viewers › Regulars.

You can run the importer again after you add commands in StreamElements. A command you already brought over shows Already brought over, and one a flow here already answers shows You already have. Neither is ticked. If you tick a You already have row, it arrives paused beside your existing flow, so you can pick which one to keep on.

Recreate your top commands

Use this for anything the importer couldn’t bring over, or to start from Bloopbot’s own ready-made flows. Do it once your channel is signed in.

  1. Open Flows, press Marketplace, and add the Starter pack for the everyday commands and stream reactions it covers, including its own !deaths counter (mods add to it with !deaths +) as a working example of a StreamElements-style tally.
  2. For anything Starter doesn’t cover, press + New flow → Start blank, add a Chat command trigger, and connect a Chat message action with your reply text.
  3. Add a Who can trigger, Has a role or Cooldown check in front of the action for anything that had a permission level or a cooldown in StreamElements.
The Flows page with Add to Flows docked on its right, the list and its + New flow and + Add buttons beside it: Search flows and packs, the All, Packs and Flows filters, then Packs, with Starter, Pack · 12 flows marked Installed and Alerts, Pack · 8 flows with Add, and more packs below.
Add to Flows: add the Starter pack, then anything it doesn’t already cover. Click to enlarge.

A worked example — a public !discord command with a moderator-only !setdiscord to update the link:

  1. On Variables, declare a text variable named discord_url with your current invite link as its starting value.
  2. Build a flow: Chat command (discord) → Chat message reading Join us: $(var.discord_url).
  3. Build a second flow: Chat command (setdiscord) → Who can trigger (At least: moderator) → Set a variable (discord_url, set to $(query)) → Chat message reading Discord link updated.
  4. Save both, then test as below before you rely on them live.
The flow canvas with a Chat command trigger connected to a Chat message action. Under the trigger, a tray of the values it hands on — Who typed it, After the command, Word 1, Word 2 and a +1 more button; under the Chat message, its Message field with a user badge, with a dashed data wire into it from Who typed it. The node palette is on the left, Test fire and Save are in the top bar, and the Tidy up button is in the canvas toolbar.
The canvas view of a command flow: a Chat command trigger feeding a Chat message action, with the values the trigger hands on — Who typed it, After the command, Word 1, Word 2 — in the tray underneath. Click to enlarge.

Recreate timers and filters

For a StreamElements timer, add an On a timer trigger to a new flow and connect it to a Chat message; set the interval, or specific days and a time. See post a recurring chat message.

For StreamElements’ spam filters, open Moderation and configure the equivalent filter directly — it applies to every message and isn’t something you build as a flow. See set up moderation helpers.

Move your overlay and alerts

StreamElements plays alerts through the same single browser source as the rest of its overlay. In Bloopbot, build an overlay with the alert layers you need on Overlays, then add its own Browser Source in OBS — add an overlay to OBS and show alerts on stream walk through both. Overlays may not be available on your channel yet — check what your plan includes.

  1. Build the new widget in Bloopbot first, with its alert layers configured the way you want them to look.
  2. Use Simulate → Test events in the editor’s top bar to check an alert plays and looks right, with its “Also play on the live overlay in OBS” box left unticked so nothing reaches a real viewer.
  3. Press Publish. OBS only ever shows a widget’s last published version — nothing you build reaches OBS until you publish it.
  4. Add the widget’s OBS URL as a new Browser Source, sized to your canvas, alongside your existing StreamElements source — don’t replace it yet. An alert layer’s own Test published output… button sends one real test to OBS so you can confirm it, without waiting for a real event.
  5. Once you’re happy, remove the StreamElements Browser Source from your scene so only one overlay is answering the same alert.

Turn off the old bot

For each command, timer or filter you’ve rebuilt, switch off the StreamElements original — in the StreamElements dashboard, not here — once its Bloopbot flow is live and doing the same job. Leaving both running is what causes duplicate replies and, for alerts, two overlays drawing the same event at once.

When you’re ready to retire the StreamElements chatbot entirely, use Part in its dashboard’s Chatbot section (or the !bot part chat command) to remove it from your Twitch chat, and consider /unmod-ing its account in Twitch chat once it has left.

Check it before you rely on it

Bloopbot draws a clear line between a simulated check and something that actually reaches Twitch or OBS:

  • Test fire, in the flow editor’s top bar, runs the flow as a dry run and records what would have happened — it does not post to real chat and does not touch a real viewer’s cooldown or points.
  • In the widget editor, Simulate → Test events plays in the preview only, until you tick “Also play on the live overlay in OBS”; an alert layer’s own Test published output… sends one real test to OBS — either way, OBS only ever shows what you last Published.
  • A real check means typing the command in your own Twitch chat, or triggering the real event, and watching for the actual reply or alert, exactly once.

Troubleshooting

  • The importer says StreamElements has no channel for you. Bloopbot looks for the StreamElements channel of the Twitch account you signed in with. If you used StreamElements on a different Twitch account, its commands can’t be imported here, so rebuild them as above.
  • The importer says the StreamElements channel belongs to a different Twitch account. A channel with your name on StreamElements is linked to another Twitch account, so Bloopbot won’t read it.
  • A command you had isn’t in the list. It’s hidden from your public command list in StreamElements. Rebuild it as above, or make it visible in StreamElements and run the importer again.
  • You get two replies, or two alerts. StreamElements and Bloopbot are both still answering the same command, timer or event. Turn off the one you’re retiring, and for alerts remove the matching OBS Browser Source — see “Turn off the old bot” and “Move your overlay and alerts” above.
  • The command does nothing. Check the flow is live rather than paused, and that a Who can trigger, Has a role or Cooldown check isn’t quietly stopping it for the account you’re testing with. Fix a flow or connection walks through the rest.
  • The reply shows $(var.discord_url) or $(user) literally, instead of the value. The variable was never declared on Variables, or the token is misspelled — check it against the Insert… menu on that field rather than retyping it from memory.
  • The reply shows [count: use $(var.…) — see docs/flows.md §3b]. That’s Bloopbot’s deliberate placeholder for a literal $(count) or ${count} left over from StreamElements — there is nothing to count without a declared variable. Replace it with a variable and a Set a variable step, as in “Recreate your top commands” above.
  • The overlay is blank in OBS. An alert layer stays blank until an alert plays on it — use Simulate → Test events or an alert layer’s own Test published output…, and confirm you’ve pressed Publish and the Browser Source points at the current widget URL. Fix a flow or connection covers the rest of the OBS checks.
A little guidance. A lot of possibilities.Something not working?