WhatsApp API Interactive Messages

Panduan lengkap WhatsApp API interactive messages. Buttons, lists, quick replies. Buat bot lebih interaktif. Tutorial developer!

WhatsApp API Interactive Messages
WhatsApp API Interactive Messages

Interactive = User experience lebih baik!

Interactive messages memungkinkan user klik tombol atau pilih dari list daripada ketik manual. Lebih mudah, lebih cepat, lebih sedikit error.


Jenis Interactive Messages

šŸ“± TIPE INTERACTIVE:

REPLY BUTTONS:
- Max 3 tombol
- User klik untuk reply
- Simple choices

LIST MESSAGE:
- Max 10 items (1 section)
- Max 10 sections
- Dropdown menu style

CTA BUTTONS:
- Call Phone Number
- Visit Website URL

LOCATION REQUEST:
- Minta user share lokasi

FLOW MESSAGE:
- Multi-step form
- Complex interactions

Reply Buttons

Kirim Reply Buttons:

javascript

async function sendReplyButtons(to, bodyText, buttons) {
    const url = `https://graph.facebook.com/v17.0/${PHONE_NUMBER_ID}/messages`;
    
    const payload = {
        messaging_product: 'whatsapp',
        to: to,
        type: 'interactive',
        interactive: {
            type: 'button',
            header: {
                type: 'text',
                text: 'Pilih Opsi'
            },
            body: {
                text: bodyText
            },
            footer: {
                text: 'Klik tombol di bawah'
            },
            action: {
                buttons: buttons.map((btn, i) => ({
                    type: 'reply',
                    reply: {
                        id: btn.id,
                        title: btn.title // Max 20 karakter
                    }
                }))
            }
        }
    };
    
    return await axios.post(url, payload, {
        headers: {
            'Authorization': `Bearer ${ACCESS_TOKEN}`,
            'Content-Type': 'application/json'
        }
    });
}

// Usage
await sendReplyButtons(
    '628123456789',
    'Hai! Mau ngapain hari ini?',
    [
        { id: 'btn_order', title: 'šŸ›’ Order' },
        { id: 'btn_track', title: 'šŸ“¦ Cek Pesanan' },
        { id: 'btn_help', title: 'šŸ’¬ Bantuan' }
    ]
);

Handle Button Response:

javascript

// Di webhook handler
function handleInteractiveResponse(message) {
    if (message.type !== 'interactive') return;
    
    const interactive = message.interactive;
    
    if (interactive.type === 'button_reply') {
        const buttonId = interactive.button_reply.id;
        const buttonTitle = interactive.button_reply.title;
        
        console.log(`User klik: ${buttonTitle} (${buttonId})`);
        
        switch (buttonId) {
            case 'btn_order':
                return handleOrder(message.from);
            case 'btn_track':
                return handleTracking(message.from);
            case 'btn_help':
                return handleHelp(message.from);
        }
    }
}

List Message

Kirim List:

javascript

async function sendListMessage(to, bodyText, buttonText, sections) {
    const payload = {
        messaging_product: 'whatsapp',
        to: to,
        type: 'interactive',
        interactive: {
            type: 'list',
            header: {
                type: 'text',
                text: 'Menu Utama'
            },
            body: {
                text: bodyText
            },
            footer: {
                text: 'Pilih dari menu'
            },
            action: {
                button: buttonText, // Max 20 karakter
                sections: sections
            }
        }
    };
    
    return await sendMessage(payload);
}

// Usage
await sendListMessage(
    '628123456789',
    'Selamat datang! Pilih kategori produk:',
    'Lihat Kategori',
    [
        {
            title: 'Produk',
            rows: [
                {
                    id: 'cat_fashion',
                    title: 'šŸ‘— Fashion',
                    description: 'Baju, celana, aksesoris'
                },
                {
                    id: 'cat_electronics',
                    title: 'šŸ“± Elektronik',
                    description: 'HP, laptop, gadget'
                },
                {
                    id: 'cat_food',
                    title: 'šŸ” Makanan',
                    description: 'Snack, minuman, frozen'
                }
            ]
        },
        {
            title: 'Layanan',
            rows: [
                {
                    id: 'svc_track',
                    title: 'šŸ“¦ Cek Pesanan',
                    description: 'Lacak status pengiriman'
                },
                {
                    id: 'svc_help',
                    title: 'šŸ’¬ Bantuan',
                    description: 'Chat dengan CS'
                }
            ]
        }
    ]
);

