# JavaScript API

window.Selwise referansı
Kaynak: https://selwise.com/docs/integration/javascript-api

Script yüklendiğinde (CDN'de otomatik, npm'de `exposeGlobal: true` ile) tarayıcıda `window.Selwise` global nesnesi oluşur. Bu sayfa, nesnenin sunduğu **her** yöntemi imzasıyla, davranışıyla ve örneğiyle; DOM'a yayımlanan olayları; widget'ın tarayıcı depolamasında tuttuklarını ve hata ayıklama anahtarlarını listeler. Kurulum için [Widget Kurulumu](/docs/integration/widget-installation) sayfasına bakın.

## Hazır olma

`window.Selwise` iki aşamada oluşur:

1. **Komut kuyruğu.** Kurulum snippet'i, widget yüklenmeden önce `window.Selwise` üzerine bir **taslak** koyar. Taslak yalnızca on yöntemi içerir ve çağrıları bir kuyruğa yazar: `track`, `trackOrder`, `identify`, `setTraits`, `pushDataLayer`, `grantConsent`, `revokeConsent`, `showConsentPreferences`, `withdrawConsent`, `endJourney`. Widget yüklendiğinde bu çağrılar, `init()` bittikten sonra, **çağrıldıkları sırayla** oynatılır.
2. **Gerçek örnek.** Widget yüklenince taslağın yerine gerçek nesne gelir ve bütün yöntemler çalışır.

Sonuç olarak: yukarıdaki on yöntem sayfanın her yerinden güvenle çağrılabilir. **Değer döndüren** yöntemler (`getVisitorId()`, `getCart()`, `getExperimentVariant()` ...) taslakta **yoktur**; widget yüklenmeden çağırmak `TypeError` verir (ya da `?.` ile sessizce `undefined` döner). Onları yalnızca gerçek örnek hazırken çağırın:

```js
function withSelwise(callback) {
  if (window.Selwise && typeof window.Selwise.getVisitorId === 'function') return callback(window.Selwise);
  var tries = 0;
  var timer = setInterval(function () {
    tries += 1;
    if (window.Selwise && typeof window.Selwise.getVisitorId === 'function') {
      clearInterval(timer);
      callback(window.Selwise);
    } else if (tries > 100) {
      clearInterval(timer); // 10 saniye içinde gelmediyse vazgeç
    }
  }, 100);
}

withSelwise(function (selwise) {
  console.log('Ziyaretçi:', selwise.getVisitorId());
});
```

Veri katmanı push'ları (`window.selwiseLayer.push(...)`) widget'tan önce de eklenebilir: dizi önceden varsa widget açılışta onu işler. Bkz. [Veri Katmanı](/docs/integration/data-layer).

## Yaşam döngüsü

### init

```ts
Selwise.init(config: { siteKey: string; apiUrl?: string; exposeGlobal?: boolean; locale?: string }): Promise<void>
```

Widget'ı başlatır. **CDN kurulumunda otomatik çağrılır**; kendiniz çağırmazsınız. npm paketinde siz çağırırsınız: bkz. [npm paketi](/docs/integration/advanced-installation#npm-paketi). `siteKey` yoksa widget başlamaz ve konsola hata yazar. Tarayıcı dışında (SSR) çağrılırsa hiçbir şey yapmaz. Çözülen söz, yapılandırma yüklenip kuyruğa alınmış çağrılar oynatıldıktan sonra tamamlanır. `locale` için bkz. [Dil](#dil).

### Dil

Widget sayfanın dilini `<html lang>` özniteliğinden okur ve yapılandırmayı o dilde ister. Hesabınızda o dil açıksa metinler o dilde, değilse hesabın varsayılan dilinde gelir. Tarayıcının dili kullanılmaz: Türkçe bir sayfa, İngilizce ayarlı bir tarayıcıda da Türkçe kalır. Hesabın dillerini Selwise hesap yöneticiniz belirler.

```ts
Selwise.setLocale(locale: string): void
```

`<html lang>` dili doğru söylemiyorsa kullanın (örneğin `en`, `en-GB`). npm paketinde dili `init({ locale })` ile vermek en iyisidir; o zaman yapılandırma baştan doğru dilde istenir. Sayfa yüklendikten sonra çağrılırsa widget'ın kendi metinleri (çerez bildirimi düğmeleri, "ürün bulunamadı" gibi) hemen değişir; sizin yazdığınız metinler bir sonraki sayfa yüklemesinde gelir. Bu yöntem kuyruğa alınmaz: yüklenmeden önce çağrılırsa etkisi yoktur.

