Guide · Flows

How to automate Discord without code (Flows + Google Sheets)

Build no-code Discord automations in a visual editor — log new members to Google Sheets, auto-reply to keywords and post on a schedule, step by step.

FlowsRemindersWelcome messages

On this page

Most Discord “automation” is a pile of single-purpose bots, each with its own dashboard. Flows lets you automate Discord without code in one visual editor: pick a trigger (a member joins, a message arrives, a schedule fires), add logic (If, Switch, Filter, Loop) and chain actions (send a message, give a role, write to Google Sheets, call a web API). This guide explains the building blocks and then walks through three real workflows you can copy.

What you need

  • BotGG in your server (https://discord.com/oauth2/authorize?client_id=1553367772451446804&scope=bot%20applications.commands&permissions=282969912110295) and Manage Server permission.
  • The web console at https://console.botgg.app → your server → Flows. Flows has no slash commands; everything is built in the console.
  • For the Google Sheets example: a Google account and a few minutes in Google Cloud. Google Sheets and MySQL nodes, and webhook triggers, are part of Pro. Discord triggers, logic, Discord actions, schedules and HTTP requests work on the free plan (5 flows).

The building blocks

Every flow has exactly one trigger and any number of nodes connected by lines on a canvas.

GroupNodes
TriggersMember joined, Member left, New message, Reaction added, Member roles changed, Voice activity, Button clicked, Schedule, Webhook, Manual trigger
LogicIf (true/false), Switch (several routes + fallback), Filter (stop when false), Loop, Wait, Stop
DataSet fields, Date & time, Text (templates, regex), JSON
Discord actionsSend message (with embed builder and buttons), Send DM, Reply to message, Add reaction, Add/Remove role, Timeout, Kick, Ban, Create thread, Edit channel, Get member
IntegrationsHTTP request, Google Sheets, MySQL

Expressions: inserting data with {{ }}

Any text field can contain expressions in double curly braces. The variable picker in the node panel inserts them for you, so you rarely type them by hand:

  • {{ $trigger.user.username }} — data from the trigger (here: who joined).
  • {{ $trigger.message.content | lower }} — the message text, lower-cased with a filter.
  • {{ $node["Google Sheets"].updatedRows }} — output of an earlier node, by its name.
  • {{ $now | date('YYYY-MM-DD HH:mm', 'Europe/London') }} — the current time, formatted in a time zone (UTC if you leave the zone out).
  • {{ $guild.name }}, {{ $vars.counter }}, {{ $json.field }} — server, workflow variables, current item.

Filters are chained with |: upper, lower, trim, default('none'), replace(a,b), split, join, round(2), date(format) and more. There is no code execution — expressions only read data, and comparisons live in If, Filter and Switch.

Example 1: Log new members to a Google Sheet

A member list with join dates you can sort, filter and share with your team.

1. Create a service account in Google Cloud. In the Google Cloud console create (or choose) a project, enable the Google Sheets API, then go to IAM & Admin → Service accounts → create one. Open it → Keys → Add key → JSON. A JSON key file downloads.

2. Add the credential in BotGG. In Flows open Credentials → New credential, choose the Google service account type and paste the whole JSON key. Click Save & test. The key is encrypted at rest and never shown back to the browser.

3. Share the spreadsheet. Create a Google Sheet, then share it (Editor) with the service account’s e-mail — the client_email value from the JSON, ending in iam.gserviceaccount.com. This is the step people forget.

4. Build the flow. Create a flow (or start from the Log messages to Google Sheets template and swap the trigger):

  1. Trigger: Member joined, with “Ignore bots” on.
  2. Action: Google Sheets → operation Append, paste the spreadsheet URL, sheet name Sheet1, values mode Columns.
  3. Map columns (header → value): - Username → {{ $trigger.user.username }} - User ID → {{ $trigger.user.id }} - Joined → {{ $now | date('YYYY-MM-DD HH:mm', 'Europe/London') }} - Account created → {{ $trigger.user.createdAt | date('YYYY-MM-DD') }}

Column names match the header row case-insensitively; if the sheet is empty, the first append writes the header row for you. Click Test flow to run it with sample data, check the new row, then switch the flow on and save.

Want departures too? Duplicate the flow, change the trigger to Member left and use Update with lookup column User ID to fill a “Left” column instead of adding a row.

Example 2: Keyword auto-reply in a help channel

Answer the same question for the hundredth time without typing it.

  1. Trigger: New message, channels #help, “Ignore bots” on, match contains, pattern server ip.
  2. Action: Reply to message with the answer — for example Hi {{ $trigger.user.displayName }}, the IP is play.example.net. Rules are in #rules.

Need several answers? Keep the trigger on any message and add a Switch node with value {{ $trigger.message.content | lower }}. Add routes such as contains ip, contains apply, contains rules, each connected to its own Reply to message node, and leave fallback unconnected so other messages are ignored. To skip staff, put a Filter before the Switch: {{ $trigger.member.roles }} does not contain your staff role’s ID.

Example 3: A scheduled weekly message

  1. Trigger: Schedule → type Cron, expression 0 18 * * 5 (Fridays at 18:00). Schedules use the server time zone from the console settings; the editor shows the next runs so you can check.
  2. Optional: HTTP request (GET) to a public API — say, your game server’s status endpoint — and use {{ $node["HTTP request"].body.players }} in the message.
  3. Action: Send message to #announcements with the embed builder: title Weekend raid night, description Raid night for the week of {{ $now | date('D MMMM') }}: sign-ups are open., plus a button if you want a click to start another flow via the Button clicked trigger.

For simple one-off reminders and recurring announcements without logic, Reminders is quicker; use Flows when the post needs data, conditions or follow-up actions.

TipWhy
Name nodes clearly (“Log join”, “Help reply”)Expressions reference nodes by name
Test with Discord actions disabled firstTest runs really send messages and change roles
Turn on “Continue on fail” or retries for HTTP/Sheets nodesA slow API won’t break the whole flow
Use Filter earlyStops the flow before it does work it doesn’t need
Check Executions after changesEvery run shows each node’s input, output and errors

Troubleshooting

  • The flow never runs. Both the flow and the Flows feature must be enabled. Saved changes reach Discord triggers within about a minute.
  • Keyword filters never match. Text matching depends on Discord’s Message Content access for the bot; without it, message text arrives empty.
  • Google Sheets returns 403 or “not found”. The sheet isn’t shared with the service-account e-mail, or the Google Sheets API isn’t enabled in that Cloud project.
  • Times are a few hours off. The date filter formats in UTC unless you pass a zone as the second argument, e.g. date('HH:mm', 'America/New_York').
  • “Add role” fails. BotGG’s role must be above the role it assigns, and actions only work on this server’s channels, roles and members.
  • The flow reacts to its own messages. It doesn’t — BotGG’s own messages and reactions never trigger flows, so you can’t create an accidental loop.

Once your flows run, look at welcome messages and the verification guide for built-in features you don’t need to rebuild, and the commands list for everything else.

FAQ

Is Flows like Zapier or n8n for Discord?

Yes, in the same spirit: a visual canvas with triggers, logic and actions — but built into a Discord bot, so Discord events and actions work without webhooks or API keys.

Do I need to know how to code?

No. Nodes are configured through forms and pickers; expressions are inserted from a variable picker. There is no code node at all.

Can Flows write to Google Sheets on the free plan?

Google Sheets and MySQL nodes and webhook triggers are Pro features. Discord actions, logic, schedules and HTTP requests are free. See pricing.

Can I send data from a website or form into Discord?

Yes, with a Webhook trigger (Pro): each flow gets its own secret URL, and whatever you POST to it is available as {{ $trigger.body }}.

Ready to level up your server?

Add BotGG for free, then switch features on in the web console.