Handle List Response:

javascript

function handleListResponse(message) {
    if (message.interactive.type === 'list_reply') {
        const selectedId = message.interactive.list_reply.id;
        const selectedTitle = message.interactive.list_reply.title;
        const selectedDescription = message.interactive.list_reply.description;
        
        console.log(`User pilih: ${selectedTitle}`);
        
        // Route berdasarkan selection
        if (selectedId.startsWith('cat_')) {
            return showCategoryProducts(message.from, selectedId);
        }
        
        if (selectedId.startsWith('svc_')) {
            return handleService(message.from, selectedId);
        }
    }
}

CTA Buttons (Call to Action)

Call Phone Number:

javascript

async function sendCallButton(to, bodyText, phoneNumber, buttonText) {
    const payload = {
        messaging_product: 'whatsapp',
        to: to,
        type: 'interactive',
        interactive: {
            type: 'cta_url',
            body: {
                text: bodyText
            },
            action: {
                name: 'cta_url',
                parameters: {
                    display_text: buttonText,
                    url: `tel:${phoneNumber}`
                }
            }
        }
    };
    
    return await sendMessage(payload);
}

// Untuk call button di template, gunakan:
// type: 'PHONE_NUMBER' di template components

Visit URL:

javascript

async function sendUrlButton(to, bodyText, url, buttonText) {
    const payload = {
        messaging_product: 'whatsapp',
        to: to,
        type: 'interactive',
        interactive: {
            type: 'cta_url',
            body: {
                text: bodyText
            },
            action: {
                name: 'cta_url',
                parameters: {
                    display_text: buttonText,
                    url: url
                }
            }
        }
    };
    
    return await sendMessage(payload);
}

// Usage
await sendUrlButton(
    '628123456789',
    'Klik tombol di bawah untuk melihat produk lengkap!',
    'https://shop.brand.com/catalog',
    'šŸ›’ Lihat Katalog'
);

Location Request

Minta Lokasi User:

javascript

async function requestLocation(to, bodyText) {
    const payload = {
        messaging_product: 'whatsapp',
        to: to,
        type: 'interactive',
        interactive: {
            type: 'location_request_message',
            body: {
                text: bodyText
            },
            action: {
                name: 'send_location'
            }
        }
    };
    
    return await sendMessage(payload);
}

// Usage
await requestLocation(
    '628123456789',
    'Untuk cek ongkir, share lokasi kamu dengan klik tombol di bawah:'
);

Handle Location Response:

javascript

function handleLocationMessage(message) {
    if (message.type === 'location') {
        const { latitude, longitude, name, address } = message.location;
        
        console.log(`Location: ${latitude}, ${longitude}`);
        console.log(`Name: ${name}`);
        console.log(`Address: ${address}`);
        
        // Calculate shipping, find nearest store, etc
        return calculateShipping(latitude, longitude);
    }
}

Kombinasi dengan Media

Buttons dengan Image Header:

javascript

async function sendButtonsWithImage(to, imageUrl, bodyText, buttons) {
    const payload = {
        messaging_product: 'whatsapp',
        to: to,
        type: 'interactive',
        interactive: {
            type: 'button',
            header: {
                type: 'image',
                image: {
                    link: imageUrl
                }
            },
            body: {
                text: bodyText
            },
            action: {
                buttons: buttons.map(btn => ({
                    type: 'reply',
                    reply: { id: btn.id, title: btn.title }
                }))
            }
        }
    };
    
    return await sendMessage(payload);
}

