---
title: "Analitik Bawaan Telegram untuk Penempatan Iklan"
description: "Cara mengukur penempatan iklan dengan tautan Telegram unik: tautan undangan untuk channel, parameter start dan startapp untuk bot dan Mini App, serta contoh implementasi atribusi."
outline: [2,3]
---
# Analitik Bawaan Telegram
Telegram menyediakan alat untuk menganalisis hasil penempatan iklan menggunakan tautan unik. Anda dapat membuat tautan terpisah untuk setiap penempatan iklan. Untuk channel dan grup, statistik bergabung tersedia langsung di Telegram, sedangkan untuk bot dan Mini App Anda perlu mengonfigurasi penyimpanan parameter tautan dan pengumpulan data di sisi proyek Anda.

> [!WARNING] PERHATIAN
> Satu penempatan iklan = satu tautan unik. Jika tautan yang sama digunakan di beberapa iklan, sumber trafik akan tercampur dan tidak dapat dipisahkan setelahnya.

Jenis analitik ini terpisah dari statistik kampanye dan pelacakan konversi AdsGram.

## Bagian 1. Untuk manajer kampanye di sisi pengiklan

### 1. Tautan mana yang harus digunakan?
Untuk membandingkan hasil berbagai penempatan iklan, gunakan tautan unik untuk masing-masing.

Misalnya, jika Anda mempromosikan proyek di tiga channel Telegram, buat tiga tautan terpisah. Dengan begitu Anda dapat mengetahui penempatan mana yang mendatangkan pengguna paling banyak.

Jenis tautan bergantung pada tujuan iklan:

| Tujuan iklan | Format tautan | Tempat melacak hasil |
|---|---|---|
| Channel atau grup Telegram | Tautan undangan terpisah | Telegram: pengaturan channel atau grup → `Invite links` |
| Bot | `t.me/YourBot?start=ad_sep_anna` | Bot Anda, jika menyimpan parameternya |
| Mini App | `t.me/YourBot?startapp=ad_sep_anna` | Server aplikasi Anda, jika menyimpan parameternya |

Ganti `YourBot` dengan username bot Anda dan `ad_sep_anna` dengan parameter unik untuk penempatan iklan.

### 2. Channel dan grup: tautan undangan
Buat tautan undangan terpisah untuk setiap penempatan iklan.

1. Buka channel atau grup dan ketuk namanya.
2. Buka pengaturan edit atau pengelolaan. Di versi desktop, gunakan ⋮ → `Manage channel` / `Manage group`.
3. Buka `Invite links` dan pilih opsi untuk membuat tautan baru.
4. Beri nama tautan sesuai penempatan, misalnya `ad_sep_anna`. Nama ini hanya terlihat oleh admin, tidak oleh pengguna yang membuka tautan.
5. Jika perlu, atur tanggal kedaluwarsa, batas jumlah pengguna, atau wajibkan persetujuan admin.
6. Gunakan tautan hanya di satu penempatan iklan.

**Tempat melihat statistik:** layar `Invite links` di Telegram menampilkan berapa banyak pengguna yang bergabung melalui setiap tautan. Buka tautan tertentu untuk melihat daftar penggunanya.

Tautan publik biasa seperti `t.me/yourchannel` tidak memungkinkan Anda memisahkan pengguna yang bergabung berdasarkan penempatan iklan. Channel publik juga dapat membuat tautan undangan, jadi gunakan tautan undangan terpisah dalam iklan Anda.

### 3. Bot: tautan dengan parameter `start`
Gunakan format tautan berikut:

```
https://t.me/<bot>?start=<parameter>
```

Contoh:

```
https://t.me/YourBot?start=ad_sep_anna
```

Saat pengguna membuka tautan dan menekan `Start`, bot menerima perintah yang berisi parameter:

```
/start ad_sep_anna
```

Telegram tidak secara otomatis melaporkan atribusi iklan untuk peluncuran bot ini. Bot harus menyimpan parameter saat catatan pengguna pertama kali dibuat.

Hitung hanya pengguna baru jika metrik Anda adalah akuisisi pengguna baru. Pengguna lama yang membuka tautan iklan tidak menjadi pengguna baru.

### 4. Mini App: tautan dengan parameter `startapp`
Untuk Mini App utama bot, gunakan:

```
https://t.me/<bot>?startapp=<parameter>
```

Untuk Mini App yang dibuat dengan `/newapp` di `@BotFather`, Anda dapat menggunakan:

```
https://t.me/<bot>/<app>?startapp=<parameter>
```

