Discover recipe

Discord Welcome Quiz: Auto-Assign Roles and Regions on Join

Onboard new members with a short welcome quiz that records their region and language as achievements, grants notification roles automatically, and awards XP for finishing.

Audience
community managers running a Discord server
Time to set up
~15 minutes (most of which is creating achievements and roles in your community settings, not authoring the survey)
Best for
servers with members in multiple regions or languages, or servers that use opt-in roles for notifications

Onboard new community members by recording their region, language, and notification preferences, and granting the matching Discord roles automatically.


The scenario

You run a community Discord with members across the Americas, Europe, and Asia-Pacific. You’d like new members to introduce themselves with a short quiz that does three things at once:

  1. Records who they are, their region and preferred language, in a way that surfaces on their profile and persists across surveys.
  2. Subscribes them to the right notifications: Announcements, Giveaways, Events, without asking them to navigate to a separate roles channel.
  3. Welcomes them by name with a small XP bonus for completing.

The recipe uses achievements for region/language (permanent profile-visible info) and roles for notification preferences (opt-in mentions). The difference matters; the section below on achievements vs. roles explains why.


Flow

  ┌──────────────────────────────────────────┐
  │ q1: Intro (content_block)                │
  │ "Hey [UserName]! Welcome 🎉              │
  │  Ready to introduce yourself?"           │
  │ → [ Let's go! 🚀 ]                       │
  └──────────────────────────────────────────┘


  ┌──────────────────────────────────────────┐
  │ q2: Region?     ▢ Americas               │
  │                 ▢ Europe                 │
  │                 ▢ Asia-Pacific           │
  └──────────────────────────────────────────┘


  ┌──────────────────────────────────────────┐
  │ q3: Language?   ▢ English ▢ Spanish      │
  │                 ▢ French  ▢ Japanese     │
  └──────────────────────────────────────────┘


  ┌──────────────────────────────────────────┐
  │ q4: Notifications?                       │
  │ ☐ Announcements ☐ Giveaways ☐ Events     │
  └──────────────────────────────────────────┘


  ╔══════════════════════════════════════════╗
  ║  Fire matching action blocks based on    ║
  ║  q2, q3, q4 (skip logic, single-question ║
  ║  hide expressions per block):            ║
  ║                                          ║
  ║   q2 → 1 of 3 region achievements        ║
  ║   q3 → 1 of 4 language achievements      ║
  ║   q4 → 0-3 notification roles            ║
  ╚══════════════════════════════════════════╝


  ┌──────────────────────────────────────────┐
  │ Outro: thank-you + welcome XP bonus      │
  │ (managed via project rewards/settings)   │
  └──────────────────────────────────────────┘

Why q2/q3/q4 and not q1/q2/q3? The intro content_block counts as q1. Skip-logic position numbering includes every block, not just questions. If you remove the intro, shift the action-block preconditions back to q1/q2/q3.


Prerequisites

You’ll set these up once in your community settings, then reference them by ID in the script.

1. Achievements (7 total)

Create these via the Subo Discord bot (/xp-settings → Achievements) or the Rewards section in the web app. For each, set a name, an emoji/image, and link a Discord role so the badge also grants the role automatically when the achievement fires.

Achievement nameLinked Discord roleSuggested ID
🌎 Americas@🌎 Americasxp_role_id: 1001
🌍 Europe@🌍 Europexp_role_id: 1002
🌏 Asia-Pacific@🌏 Asia-Pacificxp_role_id: 1003
🗣 English speaker@Englishxp_role_id: 1010
🗣 Spanish speaker@Españolxp_role_id: 1011
🗣 French speaker@Françaisxp_role_id: 1012
🗣 Japanese speaker@日本語xp_role_id: 1013

(English is included here so the bot can record it on the user’s profile; the example below only awards Spanish/French/Japanese because English is the default and skipping the explicit grant keeps the flow shorter. Adjust to taste.)

2. Discord roles for notifications (3 total)

Create these as plain Discord roles in your server. No achievement needed: these exist purely to enable @RoleName mentions in your announcement channels.

Role nameSuggested ID
@📣 Announcements1382089724239417454
@🎁 Giveaways1382089724239417455
@📅 Events1382089724239417456

3. Project

Create a project named “Welcome” via POST /v1/communities/{id}/projects or the web app. Leave max_completes_per_user: 1 (members should only take this once).


The script

The full payload is published as the welcomeQuiz example on the PUT /script endpoint in the API reference. The walkthrough below shows what each section does.

Intro: q1 (content_block)

{
  "type": "content_block",
  "prompt": "Hey [UserName]! Welcome to the community 🎉 Ready to introduce yourself?",
  "image_url": "https://i.ibb.co/GfB0H7Z6/subo-equalizer.gif",
  "continue": { "after": "click", "label": "Let's go! 🚀" }
}

[UserName] is substituted with the respondent’s display name at render time. image_url displays a GIF or static image (Discord embeds and the web ConvoChat both support animated GIFs). continue.after = "click" shows a labelled button rather than auto-advancing. The deliberate tap sets the tone that this is a moment, not just a form.

Questions: q2, q3, q4

{
  "type": "single_punch",
  "prompt": "Which region are you in?",
  "options": [
    { "value": "Americas",     "label": "🌎 Americas" },
    { "value": "Europe",       "label": "🌍 Europe" },
    { "value": "Asia-Pacific", "label": "🌏 Asia-Pacific" }
  ]
}

Three plain question blocks: region (single-select), language (single-select), notifications (multi-select). The values are what skip logic will compare against: "Americas", "Europe", "Asia-Pacific" for q2 and so on. Labels are display-only and can include emoji.

The value field is case-sensitive in skip-logic comparisons. Pick values you can read in expressions later and stick to them; you’ll reference them by exact string in every action block below.

Region achievements: one fires, two hide

{
  "type": "action_block",
  "prompt": "Welcome to the Americas crew! 🌎",
  "action_kind": "give_achievement",
  "action_config": { "xp_role_id": 1001 },
  "precondition": "NOT (q2 = \"Americas\")",
  "continue": { "after": "pause", "pause": 2 }
}

Three action blocks, one per region. Each is hidden unless q2 matches that region’s value. Because the conditions are mutually exclusive, exactly one fires.

The skip-logic pattern is:

Hide this block when q2 is not Americas.NOT (q2 = "Americas")

If you’re authoring this in the web app, the Script Editor’s skip-logic panel has a Show / Hide toggle. Pick Show only when and enter q2 = "Americas" and it’ll be saved as the negated form for you.

When the Americas action block fires:

Repeat the same pattern for Europe (xp_role_id: 1002) and Asia-Pacific (xp_role_id: 1003).

Language achievements: same pattern, different question

{
  "type": "action_block",
  "prompt": "Marking you as a Spanish speaker — ¡bienvenido!",
  "action_kind": "give_achievement",
  "action_config": { "xp_role_id": 1011 },
  "precondition": "NOT (q3 = \"Spanish\")",
  "continue": { "after": "pause", "pause": 2 }
}

Identical structure to the region blocks, but referencing q3 instead. The example skips an explicit English grant because most servers treat English as the default; add one if your community works differently.

Notification roles: multi-select means list membership

{
  "type": "action_block",
  "prompt": "You're subscribed to Announcements 📣",
  "action_kind": "give_role",
  "action_config": { "role_id": "1382089724239417454" },
  "precondition": "NOT (\"announcements\" in q4)",
  "continue": { "after": "pause", "pause": 1 }
}

Two things change here:

  1. action_kind is give_role, not give_achievement. Notifications are an opt-in subscription, not a milestone. They should not appear on the user’s profile as a badge.
  2. The skip-logic operator is in, not =. Multi-select answers evaluate to a list of values, so list membership is the right test.

A respondent who selects only “Announcements” and “Events” will fire exactly those two role grants. Giveaways stays hidden because "giveaways" is not in the q4 list.

Outro

The outro (custom thank-you + welcome XP bonus) is managed via project rewards/settings rather than script blocks. With your project’s useXP enabled and a small xpPoints configured, every respondent who reaches the end gets the XP automatically, with no per-respondent skip logic needed.

To customize the outro embed (title, body, image, thumbnail, pause between embeds), use the outro fields in PUT /script. See the Replace script docs for the supported outro overrides.


Variations

Add a fourth segmentation: time zone

Insert a fourth single_punch question between language and notifications:

{
  "type": "single_punch",
  "prompt": "Roughly when are you usually online?",
  "options": [
    { "value": "Morning",   "label": "🌅 Morning" },
    { "value": "Afternoon", "label": "🌤 Afternoon" },
    { "value": "Evening",   "label": "🌆 Evening" },
    { "value": "Night",     "label": "🌙 Night" }
  ]
}

Important: adding this as the new q5 shifts the original q4 (announcements multi-select) to q5. Update every later block that referenced q4 (the notifications question) to reference q5 instead. Block-position references in skip logic are not stable across reorders. That’s a documented platform constraint.

Use XP instead of an achievement for the regional bonus

If you don’t want a permanent profile badge for region and just want a one-time XP bump per region (some communities prefer this), change the action blocks from:

"action_kind": "give_achievement",
"action_config": { "xp_role_id": 1001 }

to:

"action_kind": "give_xp",
"action_config": { "xp_amount": 25 }

The respondent still gets the XP, but no badge is recorded and no role is auto-granted. Use this when region is operational metadata, not identity.

Make completion repeatable (e.g. yearly check-in)

Set the project’s max_completes_per_user > 1 (e.g. 99) so members can retake annually to update their answers. To award fresh XP each retake, add an outro give-XP action block with fire_scope: "session". See the Event RSVP recipe for the same pattern applied to recurring events.


When this recipe doesn’t fit



Achievements vs. roles

The recipe makes a deliberate choice between give_achievement and give_role. The short version:

Achievement (give_achievement)Role (give_role)
Discord sideGrants the linked role (if configured)Grants the role
Subo profileShows as a badge on the member’s profileInvisible
Persists across surveys?Yes, recorded on the user permanentlyYes, but only as a Discord role
Survives the Discord server going away?Yes, persists on SuboNo
Good forIdentity, milestones, credentialsNotifications, access control, operational tags

Rule of thumb: if the information is about who the member is, use an achievement with a linked Discord role. If the information is about what they want to be notified of or access, use a role.

Region and language are identity. Notification preferences are access. Hence the split in this recipe.

Frequently asked questions

How do you automatically give someone a role in Discord when they join?

Ask for what you need in a short onboarding survey, then attach an action block to the answer. When a member picks "Americas", the matching action block fires and Subo grants the role without a moderator touching anything. This recipe wires three notification roles that way.

Should I use an achievement or a Discord role?

Use an achievement for permanent facts about a member (their region, their language) that should show on their profile and survive the server. Use a role for anything operational, like who gets pinged for giveaways. The recipe has a full comparison table.

Can one survey grant more than one role?

Yes. A multi-select question grants one role per selected option, so a member who ticks Announcements and Events gets both. Each option carries its own action block.

Do welcome quiz answers stay attached to the member?

Achievements do. They are recorded against the member in your community and stay readable in later surveys and in the Members API, so you can segment on region or language months later without asking again.

Build it

Every recipe here is a Subo script. Author it in the web app, or send the payload straight to the public API. New communities start free.

Add Subo to your server Browse templates