### destroy

```ts
Selwise.destroy(): void
```

Dinleyicileri, çizilmiş içeriği, modülleri, `history.pushState`/`replaceState` sarmalayıcısını ve `window.Selwise` bağını temizler; bekleyen olayları göndermeyi dener. Tek sayfa uygulamalarında gezinme için **gerekmez** (widget geçişleri kendi yönetir). Uygulama kabuğu kapanırken ya da widget'ı çalışma zamanında durdurmak için kullanılır.

## Takip

### track

```ts
Selwise.track(
  name: string,
  args?: { entityType?: string; entityId?: string; metadata?: Record<string, any> }
): void
```

Bir olay gönderir. `void` döner, hata fırlatmaz ve ağı beklemez; olay bir kuyruğa girer ve toplu gönderilir. Bu yüzden bir render yolundan ya da olay işleyicisinden çağrılabilir. Olay adları ve her olayın alanları için bkz. [Event Referansı](/docs/integration/events).

```js
window.Selwise?.track('add_to_cart', {
  entityType: 'basket',
  metadata: {
    productItemCode: 'SKU-123', // ürün kodu burada, args'ın en üstünde değil
    quantity: 2,
    price: 149.9,
    currency: 'TRY',
  },
});
```

> **Ürün kodu metadata içindedir**
>
> `args` yalnızca `entityType`, `entityId` ve `metadata` taşır; en üste yazılan `productItemCode` gibi bir anahtar **yok sayılır**. Ürün olaylarında kodu `metadata.productItemCode` olarak verin (ürün beslemenizdeki `item_code` ile birebir). Olay adı tanınmıyorsa `custom_event` olarak kaydedilir.

**`metadata` sınırları.** İstemci metadata'yı gönderirken kısaltır: iç içe en çok 3 düzey, nesne başına en çok 25 anahtar, dizi başına en çok 20 öğe, metin değeri başına en çok 256 karakter ve toplam **2 KB**. Sığmazsa kimlik ve değer alanları (`orderId`, `value`, `currency`, `productItemCode`, `products` ...) kalır, süs bilgileri (ürün adı, sayfa başlığı) atılır. `productId`, `productSku` ve `sku` anahtarları kullanımdan kalktığı için atılır.

### trackOrder

```ts
Selwise.trackOrder(order: {
  orderId: string;
  currency?: string; total: number;
  subtotal?: number; discountTotal?: number; shippingTotal?: number; taxTotal?: number;
  status?: string; placedAt?: string;
  visitorId?: string; siteUserId?: string;
  items?: Array<{ productItemCode?: string; name?: string; quantity?: number; unitPrice?: number; totalPrice?: number; metadata?: object }>;
  metadata?: Record<string, any>;
}): Promise<void>
```