// Usage - Product dengan buttons
await sendButtonsWithImage(
    '628123456789',
    'https://brand.com/product.jpg',
    'šŸ›ļø Tas Kulit Premium\n\nšŸ’° Rp 500.000\nšŸ“¦ Ready stock',
    [
        { id: 'buy_now', title: 'šŸ›’ Beli' },
        { id: 'add_cart', title: 'šŸ›’ + Keranjang' },
        { id: 'ask_cs', title: 'šŸ’¬ Tanya' }
    ]
);

Unofficial API (Baileys)

Reply Buttons:

javascript

async function sendButtons(sock, to, text, buttons) {
    const jid = `${to}@s.whatsapp.net`;
    
    await sock.sendMessage(jid, {
        text: text,
        buttons: buttons.map(btn => ({
            buttonId: btn.id,
            buttonText: { displayText: btn.text },
            type: 1
        })),
        headerType: 1
    });
}

// Atau dengan template buttons
await sock.sendMessage(jid, {
    templateButtons: [
        {
            index: 1,
            urlButton: {
                displayText: 'Kunjungi Website',
                url: 'https://brand.com'
            }
        },
        {
            index: 2,
            callButton: {
                displayText: 'Hubungi Kami',
                phoneNumber: '+628123456789'
            }
        },
        {
            index: 3,
            quickReplyButton: {
                displayText: 'Quick Reply',
                id: 'quick_1'
            }
        }
    ],
    text: 'Pilih opsi:'
});

List Message:

javascript

async function sendList(sock, to, text, buttonText, sections) {
    const jid = `${to}@s.whatsapp.net`;
    
    await sock.sendMessage(jid, {
        text: text,
        buttonText: buttonText,
        sections: sections,
        listType: 1
    });
}

// Usage
await sendList(sock, '628123456789', 'Pilih menu:', 'Menu', [
    {
        title: 'Kategori',
        rows: [
            { title: 'Fashion', rowId: 'cat_fashion' },
            { title: 'Elektronik', rowId: 'cat_elec' }
        ]
    }
]);

Flow Builder Example

javascript

// Multi-step conversation flow
const flows = {
    'start': {
        message: 'Selamat datang! Mau ngapain?',
        buttons: [
            { id: 'flow_order', title: 'Order' },
            { id: 'flow_track', title: 'Cek Pesanan' }
        ],
        next: {
            'flow_order': 'select_category',
            'flow_track': 'input_order_id'
        }
    },
    'select_category': {
        type: 'list',
        message: 'Pilih kategori:',
        sections: [/* ... */],
        next: {
            'cat_*': 'show_products'
        }
    },
    // ... more steps
};

async function handleFlowStep(phone, step, input) {
    const currentFlow = flows[step];
    const nextStep = currentFlow.next[input];
    
    // Save user state
    await saveUserState(phone, nextStep);
    
    // Send next message
    await sendFlowMessage(phone, flows[nextStep]);
}

Best Practices

DO āœ…

- Gunakan buttons untuk pilihan terbatas
- Gunakan list untuk banyak pilihan
- ID yang descriptive
- Combine dengan media
- Handle semua responses
- Fallback untuk unknown

DON'T āŒ

- Terlalu banyak buttons (max 3)
- Title terlalu panjang (max 20 char)
- Skip handling responses
- Tidak ada fallback
- Nested menus terlalu dalam
- Ignore user free text

FAQ

Kapan pakai buttons vs list?

Buttons: 2-3 pilihan simple. List: lebih dari 3 atau perlu deskripsi.

Bisa combine buttons dan list?

Tidak dalam 1 message. Tapi bisa sequential - buttons dulu, lalu list.

Interactive di template bisa?

Ya! Bisa tambahkan buttons di template (Quick Reply atau CTA).


Kesimpulan

Interactive = Better UX!

Text OnlyInteractive
Harus ketikKlik tombol
Typo proneError-free
SlowFast
ConfusingClear options

Buat Interactive Bot →


Artikel Terkait