# Tombol tautan WhatsApp

Tombol tautan menempatkan satu tombol yang dapat diketuk di bawah pesan WhatsApp untuk membuka URL di browser penerima. Gunakan tombol ini ketika langkah selanjutnya ada di web, misalnya halaman checkout atau daftar jadwal workshop, bukan di dalam chat itu sendiri. Untuk pilihan yang dijawab penerima di dalam WhatsApp, gunakan [tombol balasan](/docs/guides/whatsapp/message-types/interactive/reply-buttons) atau [menu daftar](/docs/guides/whatsapp/message-types/interactive/list-menus).

## Kirim tombol tautan

Atur `interactive.type` ke `cta_url`, dengan objek `body_text` dan `cta_url` yang membawa `text` dan `url` tombol:

**TypeScript**

```typescript
const msg = await bird.whatsapp.send({
  to: "+16505551234",
  from: "+13124495648",
  interactive: {
    type: "cta_url",
    body_text: "Tap the button below to see the available dates.",
    cta_url: { text: "See dates", url: "https://example.com/workshops?click_id=a1b2c3" },
  },
});
console.log(msg.id, msg.status);
```

Examples: [TypeScript](/id-id/dokumentasi/guides/whatsapp/message-types/interactive/cta-url-buttons.ts.md) · [Python](/id-id/dokumentasi/guides/whatsapp/message-types/interactive/cta-url-buttons.py.md) · [Go](/id-id/dokumentasi/guides/whatsapp/message-types/interactive/cta-url-buttons.go.md) · [PHP](/id-id/dokumentasi/guides/whatsapp/message-types/interactive/cta-url-buttons.php.md) · [CLI](/id-id/dokumentasi/guides/whatsapp/message-types/interactive/cta-url-buttons.cli.md) · [MCP](/id-id/dokumentasi/guides/whatsapp/message-types/interactive/cta-url-buttons.mcp.md) · [cURL](/id-id/dokumentasi/guides/whatsapp/message-types/interactive/cta-url-buttons.curl.md)

`from` wajib ada di setiap pesan layanan: nomor milik workspace Anda, bukan nomor yang dikelola Bird. Bentuk lengkapnya menambahkan header opsional, footer, dan kutipan dari pesan sebelumnya:

```json
{
  "to": "+16505551234",
  "from": "+13124495648",
  "in_reply_to_message_id": "wam_01kya19eknftrs2s6p82asmvnh",
  "interactive": {
    "type": "cta_url",
    "header": {
      "type": "image",
      "url": "https://cdn.example.com/banners/workshop.png"
    },
    "body_text": "Tap the button below to see the available dates.",
    "footer_text": "Dates are subject to change.",
    "cta_url": {
      "text": "See dates",
      "url": "https://example.com/workshops?click_id=a1b2c3"
    }
  },
  "tags": [{ "name": "campaign", "value": "autumn-workshops" }],
  "metadata": { "order_id": "A-4192" }
}
```