Contoh:

```
https://t.me/YourBot?startapp=ad_sep_anna
```

Jika perlu, tambahkan parameter mode tampilan:
- `&mode=compact` — mode ringkas.
- `&mode=fullscreen` — mode layar penuh.

Mini App menerima parameter di field `start_param`. Server aplikasi Anda harus menyimpannya saat pengguna pertama kali meluncurkan aplikasi.

Jika pengguna membuka Mini App tanpa tautan iklan — misalnya melalui tombol menu atau profil bot — parameter iklan mungkin tidak ada. Anggap peluncuran tersebut sebagai organik, kecuali ada sumber atribusi lain yang andal.

### 5. Aturan parameter
- Panjang maksimum:
    - Parameter `start` — **64 karakter**
    - Parameter `startapp` — **512 karakter**
- Karakter yang diizinkan:
    - `A-Z`, `a-z`, `0-9`, `_`, `-`
    - Jangan gunakan spasi, huruf Kiril, atau titik. Untuk menghindari masalah kompatibilitas, gunakan hanya set karakter yang diizinkan.
- Jangan sertakan data pribadi pengguna dalam parameter.
- Pola penamaan yang disarankan. Gunakan format yang konsisten agar penempatan mudah ditemukan dalam laporan: `ad_<month>_<source>_<creative>`

  Contoh:
    - `ad_sep_tgads_video1`
    - `ad_sep_blogger_anna`

### 6. Tautan kampanye bukan tautan referral
**Tautan referral** memungkinkan pengguna mengundang orang lain dan menerima hadiah.

**Tautan iklan** mengukur trafik dari penempatan iklan. Tautan ini sendiri tidak boleh memicu hadiah referral.

Pisahkan kedua jenis tautan dengan prefiks:
- `ref_…` — tautan referral pengguna.
- `ad_…` — tautan penempatan iklan.

Membuat tautan referral terpisah untuk setiap kampanye iklan hanyalah solusi sementara. Hal ini dapat menyebabkan hadiah referral dibayarkan untuk trafik iklan dan statistik menjadi tercampur.

### 7. Cara menghitung klik
Telegram tidak menyediakan statistik klik untuk tautan `t.me`.

Jika Anda perlu menghitung klik, arahkan pengguna terlebih dahulu melalui redirect milik Anda sendiri, lalu ke Telegram.

Contoh:

```
https://yourdomain.com/go/ad_sep_anna → https://t.me/YourBot?start=ad_sep_anna
```

Server Anda mencatat klik dan mengarahkan pengguna ke tautan tujuan. Cara ini memerlukan implementasi sendiri dan tidak menggantikan pelacakan peluncuran, pengguna baru, atau pengguna yang bergabung ke channel.

### 8. Menyimpan tabel hasil
Buat tabel dengan satu baris untuk setiap tautan unik.

Kolom yang disarankan:

| Field | Yang dicatat |
|---|---|
| Parameter tautan | Misalnya, `ad_sep_anna` |
| Penempatan | Nama channel, postingan, influencer, atau iklan |
| Tanggal | Periode penempatan |
| Biaya | Biaya iklan |
| Pengguna baru | Jumlah pengguna baru yang diatribusikan ke tautan |
| Biaya per pengguna | Biaya ÷ jumlah pengguna baru |

### 9. Daftar periksa sebelum peluncuran
Sebelum memublikasikan iklan, pastikan bahwa:
- Setiap penempatan memiliki tautannya sendiri; tautan tidak digunakan ulang di penempatan lain.
- Parameter tidak melebihi panjang maksimum dan hanya berisi karakter yang diizinkan.
- Tautan telah diuji dengan akun kedua: pengguna yang bergabung terhitung, atau parameter tersimpan oleh bot atau Mini App.
- Tautan, nama penempatan, dan biaya telah dimasukkan ke tabel.

## Bagian 2. Implementasi untuk developer
Contoh di bawah menggunakan Python, SQL, dan `aiogram 3` untuk bot. Prinsip yang sama dapat diterapkan dengan teknologi lain.

Kode ini adalah dasar implementasi, bukan integrasi lengkap yang siap pakai. Fungsi akses database dan beberapa detail integrasi harus disesuaikan dengan aplikasi Anda.

### 10. Data apa yang perlu disimpan
Atribusi memerlukan tiga entitas:
1. Daftar tautan iklan dan kampanye.
2. Sumber akuisisi pengguna, disimpan saat catatan pengguna dibuat.
3. Riwayat kunjungan tautan kampanye, termasuk kunjungan dari pengguna lama.

