PushizoDocs
Analitik & veri

Event Streams: webhook gövde şablonu ve olay filtresi

Event Streams, giden webhook'ların (docs/webhooks.md) gövdesini alıcının beklediği biçime dönüştürmenizi ve yalnızca ilgilendiğiniz olayları almanızı sağlar (ADR-0030). Dashboard'da Geliştirici → Webhooks → endpoint…

Event Streams, giden webhook'ların (docs/webhooks.md) gövdesini alıcının beklediği biçime dönüştürmenizi ve yalnızca ilgilendiğiniz olayları almanızı sağlar (docs/adr/0030-event-streams-ve-veri-ambari.md). Dashboard'da Geliştirici → Webhooks → endpoint formu → Event Streams bölümünden veya API'de body_template, body_content_type, filters alanlarıyla ayarlanır.

Gövde şablonu (Liquid)

Şablon boşsa standart gövde gönderilir. Şablonda olay event adıyla kullanılır:

AlanÖrnek
event.idwhe_01J… (alıcı tarafında tekilleştirme)
event.typedelivery.clicked
event.created_at2026-10-15T09:30:00.000Z
event.app_idapp_01J…
event.dataOlay türüne özgü veri (bkz. webhook olay kataloğu)

application/json (varsayılan): değişken çıktıları otomatik olarak JSON dize içeriği olarak kaçışlanır, bu yüzden tırnak içinde güvenle kullanılır. Bir nesneyi olduğu gibi gömmek için json ve raw filtrelerini birlikte kullanın. Çıktı geçerli JSON olmalıdır.

{
  "text": "{{ event.type }} — kampanya {{ event.data.campaign_id }}",
  "user": "{{ event.data.user.external_id }}",
  "event": {{ event | json | raw }}
}
```text

**`text/plain`**: kaçış yapılmaz, çıktı olduğu gibi gönderilir (`Content-Type: text/plain; charset=utf-8`).

```liquid
{{ event.type }} {{ event.data.delivery_id }} {{ event.created_at }}
```text

Kurallar:
- Şablon en fazla 64 KB, render çıktısı en fazla 1 MB. `include`/`render`/`layout` etiketleri ve bilinmeyen filtreler
  kullanılamaz; render süresi ve belleği sınırlıdır.
- Batch modunda (yüksek hacimli `delivery.*` olayları) şablon her olay için ayrı render edilir: JSON türünde sonuçlar
  bir **dizi** (`[…, …]`), metin türünde **satırlar** olarak gönderilir.
- İmza (`Pushizo-Signature`) gönderilen gövde üzerinden hesaplanır; doğrulama değişmez.
- Şablon hatası (render hatası, geçersiz JSON, aşırı büyük çıktı) teslimde istek gönderilmeden kalıcı hata olarak
  kaydedilir (`template_invalid_json: …` gibi açık hata metni, teslim geçmişinde görünür). Şablonu düzeltip
  **Yeniden gönder** ile tekrar iletebilirsiniz. Kayıt sırasında sözdizimi hatası olan şablon reddedilir.

## Olay filtresi
Filtre yoksa abone olunan tüm olaylar gönderilir. Koşullar `all` (hepsi) veya `any` (herhangi biri) ile birleşir;
en fazla 20 koşul.

| Alan | Açıklama |
|---|---|
| `event_type` | Olay türü |
| `app_id` | App kimliği |
| `campaign_id` | Kampanya (`data.campaign_id`, `data.message.campaign_id` veya `data.campaign.id`) |
| `message_id` | Mesaj (`data.message_id` veya `data.message.id`) |
| `channel` | Kanal (`data.channel` veya `data.subscription.channel`) |
| `event_name` | Özel olay adı (`event.received`, `conversion.created`) |
| `journey_id` | Journey |
| `user_external_id` | Kullanıcının `external_id`'si |
| `data.<yol>` | Gövdedeki herhangi bir alan (en fazla 5 segment), ör. `data.event.properties.plan` |

Operatörler: `eq`, `neq`, `in`, `not_in` (değer listesi), `starts_with`, `contains` (metinde alt dize, dizide eleman),
`exists`, `not_exists`. Karşılaştırma metin olarak yapılır (`120` ile `"120"` eşittir).

```json
{
  "match": "all",
  "conditions": [
    { "field": "campaign_id", "op": "eq", "value": "cmp_01JABC…" },
    { "field": "channel", "op": "in", "value": ["ios_push", "android_push"] }
  ]
}
```text

Filtre olay üretildiği anda uygulanır: eşleşmeyen olaylar için teslim kaydı oluşmaz. Filtreyi sonradan
değiştirirseniz henüz gönderilmemiş eşleşmeyen teslimler `filtered_out` hatasıyla kapatılır. `event.received` için
mevcut olay adı filtresi (`event_filters.event_names`) zorunlu olmaya devam eder ve Event Streams filtresiyle birlikte
uygulanır.

## Önizleme
Kaydetmeden önce sonucu görün; istek gönderilmez:

```bash
curl -X POST "$API/v1/apps/$APP_ID/webhooks/preview" -H "Authorization: Bearer $HS_KEY" -H 'content-type: application/json' -d '{
  "event_type": "delivery.clicked",
  "data": { "campaign_id": "cmp_01JABC…", "channel": "ios_push" },
  "body_template": "{\"text\": \"{{ event.type }}\"}",
  "filters": { "match": "all", "conditions": [{ "field": "campaign_id", "op": "eq", "value": "cmp_01JABC…" }] }
}'
```text

Yanıt: `matched` (filtreden geçer mi), `failed_conditions`, `body` (render çıktısı), `content_type` ve hata varsa
`error.code` (`render_error`, `invalid_json`, `body_too_large`). `data` verilmezse olay türünün örnek verisi kullanılır.

Bu sayfada