`in_reply_to_message_id` mengutip pesan sebelumnya dalam percakapan yang sama. Lihat bagian [mengutip pesan untuk mengorelasikan balasan](/docs/guides/whatsapp/message-types/interactive#quoting-a-message-to-correlate-a-reply) di hub untuk cara resolusi bekerja dan apa yang bisa terlewat.

Tipe ini mengirim tepat satu tombol `cta_url` dan tidak dapat membawa `buttons`, `list`, atau `cards` bersamanya. Lihat bagian [tombol](/docs/guides/whatsapp/message-types/interactive#buttons) di hub untuk bentuk tombol bersama, yang juga digunakan kembali oleh tombol tautan milik kartu carousel.

## Header dan footer

Header bersifat opsional, dan tersedia dalam salah satu dari empat bentuk:

```text
"header": { "type": "text",     "text": "New workshop dates" }
"header": { "type": "image",    "url": "https://cdn.example.com/a.png" }
"header": { "type": "video",    "url": "https://cdn.example.com/a.mp4" }
"header": { "type": "document", "url": "https://cdn.example.com/a.pdf" }
```

Header media (`image`, `video`, atau `document`) membawa filenya sebagai URL `https` publik yang diambil WhatsApp saat pengiriman, bukan sebagai handle media yang diunggah. `footer_text` bersifat opsional dan menambahkan baris di bawah tombol.

## Batasan

| Field                  | Batasan                        |
| ---------------------- | ------------------------------ |
| Tombol `cta_url`       | tepat satu                     |
| `cta_url.text` (label) | wajib, 1 hingga 20 karakter    |
| `cta_url.url`          | wajib, 1 hingga 2000 karakter  |
| `body_text`            | wajib, 1 hingga 1024 karakter  |
| `footer_text`          | opsional, 1 hingga 60 karakter |
| `header.text`          | 1 hingga 60 karakter           |

Batas 2000 karakter pada `url` adalah milik Bird: Meta tidak mempublikasikan batas panjang untuk field ini. `url` juga mensyaratkan `format: uri`, alamat absolut dengan skema, tetapi Bird tidak memeriksa skema mana: alamat `http://` lolos validasi Bird, dan Meta adalah satu-satunya penentu apakah pesan terkirim.

## Apa yang dilaporkan oleh klik

Ketukan membuka alamat di browser penerima dan tidak ada yang kembali kepada Anda melalui API. Ketukan tombol tautan bukan `interactive_reply`: mapper inbound yang menghasilkan `interactive_reply` hanya menangani ketukan tombol balasan dan ketukan baris daftar, dan tautan `cta_url` tidak memiliki bentuk inbound yang setara. Yang Anda lihat adalah siklus hidup outbound biasa, status `sent`, `delivered`, dan `read` pesan, tetapi `read_at` memberi tahu Anda bahwa pesan dibuka, bukan bahwa tombol diketuk. Tidak ada event klik, tidak ada timestamp, dan tidak ada sinyal ketukan per penerima dari WhatsApp maupun dari Bird.

Dua cara untuk mendapatkan atribusi, karena pengiriman itu sendiri tidak memberikannya kepada Anda:

- **Instrumentasi halaman tujuan.** Satu-satunya bukti klik yang tersedia ada di server tujuan Anda sendiri, dari URL yang Anda berikan.
- **Variasikan URL sendiri, per penerima.** `url` yang Anda kirim adalah string literal: Bird menyimpannya dan meneruskannya ke Meta tanpa perubahan, tanpa substitusi dan tanpa sintaks variabel. URL ini identik untuk setiap penerima dalam satu pengiriman, jadi atribusi per penerima berarti Anda membuat parameter query sendiri, seperti `?click_id=<value>`, dan mengeluarkan satu panggilan `POST /v1/whatsapp/messages` per penerima. Endpoint sudah menerima satu `to` per panggilan, jadi ini adalah pencatatan di sisi Anda, bukan fitur API yang hilang.

Opsi ketiga ada di luar tipe ini sepenuhnya: [template](/docs/guides/whatsapp/templates) dengan variabel tombol `url` dipersonalisasi per penerima oleh WhatsApp sendiri, disuplai melalui komponen `button` pengiriman. Variabel tersebut harus berada di akhir alamat, ditulis sebagai `{{1}}`, sehingga dapat memvariasikan segmen path akhir atau nilai query tetapi tidak pernah host atau bagian tengah URL. Pertimbangannya: template memberikan URL per penerima dan pengiriman di luar jendela layanan pelanggan, dengan biaya review Meta dan bentuk tetap yang disetujui, sedangkan pengiriman `cta_url` memberikan pengiriman bebas bentuk, tanpa review di dalam jendela terbuka dengan URL yang Anda variasikan sendiri.

## Batasan dan kasus khusus

- **Jendela layanan pelanggan harus terbuka.** Tombol tautan adalah pesan layanan, hanya dapat dikirim di dalam jendela terbuka; lihat [jendela layanan pelanggan](/docs/guides/whatsapp/message-types#the-customer-service-window) di hub. Pemeriksaan jendela gagal secara terbuka, jadi `202` bukan bukti bahwa jendela benar-benar terbuka saat pengiriman dilakukan.
- **`from` harus berupa nomor milik workspace Anda.** Mengosongkannya, atau menyebutkan nomor yang bukan pengirim terhubung, ditolak sebelum pengiriman dibuat.
- **URL bersifat statis untuk seluruh pengiriman, dan identik untuk setiap penerima.** Tidak ada variabel per penerima pada tipe ini. Lihat [Apa yang dilaporkan oleh klik](#apa-yang-dilaporkan-oleh-klik) untuk cara mengatribusikan klik.
- **Tidak ada sinyal ketukan, selamanya.** Ketukan tombol tautan tidak menghasilkan pesan inbound maupun event webhook. Jangan membangun fitur yang menjanjikan metrik klik dari tipe ini saja.
- **Bird memeriksa bentuk URL, bukan skemanya.** `url` harus berupa alamat absolut dengan skema, tetapi Bird tidak mensyaratkan `https`, dan Meta juga tidak mempublikasikan pembatasan skema. Bandingkan dengan `url` header media, yang didokumentasikan sebagai mensyaratkan `https`.
- **URL header media yang tidak dapat diambil WhatsApp gagal setelah pengiriman diterima.** WhatsApp mengambil aset header saat pengiriman dan meng-cache-nya selama 10 menit; URL bertanda tangan harus bertahan lebih lama dari pengiriman, dan URL yang tidak dapat dijangkau gagal secara asinkron, dengan `media_rejected` pada `last_error` pesan.

Tidak ada pemeriksaan bentuk yang tercantum dalam tabel [kesalahan](/docs/guides/whatsapp/message-types/interactive#errors) di hub yang dapat terpicu pada tipe ini: pemeriksaan tersebut menginspeksi baris daftar, array `buttons`, atau kartu carousel, dan pesan `cta_url` tidak memiliki ketiganya. Kesalahan bentuk, seperti label `text` lebih dari 20 karakter, dikembalikan sebagai error validasi permintaan generik, bukan salah satu kode tersebut. Kutipan yang tidak dapat diresolusi menggagalkan permintaan sebelum apa pun dibuat atau dikenakan biaya: `404` [`E15071`](/docs/api/errors/E15071) ketika id menyebut pesan yang tidak dimiliki workspace ini, `422` [`E15072`](/docs/api/errors/E15072) ketika id menyebut pesan yang tidak dapat dikutip. Untuk kesalahan yang dapat terjadi pada pengiriman WhatsApp mana pun, jendela tertutup, pengirim hilang atau tidak valid, atau penerima tidak valid, lihat [kesalahan](/docs/guides/whatsapp/message-types/interactive#errors) dan [Mengirim pesan WhatsApp](/docs/guides/whatsapp/sending-whatsapp) di hub.

## Langkah selanjutnya

- [Pesan interaktif WhatsApp](/docs/guides/whatsapp/message-types/interactive): apa yang dimiliki bersama oleh keenam tipe interaktif
- [Template WhatsApp](/docs/guides/whatsapp/templates): untuk variabel tombol `url` yang dipersonalisasi WhatsApp per penerima
- [Mengirim pesan WhatsApp](/docs/guides/whatsapp/sending-whatsapp): envelope permintaan, model `202`, dan percobaan ulang yang aman

## Related resources

- [Connecting WhatsApp to Bird: from buying a number to a live channel](/learn/whatsapp/connecting-whatsapp-to-bird) (video)
- [What is the 24-hour customer service window on WhatsApp?](/explained/whatsapp/what-is-the-24-hour-customer-service-window) (answer)
- [WhatsApp message builder](/tools/whatsapp-message-builder) (tool)
- [WhatsApp](/products/whatsapp) (product)

[Get an implementation brief](/learn/workspace?topic=whatsapp)
