# Event Takibi

Ekran adları ve olaylar
Kaynak: https://selwise.com/docs/mobile/tracking

Mobil uygulamada ekran adlandırma, olay gönderme ve sipariş bildirme. Kimlik, onay ve kuyruk ayrı bir sayfadadır: [Kimlik, Onay ve Kuyruk](/docs/mobile/identity-and-queue).

## Ekran adları

Web'de sayfa hedefleme URL'e dayanır; uygulamada URL yoktur. Her ekran için **tek ve sabit** bir sentetik değer kullanın ve ekrana girildiğinde bildirin:

```ts
selwise.trackScreenView('app://home');       // bağlamı kurar ve page_view gönderir
selwise.setScreen('app://product');          // yalnızca bağlamı kurar, olay göndermez
```

`setScreen` o andan sonra kuyruğa alınan **her olaya** ekran adını işler; kuyruk ekran değişiminde yeni bir istek açar, böylece bir parti hiçbir zaman iki ekranı karıştırmaz. `trackScreenView` sepet bildirilmişse `page_view` üstverisine `cartSource: host` ekler; **Channel Overview** ekranındaki **Cart value** kartı bu damgayla sepetin ölçülüp ölçülmediğini söyler.

> **Ekran adları kararlı olmalı**
>
> Ekran adına dinamik değer koymayın (`app://product/12345` gibi). Her ürün için ayrı bir "sayfa" üretmek sayfa hedeflemeyi ve huni analizini kullanılamaz kılar. Ürün kimliği ekran adında değil olayın kendi alanında taşınır.

### Panelde hedefleme nasıl eşleşir

Kampanya ve öneri şeridinin **Page targeting** alanındaki desenler ekran adına şöyle uygulanır:

| Desen | Eşleşme |
|---|---|
| `app://product` | Ekran adı bu değere eşit **veya bu değeri içeriyor** (`app://product-list` de eşleşir) |
| `app://account/*` | `*` joker olarak çalışır; tüm ifadeyle eşleşmelidir |
| `regex:^app://product$` | Düzenli ifade, büyük/küçük harf duyarlı, en çok 500 karakter |

Katı eşleşme istiyorsanız `regex:` kullanın. Aynı kural `excludeUrls` için de geçerlidir. Sayfa türü (`home`, `product`, `category`, `search`, `checkout`, `cart`, `account`, `other`) kuralı ise ekranı yalnızca siz bildirirseniz çalışır: `getSurfaces(url, { pageType: 'product' })`. Bildirmezseniz sayfa türü kuralı **açık** kalır, yani kampanya her ekranda görünür. Ayrıntı: [Kampanya ve Widget](/docs/mobile/surfaces).

## Olay gönderme

```ts
track(name: string, options?: TrackOptions): void

interface TrackOptions {
  entityType?: EntityType;          // varsayılan: 'custom'
  entityId?: string;
  productItemCode?: string;         // besleme item_code ile aynı olmalı
  metadata?: Record<string, string | number | boolean | null>;
  timestamp?: number;               // ms; varsayılan şu an
  correlationId?: string;
  parentEventId?: string;
}
```

`track()` **asla hata fırlatmaz ve ağı beklemez**; render sırasında ya da dokunma işleyicisinde güvenle çağırılır. Olay kuyruğa girer ve arka planda gönderilir.

```ts
selwise.trackProductView('SKU-12345');
selwise.trackAddToCart('SKU-12345', { quantity: 1, price: 749.9, currency: 'TRY' });
selwise.trackRemoveFromCart('SKU-12345');

selwise.track('checkout_begin', {
  entityType: 'checkout',
  metadata: { total: 1499.7, currency: 'TRY', itemCount: 3 },
});
```

Kısayollar `product_view`, `add_to_cart` ve `remove_from_cart` olaylarını `entityType: 'product'` ile gönderir; ikinci parametre `metadata`'dır. `quantity` ya da `price` gibi alanlar `TrackOptions`'ın kendisinde değil, **`metadata` içinde** verilir.

Kurallar:

- **Olay adı kanonik olmalı.** Sunucu kanonik bir olay sözlüğünü tanır ([Event Referansı](/docs/integration/events)); tanımadığı ad `custom_event`'e dönüştürülür ve sizin adınız kaybolur. Kendi olayınız için `track('custom_event', { metadata: { eventName: 'kupon_kullanildi' } })` yazın.
- **`metadata` düz olmalı:** değerler yalnızca metin, sayı, boolean ve `null` olabilir; olay başına serileştirilmiş boyut en çok 2 KB'tır. Sınırı aşan tek bir olay partinin tamamının `400` ile reddedilmesine yol açar ve SDK, `408` ile `429` dışındaki `4xx` yanıtları kalıcı sayıp partiyi yeniden denemeden siler.
- **Ürün kodu besleme ile aynı olmalı.** `itemCode`, ürün beslemenizdeki `item_code` değeridir (çoğu katalogda varyant SKU'su). Eşleşmezse ürün bazlı raporlar ürünü düşürür. Sepet kodunu (`cartCode`) ya da grup kodunu (`groupCode`) kimlik diye göndermeyin. Bkz. [Varyant Gruplama](/docs/product-feeds/variant-grouping).
- `entityType` değerleri: `campaign`, `widget`, `enrichment`, `recommendation`, `search`, `script`, `page`, `product`, `basket`, `checkout`, `user`, `custom`.

### SDK'nın kendiliğinden gönderdikleri

| Çağrı | Gönderilen olay (`entityType`) |
|---|---|
| `trackScreenView` | `page_view` (`page`) |
| `identify` | `identify` (`user`), yalnızca kullanıcı değiştiyse |
| `trackSurfaceView` / `trackSurfaceClick` / `dismissSurface` | `impression` / `click` / `close` (`campaign`) |
| `trackGoalReached` | `goal_reached` (`campaign`) |
| `trackRecommendationImpression` / `trackRecommendationClick` | `widget_impression` / `product_click` (`recommendation`) |
| `search` | `search_query` ya da `search_zero_results` (`search`) |
| `trackSearchClick` | `product_click` (`search`) |
| `trackEnrichmentView` / `trackEnrichmentClick` | `impression` / `click` (`enrichment`) |
| `subscribeNewsletter` | `user_signup` (`campaign` ya da `custom`) |

## Sipariş

Ciro atfı siparişten okunur; her tamamlanan sipariş için `trackOrder` çağrılmalıdır. `track()`'ten farklı olarak **beklenir**: kayıp bir sipariş kayıp bir ciro atfıdır.

```ts
trackOrder(order: OrderInput): Promise<{ success: boolean; created: boolean; id?: string }>

const { created } = await selwise.trackOrder({
  orderId: 'ORDER-2026-1881',        // tekilleştirme anahtarı
  total: 1499.7,
  currency: 'TRY',
  items: [
    { productItemCode: 'SKU-12345', quantity: 1, unitPrice: 749.9 },
    { productItemCode: 'SKU-67890', quantity: 2, unitPrice: 374.9 },
  ],
});
```

| Alan | Not |
|---|---|
| `orderId` | **Zorunlu.** Aynı değerle tekrar göndermek siparişi ikiye katlamaz (`created: false` döner). |
| `total` | Zorunlu. Alt toplam, indirim, kargo ve vergi için `subtotal`, `discountTotal`, `shippingTotal`, `taxTotal` isteğe bağlıdır. |
| `currency` | ISO 4217. Vermezseniz sunucu kanalın para birimini kullanır; yanlış tahmin yerine bilerek boş bırakılır. |
| `items[]` | `productItemCode` (besleme `item_code`), `name`, `quantity`, `unitPrice`, `totalPrice`, `metadata`. |
| `status`, `placedAt`, `metadata` | İsteğe bağlı. |

`trackOrder` önce kuyruğu gönderir (son tıklama atfı sipariş öncesi tıklamayı görsün diye), sonra siparişi `deviceType: mobile_app` ile yollar. Hata durumunda `SelwiseApiError` fırlatır; `403` çoğunlukla anahtarda `mobile_write` olmamasıdır, `429` IP başına dakikada 10 sipariş sınırıdır. Siparişi hem WebView köprüsünden hem kendi kodunuzdan bildirirseniz aynı `orderId`'yi kullanın: [WebView Köprüsü](/docs/mobile/webview-bridge). Ayrıntı: [Sipariş Takibi](/docs/integration/order-tracking).

## Sırada ne var

- [Kimlik, Onay ve Kuyruk](/docs/mobile/identity-and-queue)
- [Kampanya ve Widget](/docs/mobile/surfaces)