Contoh skema SQL:

```sql
-- Satu baris per tautan iklan.
-- Misalnya, parameter "ad_sep_anna" sesuai dengan kode "sep_anna".
CREATE TABLE campaigns (
    code       text PRIMARY KEY,
    name       text NOT NULL,
    created_at timestamptz NOT NULL DEFAULT now()
);

-- Sumber akuisisi pengguna ditetapkan saat pembuatan.
-- NULL berarti organik.
ALTER TABLE users
ADD COLUMN campaign text REFERENCES campaigns (code);

-- Semua pengguna yang membuka tautan kampanye,
-- termasuk pengguna baru dan yang sudah ada.
CREATE TABLE campaign_visits (
    code     text REFERENCES campaigns (code),
    user_id  bigint,
    first_at timestamptz NOT NULL DEFAULT now(),
    PRIMARY KEY (code, user_id)
);
```

Field `code` harus berisi kode kampanye singkat, seperti `sep_anna`. Field `name` mendeskripsikan penempatan, misalnya `Channel Anna, postingan September`.

Tabel `campaign_visits` mencatat kunjungan secara terpisah dari sumber akuisisi asli pengguna. Sumber asli tidak boleh ditimpa setiap kali pengguna membuka tautan lain.

### 11. Parsing parameter: satu parser untuk bot dan Mini App
Gunakan satu parser untuk parameter iklan dan referral.

```python
import re

AD = re.compile(r"ad_([A-Za-z0-9_-]{1,61})")
REF = re.compile(r"ref_([A-Za-z0-9]{4,32})")


def parse_start(param: str | None) -> tuple[str, str] | None:
    """("ad", code), ("ref", code), atau None untuk kasus lainnya."""
    if not param:
        return None

    if m := AD.fullmatch(param):
        return "ad", m[1]

    if m := REF.fullmatch(param):
        return "ref", m[1]

    return None
```

Setelah parsing, periksa apakah kode yang diperoleh ada di tabel `campaigns`.
- Jangan atribusikan kode yang tidak dikenal ke kampanye yang ada. Anggap kunjungan tersebut sebagai organik atau tidak teratribusi.
- Jangan simpan nilai parameter mentah yang belum divalidasi.
- Terapkan aturan parsing yang sama untuk parameter yang diterima bot dan Mini App.

### 12. Bot: menangani `/start`
Saat pengguna memulai bot, Telegram meneruskan parameter dalam argumen perintah `/start`.

Contoh menggunakan `aiogram 3`:

```python
@router.message(CommandStart())
async def start(message: Message, command: CommandObject):
    source = parse_start(command.args)
    # "/start ad_sep_anna" -> ("ad", "sep_anna")

    async with db.transaction():
        await create_user_if_new(message.from_user, source)

        if source and source[0] == "ad":
            await record_visit(source[1], message.from_user.id)
```

Fungsi `create_user_if_new` hanya boleh membuat catatan pengguna jika pengguna belum ada.

Untuk mencegah catatan ganda, gunakan operasi atomik seperti:

```sql
-- create_user_if_new: atomik, aman saat bot dan Mini App meminta bersamaan
INSERT INTO users (id, campaign, referrer_id)
VALUES ($1, $2, $3)
ON CONFLICT (id) DO NOTHING
RETURNING id; -- ada baris yang dikembalikan = pengguna baru; tidak ada = pengguna lama, dibiarkan apa adanya
```

Jika kueri mengembalikan baris, pengguna telah dibuat. Jika tidak ada baris yang dikembalikan, pengguna sudah ada dan sumber akuisisi aslinya harus tetap tidak berubah.

Untuk mencatat kunjungan tautan kampanye, gunakan:

```sql
-- record_visit
INSERT INTO campaign_visits (code, user_id)
VALUES ($1, $2)
ON CONFLICT DO NOTHING;
```

Jika pengguna lama membuka tautan lain dan menerima `/start ad_…`, catat kunjungannya, tetapi **jangan timpa** field `campaign` miliknya.

Untuk atribusi referral, isi `referrer_id` hanya untuk pengguna baru. Jangan izinkan pengguna mereferensikan dirinya sendiri.

### 13. Mini App: menangani peluncuran pertama
Mini App dapat menerima parameter `start_param` sebagai bagian dari data peluncuran Telegram Web App.

Di sisi frontend, kirim data bertanda tangan Telegram ke server Anda:

