Flow Design Guide
Design interactive WhatsApp Flows in ChatYug without writing JSON. This guide covers why and how to use Flows in ChatYug, every designer component and its properties, starter templates, and what to do when Meta rejects a publish.
Why use Flow Design in ChatYug
WhatsApp Flows are Meta’s native in-chat forms (checkout, leads, surveys, appointments, support). ChatYug’s Flow Design module lets non-technical operators:
- Build screens with drag-and-drop (n8n-style canvas).
- Approve (= publish on Meta) from the same screen.
- Test Send the published flow to any WhatsApp number.
- Keep advanced JSON only as an escape hatch.
This is not the Chatbot keyword builder (Automation). Commerce Flows collect structured answers inside WhatsApp; chatbot flows automate replies with a different node engine.
How to use a Flow in ChatYug (end-to-end)
- Open WhatsApp Messaging → Flow Design (or Commerce → Flow Design).
- Click Create from template, choose a use case, and create the draft on Meta.
- In the designer: add/edit screens and components, connect screens with the purple port, then Save.
- Click Approve to publish on Meta (DRAFT → PUBLISHED). If Meta rejects, read the rejection panel (reason + fixes).
- Click Test Send and enter a number with country code (e.g.
919876543210). - Open Analytics on the flow card to see sends and submissions (phone, name, time, payload) and export Excel.
Production paths after publish
| Path | When to use | How |
|---|---|---|
| Commerce checkout | Cart / product checkout | Copy Meta Flow ID into Commerce Settings → Checkout Flow ID. Enable auto-send if you want ChatYug to send the flow after a cart order. |
| Portal Test Send | QA / demos | Flow Design list or designer → Test Send. |
| External API / MCP | Your CRM / AI assistant | POST /api/external/messages/flow or MCP send_commerce_flow_message. Full manage + analytics: Commerce Flows API & MCP. |
| Customer answers | Integrations + portal | Webhook nfm_reply; also stored as Flow Analytics submit events. Checkout also hits ChatYug’s encrypted flow endpoint. |
Create, list, and count flows
- Create: Flow Design → Create from template (or External API
POST /commerce/flows). - List: Flow Design home shows all drafts/published for the selected WABA; header strip shows Total / Draft / Published counts.
- API list:
GET /api/external/commerce/flowsor MCPlist_commerce_flows.
Analytics (from each flow card)
Analytics live inside Flow Design — not as a separate Messaging hub card. Each flow card shows mini send/submit counts and an Analytics button.
- Opens a per-flow report: time, event type (
send/submit), phone, name (when present), interaction payload summary. - Filters: date range, phone, event type.
- Export Excel downloads the filtered set (portal or
GET /api/commerce/flows/analytics/export?flowId=). Each form answer becomes its own column (field labels from the flow when available); there is no combined Payload blob column. - Designer top bar also has Analytics for the open flow.
V1 records Test Send / API sends and customer completions. Meta per-screen open funnels are not available in ChatYug today.
Send a flow and receive filled answers
Send (portal)
- Publish with Approve (status must be PUBLISHED).
- Test Send → enter digits with country code (e.g.
917016793529), or from Start Chat use the green sitemap button to send a published flow while the 24-hour window is open. - Conversations show an outbound Flow sent bubble; Analytics logs a
sendrow.
Send (API / MCP)
POST /api/external/messages/flow or MCP send_commerce_flow_message. Pass your own flowToken so you can match the reply later. Details: Commerce Flows API.
Receive
Customer completion arrives as webhook interactive.type = nfm_reply. Parse response_json; keys = designer field Names; include flow_token for correlation. ChatYug also stores a readable Flow response bubble in Conversations and a Flow Analytics submit event.
const answers = JSON.parse(nfm_reply.response_json || '{}');
// answers.flow_token === the token from send
// answers.<field_name> === what the customer typed/selected
Full parse samples: Receive filled data.
Pre-publish checklist (ChatYug validates on Approve)
- Terminal screens have a Footer
- Unique
UPPER_SNAKE_CASEscreen IDs - Unique lowercase field
names across the whole flow - ≥2 options on Dropdown / Radio / Checkbox
- HTTPS image URLs
- Navigate targets exist;
data_exchangeonly if Commerce endpoint is configured
Use the Variables panel for ${form.field_name} (answers) and ${data.key} (init / endpoint data). Preview shows a phone frame of the selected screen; published flows may also show Meta’s preview_url.
Designer steps (canvas model)
- Screen = a canvas node (one WhatsApp Flow screen).
- Edge = routing from one screen to another (drag the purple out-port).
- Components live inside the selected screen (left palette → drop or click).
- Screen properties: ID (
UPPER_SNAKE_CASE), Title, Terminal flag. - Terminal screens must end with a Footer (Meta requirement).
- Top bar: Save · Approve · Test Send · Analytics · JSON · Help.
Component quick index
| Component | Group | Key properties |
|---|---|---|
| TextHeading | Text | text |
| TextSubheading | Text | text |
| TextBody | Text | text (may use ${data.*}) |
| TextCaption | Text | text |
| RichText | Text | text |
| TextInput | Input | label, name, required, input-type |
| TextArea | Input | label, name, required |
| Dropdown | Input | label, name, required, options |
| RadioButtonsGroup | Input | label, name, required, options |
| CheckboxGroup | Input | label, name, required, options |
| DatePicker | Input | label, name, required |
| CalendarPicker | Input | label, name, required |
| OptIn | Input | label, name, required |
| Image | Media | src (HTTPS URL) |
| ImageCarousel | Media | image URLs (one per line) |
| PhotoPicker | Media | label, name, max KB |
| DocumentPicker | Media | label, name, max KB |
| EmbeddedLink | Action | link text, URL |
| NavigationList | Action | Title|SCREEN_ID rows |
| Footer | Action | button label, action (complete / data_exchange / navigate) |
Component reference
TextHeading
When: Start every screen with a clear title.
Step: Select screen → add Heading from Text palette → set text in the inspector.
Properties: text (required).
TextSubheading
When: Secondary title under the heading.
Step: Add Subheading → edit text.
Properties: text.
TextBody
When: Instructions or dynamic values such as order total.
Step: Add Body → set text. You may use ${data.order_total} when screen data provides that field (checkout).
Properties: text.
TextCaption
When: Small hints or legal notes under fields.
Properties: text.
RichText
When: Light formatting (e.g. **bold**) without adding an input.
Properties: text.
TextInput
When: Name, email, phone, PIN, short answers.
Step: Add Text Input → set Label, unique Name, Required, Input type (text, number, email, phone, etc.).
Properties: label, name (unique), required, input-type.
Prevent errors: Never reuse the same name on two fields.
TextArea
When: Comments, issue descriptions, notes.
Properties: label, name, required.
Dropdown
When: Single choice from a short list (payment method, issue type).
Step: Add Dropdown → set Label / Name → enter options as comma-separated titles.
Properties: label, name, required, options → Meta data-source.
RadioButtonsGroup
When: Visible single-choice list (ratings).
Properties: same pattern as Dropdown (comma-separated options).
CheckboxGroup
When: Allow multiple selections.
Properties: label, name, required, options.
DatePicker
When: Appointment or delivery date.
Properties: label, name, required.
CalendarPicker
When: Calendar-style date UI is preferred.
Properties: label, name, required.
OptIn
When: Consent / terms agreement.
Properties: label, name, required (mark required for mandatory consent).
Image
When: Show a product or brand image.
Step: Add Image → set public https:// src URL.
Prevent errors: Meta must be able to fetch the URL; avoid private or HTTP-only links.
ImageCarousel
When: Multiple images on one screen.
Step: One HTTPS URL per line in the inspector.
PhotoPicker
When: Customer uploads a photo (proof, KYC).
Properties: label, name, max file size (KB). Do not use Meta required on this component — ChatYug strips it on save; use min-uploaded-photos if Meta requires a minimum.
Answers: Submitted photos appear in Flow Analytics Attachments (thumbnails) and via External API / MCP as chatyug_url on the field.
DocumentPicker
When: Customer uploads a document (PDF, etc.). If the file MIME is video/*, Analytics treats it as video for preview/download — there is no separate VideoPicker in WhatsApp Flows.
Properties: label, name, max file size (KB). Same rule: no required property (stripped on normalize).
Answers: Appear in Flow Analytics Attachments and via API/MCP (list_flow_analytics, get_flow_media).
EmbeddedLink
When: Link to terms or a help page.
Properties: link text, URL.
NavigationList
When: Menu that jumps to other screens.
Step: Enter rows as Title|SCREEN_ID (one per line). SCREEN_ID must exist on the canvas.
Footer (CTA)
When: Every interactive screen needs a bottom button. Terminal screens must have a Footer.
Actions:
complete— close the flow (simple thank-you / done).data_exchange— send form fields to ChatYug (checkout / endpoint flows). Requires Commerce endpoint + RSA when Meta health-checks.navigate— go to another screen (set Next screen ID or connect ports).
Properties: button label, action, optional next screen.
Multi-screen variables
On a single screen, reference answers with ${form.field_name} (the field must exist on that same screen).
On a later screen, values from an earlier screen must use ${data.field_name}. Pass them in the previous screen’s Footer when action is navigate, for example:
"payload": { "interest": "${form.interest}" }
Then on the next screen body text can say You selected: ${data.interest}. Using ${form.interest} on screen 2 when interest is only on screen 1 is a common cause of Meta publish error 139002 / 4016011.
Publish readiness panel
The designer shows a Publish readiness strip above the canvas. It updates as you edit (debounced). When blocking issues exist, Approve is disabled until you fix them.
| Code | Meaning | Fix |
|---|---|---|
CROSS_SCREEN_FORM_REF | ${form.X} on a screen that does not contain field X | Use ${data.X} and pass X in the previous navigate payload |
TERMINAL_NAVIGATE | Terminal screen with Footer navigate | Uncheck Terminal or change Footer to complete |
NO_TERMINAL | Multi-screen flow with no terminal screen | Mark the last screen Terminal with complete Footer |
MULTIPLE_TERMINAL | More than one terminal when screens navigate | Only the final screen should be Terminal |
MISSING_DATA_REF | ${data.X} never passed from a previous screen | Add X to the navigate Footer payload on the prior screen |
NAVIGATE_NO_TARGET | Footer navigate points to missing screen ID | Fix Next screen ID or create the target screen |
Templates
| Template | Category | What you get | Typical next edit |
|---|---|---|---|
| Checkout | SHOPPING | Delivery fields + payment + success screen | Labels, payment options; link Flow ID in Commerce Settings |
| Lead Generation | LEAD_GENERATION | Name, business, email, phone, interest, opt-in | Interest options; Test Send to sales phone |
| Lead + Follow-up | LEAD_GENERATION | 2 screens: lead form → follow-up with ${data.interest} | Customize follow-up question; use as pattern for multi-screen flows |
| Survey | SURVEY | Rating radios + comments | Rating labels |
| Appointment | APPOINTMENT_BOOKING | Name, phone, date, time slots, notes | Time options |
| Support | CUSTOMER_SUPPORT | Issue type + description | Issue dropdown values |
| Blank | OTHER | One empty screen scaffold | Build from palette |
When Meta rejects Approve / Publish
ChatYug shows a rejection panel with three parts: What Meta said, What this means, and How to fix / prevent. The same guidance is summarized below.
| Symptom (Meta / validation) | What it means | How to fix / prevent |
|---|---|---|
| Footer / terminal | Final screen missing Footer or invalid Footer action | Mark screen Terminal; add Footer; use complete or data_exchange; Save → Approve |
| routing_model / navigate | Broken screen connections | Reconnect ports; fix NavigationList Title|SCREEN_ID; remove edges to deleted screens |
| Screen ID | Invalid or duplicate screen IDs | Use unique UPPER_SNAKE_CASE IDs only |
| Duplicate / invalid field name | Two inputs share name or name is illegal |
Unique lowercase names with underscores |
| version / data_api_version | Unsupported Flow JSON version | Prefer ChatYug templates; keep version 7.3 and data API 3.0 for endpoint flows |
| endpoint / RSA / health / data_exchange | Endpoint flow without keys/URL | Configure Commerce Settings endpoint + RSA, or switch Footer to complete for simple forms |
| data-source / dropdown / radio | Empty or invalid options | Provide at least two clear comma-separated options |
| image / src / media | Bad or unreachable image URL | Public HTTPS URL only; or remove Image components |
On the Flow Design list, drafts with stored validation_errors show Rejected by Meta — view details so you can reopen the same panel without republishing.