Data Feeds
Data Feeds, mesaj gönderilirken her alıcı için harici bir JSON uç noktasından veri çeker ve şablonda {{ feed.<ad>.alan }} olarak kullanılmasını sağlar (sadakat puanı, stok, sepet, hava durumu…). Karar kaydı:…
Data Feeds, mesaj gönderilirken her alıcı için harici bir JSON uç noktasından veri çeker ve şablonda
{{ feed.<ad>.alan }} olarak kullanılmasını sağlar (sadakat puanı, stok, sepet, hava durumu…). Karar kaydı:
docs/adr/0028-data-feeds-dynamic-content-ai.md.
Feed tanımlama
Dashboard → Mesajlar → Dinamik İçerik → Data Feeds → Yeni feed veya public API:
curl -X POST https://api.pushizo.example/v1/apps/$APP_ID/data-feeds \
-H "Authorization: Bearer $API_KEY" -H "content-type: application/json" \
-d '{
"name": "profil",
"url_template": "https://api.ornek.com/u/{{ user.external_id }}?sehir={{ user.tags.sehir }}",
"secret_headers": { "Authorization": "Bearer <servis-anahtarı>" },
"cache_ttl_seconds": 300,
"timeout_ms": 1500
}'
```text
| Alan | Açıklama |
|------|----------|
| `name` | Liquid adı: küçük harf, rakam, alt çizgi (`feed.profil`). App içinde benzersiz. |
| `url_template` | Liquid ile `user.*`, `subscription.*`, `custom_data.*` kullanılabilir; değerler URL kodlanır. |
| `method` | `GET` (varsayılan) veya `POST`. |
| `body_template` | Yalnızca POST: JSON şablonu; değişkenler JSON dize kaçışlıdır. |
| `headers` | Gizli olmayan başlıklar (yanıtta görünür). |
| `secret_headers` | Gizli başlıklar: zarf şifrelemeyle saklanır, bir daha gösterilmez (yalnızca adları). Güncellemede verilmezse korunur, `null` tümünü kaldırır. |
| `cache_ttl_seconds` | 0–86400; önbellek anahtarı feed + çözümlenmiş URL (+gövde). Feed düzenlenince önbellek geçersizleşir. |
| `timeout_ms` | 100–2000 (üst sınır 2 sn). |
## Güvenlik (SSRF)
- Yalnızca `https://` ve herkese açık adresler: `localhost`, `.local/.internal`, özel/ayrılmış IP'ler (10/8, 172.16/12,
192.168/16, 127/8, 169.254.169.254 metadata, IPv6 yerel…) ve URL içinde kullanıcı adı/parola reddedilir.
- Ad, istek anında DNS ile çözülür; özel bir adrese çözülürse istek yapılmaz ve bağlantı doğrulanan IP'ye
sabitlenir (DNS rebinding koruması). Yönlendirmeler izlenmez.
- Yanıt en fazla 256 KB ve **JSON** (nesne veya dizi) olmalıdır.
- Yerel geliştirmede `WEBHOOK_ALLOW_INSECURE_TARGETS=true` http/yerel adreslere izin verir (üretimde açılamaz).
## Şablonda kullanım ve yedek içerik
Feed çekilemezse (zaman aşımı, HTTP hatası, JSON olmayan yanıt, devre açık) **gönderim durmaz**; feed değeri boş kalır.
Bu yüzden her feed kullanımına yedek verin:
```liquid
{% if feed.profil %}{{ feed.profil.puan }} puanın var!{% else %}Puanlarını keşfet!{% endif %}
```text
Yalnızca şablonda referans verilen feed'ler çekilir (`feed.profil` → yalnızca `profil`). Aynı gönderim içinde aynı
çözümlenmiş URL bir kez istenir.
## Devre kesici
Bir feed art arda 5 kez hata verirse devre 30 sn açılır ve bu sürede istek yapılmaz. Süre dolunca tek deneme
yapılır: başarılıysa devre kapanır, hatalıysa yeniden açılır. Durum tüm worker örnekleri arasında Redis'te paylaşılır.
## Deneme (test et)
Dashboard'da **Dene** veya `POST /v1/apps/{appId}/data-feeds/{feedId}/test` `{"external_id": "…"}`: örnek
kullanıcının değerleriyle önbelleği atlayarak çeker; durum, HTTP kodu, süre, çözümlenmiş URL ve JSON önizlemesi döner.
## İzleme
- Metrikler: `data_feed_fetch_total{status="ok|cached|timeout|error|circuit_open|blocked"}`,
`data_feed_fetch_duration_seconds`.
- Worker logu "data feed çekilemedi; varsayılan içerikle devam" uyarısı feed kimliği, durum ve kısa hata içerir;
URL ve başlıklar loglanmaz.Dynamic Content (içerik tabloları ve `{% lookup %}`)
İçerik tabloları, CSV ile yüklenen satırlardan anahtar sütununa göre seçim yaparak kişiselleştirme sağlar: şehir, mağaza veya ürün bazlı kampanya metinleri gibi. Karar kaydı:…
AI içerik asistanı (Claude)
Mesaj ve şablon editörlerindeki AI asistanı paneli Claude ile başlık/metin önerir, tonu ve uzunluğu ayarlar, A/B varyantları üretir, e-posta konu satırını puanlar ve onaylı çeviri yapar. Karar kaydı:…