```javascript
// Frontend: setiap permintaan membawa data inisialisasi Telegram yang ditandatangani
fetch("/api/me", { headers: { Authorization: `tma ${Telegram.WebApp.initData}` } })
```

Di server, validasi keaslian `initData` dan usianya sebelum menggunakan ID pengguna atau `start_param`.

Contoh fungsi validasi dalam Python:

```python
import hashlib, hmac, json, time
from urllib.parse import parse_qsl


def check_init_data(
    raw: str,
    bot_token: str,
    max_age: int = 86400
) -> dict:
    fields = dict(
        parse_qsl(
            raw,
            keep_blank_values=True,
            strict_parsing=True
        )
    )

    received = fields.pop("hash", "")
    # semua field kecuali hash, termasuk "signature", diurutkan, satu key=value per baris
    data = "\n".join(
        f"{k}={v}" for k, v in sorted(fields.items())
    )

    secret = hmac.new(
        b"WebAppData",
        bot_token.encode(),
        hashlib.sha256
    ).digest()

    expected = hmac.new(
        secret,
        data.encode(),
        hashlib.sha256
    ).hexdigest()

    if not hmac.compare_digest(expected, received):
        raise PermissionError("bad signature")

    if time.time() - int(fields["auth_date"]) > max_age:
        raise PermissionError("expired")

    return {
        "user": json.loads(fields["user"]),
        "start_param": fields.get("start_param")
    }
```

Setelah validasi berhasil, ikuti proses yang sama seperti pada bot (`create_user_if_new` dan `record_visit`):
1. Ambil `user` dan `start_param` dari data yang telah divalidasi.
2. Parsing parameter dengan `parse_start`.
3. Buat pengguna hanya jika belum ada.
4. Catat kunjungan tautan kampanye jika parameter cocok dengan kampanye iklan yang dikenal.

**Keamanan:** gunakan hanya `initData` yang telah divalidasi. Jangan memercayai `initDataUnsafe` atau parameter URL sebagai sumber identitas pengguna atau atribusi karena keduanya dapat dipalsukan.

Parameter `start_param` diberikan saat aplikasi diluncurkan melalui tautan yang sesuai. Parameter ini mungkin tidak ada pada peluncuran berikutnya dari menu. Karena itu, tetapkan sumber akuisisi asli saat pengguna dibuat, bukan pada setiap peluncuran aplikasi.

### 14. Satu pengguna, dua titik masuk
Bot dan Mini App dapat menggunakan satu tabel `users` bersama, dengan setiap pengguna diidentifikasi melalui Telegram user ID-nya.

Misalnya, pengguna dapat memulai bot terlebih dahulu lalu membuka Mini App, atau sebaliknya.

Aturan atribusi:
- Handler pertama yang membuat catatan pengguna menetapkan sumber akuisisi asli.
- Handler kedua tidak boleh menimpa sumber tersebut.
- Kunjungan berikutnya dapat dicatat secara terpisah di `campaign_visits`.

Gunakan insert atomik, seperti `INSERT … ON CONFLICT DO NOTHING`. Ini membantu menghindari kesalahan jika permintaan dari bot dan Mini App datang hampir bersamaan.

### 15. Channel: melacak pengguna yang bergabung berdasarkan tautan undangan
Jika Anda memerlukan pelacakan sendiri untuk pengguna yang bergabung, alih-alih hanya mengandalkan antarmuka Telegram, buat tautan undangan terpisah untuk setiap kampanye dan simpan bersama kode kampanyenya.

Contoh pembuatan tautan dalam Python:

```python
# Buat tautan per kampanye dan simpan bersama kodenya
link = await bot.create_chat_invite_link(
    CHANNEL_ID,
    name="ad_sep_anna"
)  # nama: 1–32 karakter
save_channel_link("ad_sep_anna", link.invite_link)
```

Dalam contoh ini, nama tautan undangan dibatasi 1–32 karakter.

Untuk menerima event bergabung, bot harus menjadi admin channel dan menerima pembaruan `chat_member` yang relevan. Jika permintaan bergabung memerlukan persetujuan, bot juga harus menerima pembaruan `chat_join_request`.

Contoh konfigurasi polling:

```python
# Bergabung datang sebagai pembaruan chat_member: bot harus menjadi admin dan memintanya
await dp.start_polling(
    bot,
    allowed_updates=[
        "message",
        "chat_member",
        "chat_join_request"
    ]
)
```

Contoh handler bergabung:

```python
@router.chat_member()
async def member(update: ChatMemberUpdated):
    joined = (
        update.old_chat_member.status in ("left", "kicked")
        and update.new_chat_member.status == "member"
    )

    if joined and update.invite_link:
        save_channel_join(
            update.invite_link.name,
            update.new_chat_member.user.id
        )
```

Jika tautan memerlukan persetujuan admin, tangani `chat_join_request`. Tautan undangan tersedia di `update.invite_link`; setelah memeriksa permintaan, Anda dapat memanggil `approve_chat_join_request`.

Anda juga dapat mencatat pengguna yang keluar dari channel untuk mengetahui siapa yang tetap bertahan.

Telegram sudah menampilkan kepada admin jumlah pengguna yang bergabung per tautan undangan. Database sendiri berguna jika Anda ingin menggabungkan data bergabung ke channel dengan informasi pengguna bot atau analitik lainnya.

### 16. Opsional: melacak klik dengan redirect
Untuk menghitung klik sebelum pengguna sampai di Telegram, buat endpoint redirect milik Anda sendiri.

Contoh dalam Python untuk Mini App:

```python
@app.get("/go/{code}")
async def go(code: str, request: Request):
    agent = request.headers.get("user-agent", "")

    if code_exists(code) and "TelegramBot" not in agent:  # abaikan crawler pratinjau tautan Telegram
        record_click(code)

    return RedirectResponse(
        f"https://t.me/{BOT}?startapp=ad_{code}",
        status_code=302
    )
```

Contoh ini memvalidasi kode dan mengecualikan permintaan yang User-Agent-nya berisi `TelegramBot`, agar permintaan pratinjau tautan Telegram tidak dihitung sebagai klik pengguna biasa.

Sesuaikan implementasi dengan infrastruktur Anda dan uji dengan tautan nyata. Redirect harus mengarah ke tautan bot atau Mini App yang benar dengan parameter yang sesuai.

### 17. Contoh laporan
Kueri berikut menampilkan, untuk setiap kampanye, jumlah pengunjung unik tautan kampanye, pengguna baru, dan pengguna yang teraktivasi.

```sql
SELECT
    c.code,
    c.name,
    (
        SELECT count(*)
        FROM campaign_visits v
        WHERE v.code = c.code
    ) AS visitors,
    (
        SELECT count(*)
        FROM users u
        WHERE u.campaign = c.code
    ) AS new_users,
    (
        SELECT count(*)
        FROM users u
        WHERE u.campaign = c.code
          AND u.first_action_at IS NOT NULL
    ) AS active
FROM campaigns c
ORDER BY new_users DESC;
-- first_action_at: kapan pengguna pertama kali melakukan tindakan yang dibayar kampanye (tugas, pembelian)
```

Dalam contoh ini, `first_action_at` adalah waktu saat pengguna pertama kali menyelesaikan tindakan target yang dibayar pengiklan, seperti menyelesaikan tugas atau melakukan pembelian.

Metrik `visitors` mewakili pengguna yang memiliki kunjungan tercatat ke kampanye terkait di `campaign_visits`. Metrik ini tidak sama dengan jumlah klik tautan, kecuali klik dicatat secara terpisah melalui redirect.

### 18. Kesalahan umum dan batasan
- **Bot hanya menerima parameter saat pengguna menekan `Start`.** Tidak semua orang yang mengklik tautan memulai bot, sehingga jumlah peluncuran bisa lebih rendah daripada jumlah klik.
- **Memulai ulang bukan berarti pengguna baru.** Jika pengguna menghapus chat dan memulai bot lagi, parameter dapat dikirim ulang, tetapi pengguna tersebut bukan pengguna baru.
- **Jangan timpa sumber akuisisi asli.** Gunakan tabel kunjungan terpisah dengan stempel waktu untuk menganalisis kunjungan berikutnya.
- **Pisahkan akun baru dan akun lama.** Jika tujuannya adalah akuisisi, kunjungan berulang tidak boleh menambah jumlah pengguna baru.
- **Kecualikan bot dan referral diri sendiri.** Periksa `is_bot` dan jangan izinkan pengguna mereferensikan dirinya sendiri.
- **Patuhi batasan parameter.** Panjang total parameter `start` tidak boleh melebihi 64 karakter. Gunakan kode singkat, seperti `sep_anna`, untuk menyisakan ruang bagi prefiks `ad_` atau `ref_`.
- **Pisahkan atribusi referral dan atribusi iklan.** Prefiks dan aturan pemrosesan yang berbeda membantu mencegah hadiah dan laporan yang salah.