Tamamlanan siparişi `POST /orders` ucuna bildirir; son temas atfını, ziyaretçi ve oturum kimliğini, sayfa adresini ve deney atamalarını kendisi ekler. Tüm alanlar, tablo ve örnekler için bkz. [Sipariş Takibi](/docs/integration/order-tracking); HTTP sözleşmesi [Sipariş API'si](/docs/api-reference/orders-api).

- `orderId` boşsa çağrı **sessizce hiçbir şey yapmaz**. Aynı `orderId` tekrar gönderilirse sunucu çift sayım yapmaz.
- Dönen söz, istek **başarısız olsa bile** çözülür; hata yutulur ve **yeniden denenmez**. İsteği kaçırılmaması gereken siparişleri sunucu tarafından da gönderin.
- Sipariş çağrısı çerez onayı kontrolünden **geçmez**.

### Kimlik

```ts
Selwise.identify(userId: string, metadata?: Record<string, any>): Promise<{ success: boolean; merged?: boolean }>
Selwise.setTraits(traits: Record<string, any>): Promise<boolean>
```

`identify`, anonim ziyaretçiyi sizin müşteri kimliğinizle eşleştirir; `userId` boşsa `{ success: false }` döner. `metadata` içindeki `email` bir özellik değildir, kimliğe bağlanır; geçerli bir adres değilse atılır, diğer anahtarlar özellik olur. Aynı kişi, tarayıcı ve adres için onaylanmış ikinci çağrı ağa gitmez. `setTraits` kimliği değiştirmeden özellik yazar ve **tanınmış bir müşteri gerektirir** (önce `identify`); yazılamazsa `false` döner. Ayrıntı ve doğrulama: [Kullanıcı Kimliklendirme](/docs/integration/identify), HTTP sözleşmesi: [Kullanıcı Kimliklendirme API'si](/docs/api-reference/identify-api).

```js
window.Selwise?.identify('MUSTERI-1001', { email: 'ayse@example.com', plan: 'premium' });
window.Selwise?.setTraits({ favoriKategori: 'ayakkabi' });
```

Kimliği unutmak (çıkış) için ayrı bir yöntem yoktur; veri katmanına `user_logout` olayını gönderin: [Kullanıcı Kimliklendirme](/docs/integration/identify#çıkış).

### Kimlik okuyucuları

```ts
Selwise.getSiteUserId(): string | undefined  // identify ile atanan müşteri kimliği
Selwise.getVisitorId(): string               // kalıcı anonim ziyaretçi kimliği
Selwise.getSessionId(): string               // oturum kimliği
```

Bunları sunucu tarafı sipariş ya da olay gönderirken (`visitorId`, `sessionId`) kullanabilirsiniz; bkz. [Sipariş API'si](/docs/api-reference/orders-api).

## Yolculuk (journey)

```ts
Selwise.getJourneyId(): string | null
Selwise.getJourneyState(): { journeyId: string | null; age: number | null; isValid: boolean }
Selwise.endJourney(): void
```

Yolculuk, sayfalar arasındaki olay zincirini tek bir kimliğe bağlar ve en çok 30 dakikalık süreyle sınırlıdır; süre dolunca yeni bir yolculuk başlar. `endJourney()` mevcut yolculuğu kapatır ve bir sonraki olayda yenisi başlar. `getJourneyState()` hata ayıklama içindir.

```js
const journey = window.Selwise?.getJourneyState();
if (journey?.isValid) console.log('Aktif yolculuk:', journey.journeyId);
```

## Deneyler (A/B test)

```ts
Selwise.getVariant(experimentId: string): object | undefined
Selwise.getExperimentVariant(experimentId: string): string | null
Selwise.getActiveExperiments(): object[]
```

Ziyaretçiye atanan kolu okur. Atama sunucuda hesaplanır (ziyaretçi kimliğinin özeti; aynı ziyaretçi her seferinde aynı kolu alır) ve `selwise_experiments` anahtarında önbelleğe alınır. Atama, widget'ın yapılandırmayı yüklemesinden **sonra** hazır olur: çok erken çağırırsanız `getExperimentVariant()` `null`, `getVariant()` `undefined`, `getActiveExperiments()` boş dizi döner. Kendi arayüzünüzü kola göre değiştirmek için [Hazır olma](#hazır-olma) bölümündeki bekleme kalıbını kullanın:

```js
withSelwise(function (selwise) {
  var variant = selwise.getExperimentVariant('EXPERIMENT_ID');
  if (variant === 'VARIANT_ID') {
    // B kolunun arayüzünü göster
  }
});
```

**Bir kolu zorlamak (QA).** Adrese `?selwise_variant=DENEY_ID:KOL_ID` ekleyin (birden çok deney için parametreyi tekrarlayın). Widget o kolu gösterir, saklamaz ve o ziyaret için **hiçbir sayı yazmaz**; parametreyi kaldırmak zorlamayı bitirir. Atama ucunun karşılığı: [Widget'ın Kendi Kullandığı Uçlar](/docs/api-reference/widget-endpoints#deney-ataması).

## Veri katmanı

```ts
Selwise.pushDataLayer(data: SelwiseDataLayer): void
Selwise.getDataLayer(): SelwiseDataLayer[]
```

`pushDataLayer`, `window.selwiseLayer.push()` ile aynı işi yapar. Panelde **Data Layer** entegrasyonu kapalıysa çağrı yok sayılır (test modunda konsola uyarı yazılır). `getDataLayer()` son 500 kaydı döndürür; entegrasyon kapalıysa boş dizi. Zarf yapısı ve olay adları: [Veri Katmanı](/docs/integration/data-layer).

## Sepet

```ts
Selwise.getCart(): { known: boolean; total: number; itemCount: number; currency: string | null }
```

Selwise'in bildiği sepeti döndürür. `known` en önemli alandır: yalnızca sepetin **tamamı** bilindiğinde `true` olur (veri katmanının `basket.total` alanı, `cart_view` olayı ya da Akinon, Shopify, IdeaSoft ve T-Soft'ta mağazanın kendi sepeti). Yalnızca sepete ekleme ve çıkarma olaylarından tutulan bir sayaçta `false` olur; bu durumda tutarı ziyaretçiye yazmayın, hedef çubuğu da yazmaz.

Sepet değiştikçe `document` üzerinde `selwise:cart` olayı tetiklenir; `detail` alanı `getCart()` ile aynı şekildedir:

```js
document.addEventListener('selwise:cart', function (event) {
  var cart = event.detail;
  if (!cart.known) return;
  console.log('Sepet:', cart.total, cart.currency, cart.itemCount);
});
```

Sepetin nasıl ölçüldüğü için bkz. [Hedef Çubuğu](/docs/widgets/goal-bar) ve [Veri Katmanı](/docs/integration/data-layer).

## Onay (consent)

```ts
type ConsentState = { necessary: boolean; analytics: boolean; marketing: boolean; preferences: boolean };

Selwise.getConsentState(): ConsentState | null
Selwise.grantConsent(categories?: Partial<ConsentState>): void
Selwise.revokeConsent(categories?: (keyof ConsentState)[]): void
Selwise.showConsentPreferences(): void
Selwise.withdrawConsent(): void
```

| Yöntem | Ne yapar |
| --- | --- |
| `getConsentState()` | Kayıtlı kararı döndürür. Ziyaretçi **henüz cevap vermediyse `null`**: "hiçbir şeye izin vermedi" ile "sorulmadı" farklı durumlardır |
| `grantConsent()` | Argümansız **tüm** kategorilere izin verir. `{ marketing: false }` gibi bir kısmi nesne, verilmeyenleri `true` bırakır ve `necessary` her zaman `true`'dur |
| `revokeConsent()` | Argümansız tüm isteğe bağlı kategorileri geri çeker. `['marketing']` yalnızca verilenleri; `necessary` geri çekilemez |
| `showConsentPreferences()` | Banner'ı yeniden açar |
| `withdrawConsent()` | Kararı tamamen unutur, sunucuya geri çekme kaydı yazar ve banner'ı yeniden açar |

Üçü de veri katmanından **bağımsız** çalışır: veri katmanı kapalı olsa da karar yazılır ve bekletilen olaylar serbest bırakılır. Karar sunucuya da bildirilir (`action: api`). Ayrıntı ve kendi onay çözümünüzle entegrasyon: [Onay Yönetimi](/docs/integration/consent).

## Bildirim izni

```ts
Selwise.requestPushPermission(): Promise<string>
Selwise.pushPermissionState(): Promise<string>
Selwise.revokePushPermission(): Promise<string>
```

Tarayıcı bildirimleri (web push) için. Sonuç `granted`, `denied`, `default` (istemi kapattı) ya da `unsupported`. **`requestPushPermission()` gerçek bir kullanıcı hareketinden (bir düğmenin tıklaması) çağrılmalıdır**: Chrome hareket dışı bir isteği sessizce reddeder, ve bir site tarayıcıdan **ömür boyu bir** izin istemi alır; ikinci kapatmadan sonra Chrome ve Firefox kaynağı kalıcı engeller. Bu yüzden izin sayfa yüklenirken hiç istenmez. Kanalda bildirim anahtarları yoksa ya da tarayıcı desteklemiyorsa `unsupported` döner. Hizmet çalışanının kurulumu: [Widget Kurulumu](/docs/integration/advanced-installation#web-bildirimi-için-service-worker).

```js
document.querySelector('#bildirim-ac').addEventListener('click', function () {
  window.Selwise.requestPushPermission().then(function (state) {
    console.log('Bildirim izni:', state);
  });
});
```

## DOM olayları

Widget, kendi davranışını sayfanıza şu olaylarla bildirir:

| Olay | Hedef | `detail` | Ne zaman |
| --- | --- | --- | --- |
| `selwise:cart` | `document` | `getCart()` şekli | Sepet bilgisi değiştiğinde |
| `selwise:display` | Çizilen kök öğe (köpürmez) | yok | Bir yüzey (popup, hedef çubuğu ...) gerçekten ekrana geldiğinde; gösterim ölçümü buna bağlıdır |
| `selwise:quick-view` | `window` | `{ source, widgetId, product }` | Bir öneri ya da arama kartında "hızlı bakış" davranışı seçildiğinde; kendi hızlı bakış penceresini çizmek isteyen mağaza dinler |
| `selwise:subscription-inactive` | `window` | `{ message }` | Yapılandırma isteği `403` döndüğünde: widget durur ve hiçbir şey çizmez |
| `selwise:onsite-error` | `window` | `{ actionId, message }` | Bir sayfa üstü deneyin özel JavaScript eylemi hata verdiğinde; hata sizin sayfanızın `window.onerror`'una değil bu olaya gider |

> **403 her zaman abonelik demek değildir**
>
> Widget, yapılandırma ucundan gelen **her** `403` cevabını bu olayla bildirir ve durur. Gerçek neden alan adının doğrulanmamış olması, `Origin`'in kanalın alan adlarından biri olmaması ya da hesap teslimatının kapalı olması olabilir; ayrım `detail.message` ve Ağ sekmesindeki yanıt gövdesindedir. Bkz. [Takip Sorunları](/docs/troubleshooting/tracking-issues).

## Depolama anahtarları

Widget tarayıcı depolamasında yalnızca `selwise_` önekli anahtarlar kullanır. `localStorage` kullanılamıyorsa (gizli sekme, engelli depolama) sırayla `sessionStorage`'a, sonra sayfa belleğine düşer; bu durumda ziyaretçi kimliği ve deney atamaları sayfa yenilenince sıfırlanır.

| Anahtar | Amaç | Depolama |
| --- | --- | --- |
| `selwise_vid` | Ziyaretçi kimliği | localStorage |
| `selwise_sid` | Oturum kimliği | sessionStorage |
| `selwise_suid`, `selwise_supid` | `identify` ile atanan müşteri kimliği ve Selwise'in dahili profil kimliği | localStorage |
| `selwise_identified`, `selwise_user_traits`, `selwise_merged_vids` | Onaylanmış identify işareti, özellik önbelleği, birleşen ziyaretçi kimlikleri | localStorage |
| `selwise_journey_id`, `selwise_journey_created`, `selwise_journey_seq` | Yolculuk kimliği, başlangıcı ve olay sırası | localStorage |
| `selwise_experiments`, `selwise_experiment_conversions`, `selwise_experiment_exposures` | Deney atamaları ve sayılmış dönüşüm ve gösterimler | localStorage |
| `selwise_frequency_caps` | Gösterim sıklığı sınırı | localStorage |
| `selwise_dismissed_<kimlik>` | Ziyaretçinin kapattığı kampanyanın sürüm özeti ve kapatma zamanı; kimlik içermez. Kampanyanın "Kapatıldıktan sonra" ayarı oturum ise sessionStorage, gün sayısı ise localStorage (kalıcı depolamaya izin yoksa oturumda) | sessionStorage / localStorage |
| `selwise_consent_<siteKey>` | Çerez onayı kararı (**Cookie Consent → Policy** sekmesinde saklama anahtarını değiştirebilirsiniz) | localStorage |
| `selwise_last_touch*`, `selwise_correlation_*` | Gelir atfı için son temas ve ilişkilendirme kimliği | sessionStorage |
| `selwise_test_mode`, `selwise_debug` | Test modu ve hata ayıklama bayrakları | localStorage |
| `selwise_editor_*` | Panelden açılan görsel editör oturumu | sessionStorage |

Olay kuyruğunun taşmış kısmı tarayıcıda IndexedDB'de bekler ve bir sonraki açılışta gönderilir.

## Test ve hata ayıklama

```js
// Test modu: test işaretli kampanya, widget ve zenginleştirme kuralları da çizilir
localStorage.setItem('selwise_test_mode', 'true');

// Hata ayıklama: ayrıntılı konsol günlükleri
localStorage.setItem('selwise_debug', 'true');

location.reload();
```

Test modunu adresten de açabilirsiniz: **`?selwise_test_mode=true`** (ya da `=1`) ekleyin. Widget bayrağı yazar ve parametreyi adresten **siler** (geçmişi yenilemeden); `=0` ya da `=false` bayrağı kapatır. Bir test bağlantısını ekip arkadaşınıza göndermenin yolu budur. Kapatmak için ilgili anahtarı `removeItem` ile silin. Ayrıntılar: [Önizleme ve Test Modu](/docs/product-enrichment/testing), [Takip Sorunları](/docs/troubleshooting/tracking-issues).

Hata ayıklama kapalıyken widget konsola **yalnızca** gerçek hataları yazar (örneğin `siteKey` eksikliği); test modu ya da hata ayıklama açıkken tanılama günlükleri de yazılır.
