# Widget Kurulumu

Script, etiket yöneticisi, öznitelikler ve tek sayfa uygulamaları
Kaynak: https://selwise.com/docs/integration/widget-installation

Selwise widget'ı sitenize tek bir `<script>` etiketiyle, bir etiket yöneticisiyle ya da npm paketiyle kurulur. Bu sayfa script ve etiket yöneticisi yollarını, script'in aldığı öznitelikleri, tek sayfa uygulamalarındaki davranışı ve kurulumu geri alma yollarını anlatır. npm paketi, sürümleme ve önbellek kuralları ve içerik güvenlik politikası (CSP) için [npm, Önbellek ve CSP](/docs/integration/advanced-installation); en kısa yol için [Script'i Sitenize Ekleyin](/docs/getting-started/installing-widget).
## Ön koşul: kanal, kanal anahtarı ve doğrulama

Kurulumdan önce panelde bir **web kanalı** tanımlı olmalı. Kanalı ekleme: [Kanal Ekleme](/docs/channels/adding-channels). Kanalın **Channel Key** (Kanal Anahtarı) değeri **Kanallar → Kanal Özeti** (Channels → Channel Overview) ekranındaki kartta durur; tüm kurulum bu anahtarla çalışır.

> **Kanal anahtarı gizli değildir**
>
> `siteKey` tarayıcıda görünür ve bir sır değildir. Güvenlik gizlilikten değil **alan adı doğrulamasından** gelir: Selwise, içerik isteklerini yalnızca doğrulanmış alan adınızın `Origin`/`Referer` başlığından kabul eder. Bkz. [Kimlik Doğrulama ve Erişim](/docs/api-reference/authentication).

Kanal doğrulanmamışsa widget içerik çizmez ve olaylar kaydedilmez. Kurulumdan sonra [Alan Adı Doğrulama](/docs/channels/domain-verification) adımını tamamlayın.
## CDN ile kurulum

Aşağıdaki satırları sitenizin **tüm sayfalarında**, `<head>` içinde, mümkün olduğunca en üstte yerleştirin. Kod `<head>` dışına konursa izleme çalışır ama değişiklikler sayfa çizildikten sonra uygulanır. `SITE_KEY` yerine kendi anahtarınızı yazın.

```html
<link rel="preconnect" href="https://widget.selwise.com" crossorigin>
<link rel="preconnect" href="https://api.selwise.com" crossorigin>
<script>window.Selwise=window.Selwise||{};window.Selwise.q=window.Selwise.q||[];['track','trackOrder','identify','setTraits','pushDataLayer','grantConsent','revokeConsent','showConsentPreferences','withdrawConsent','endJourney'].forEach(function(m){if(!window.Selwise[m])window.Selwise[m]=function(){window.Selwise.q.push([m,arguments])}});</script>
<script async src="https://widget.selwise.com/client.js" data-site-key="SITE_KEY"></script>
```

Script yüklendiğinde `data-*` özniteliklerini okuyarak **otomatik başlatılır**; ayrıca `Selwise.init()` çağırmanıza gerek yoktur ve `window.Selwise` nesnesi kendiliğinden oluşur.

Üstteki üç satır birlikte çalışır:

| Satır | Ne yapar |
| --- | --- |
| `preconnect` (iki satır) | İki hosta DNS ve TLS el sıkışmasını erken başlatır; 100-300 ms kazanç. Atlanabilir, ama bedelsizdir |
| Komut kuyruğu | `async` yüklemede `window.Selwise` henüz yokken yapılan `trackOrder`, `identify` gibi çağrıları tamponlar ve widget hazır olunca **sırayla** oynatır. **Bu satır olmadan `async` sipariş kaybettirir**: `window.Selwise?.trackOrder(...)` çağrısı widget gelmeden çalışırsa `?.` hatasız sessizce hiçbir şey yapmaz |
| `async` script | HTML ayrıştırmasını durdurmaz. Senkron hâli canlı bir vitrinde 210 ms ölçüldü (yavaş mobil bağlantıda 1-2 sn) |

Komut kuyruğunun garantileri: çağrılar widget'ın `init()` işi (yapılandırma ve onay durumu yüklenmesi) **bittikten sonra**, çağrıldıkları sırayla oynatılır; bir kez oynatılan çağrı bir daha oynatılmaz; bozuk bir çağrı diğerlerini durdurmaz. Kuyruğa girebilen yöntemler: `track`, `trackOrder`, `identify`, `setTraits`, `pushDataLayer`, `grantConsent`, `revokeConsent`, `showConsentPreferences`, `withdrawConsent`, `endJourney`. `getVisitorId()` gibi **değer döndüren** yöntemler kuyruklanmaz; onları widget yüklendikten sonra çağırın (bkz. [Hazır olma](/docs/integration/javascript-api#hazır-olma)).

> **Tek bir kez ekleyin**
>
> Script'i sayfa başına yalnızca bir kez ekleyin. İki etiket iki widget örneği, yani çift olay ve çift çizim demektir. Tek sayfa uygulamalarında script'i her sayfada yeniden eklemeyin; Selwise sayfa geçişlerini kendisi algılar.

> **Panelden kopyaladığınız kod daha güncel**
>
> Bu sayfadaki örnek yalın sürümdür ve çalışır. Panelin **Kurulum** ekranında verdiği kod ayrıca **sayfa çizilmeden önce gizleme** yapar: içerik değişiklikleri (A/B testleri, kişiselleştirmeler, özel script CSS'i) orijinal sayfa görünmeden uygulanır. Bu yalnızca kod `<head>` içinde, mümkün olduğunca en üstteyse çalışır. Kurulumunuzun güncel olup olmadığını kanal sayfasındaki **Kurulum kodunu denetle** düğmesiyle görürsünüz.
## Script öznitelikleri

| Öznitelik | Zorunlu | Açıklama |
| --- | --- | --- |
| `data-site-key` | Evet | Kanalın anahtarı. Yoksa widget **başlamaz** ve konsola `No site key — widget not started` hatası yazar |
| `data-api-url` | Hayır | API taban adresi. **CDN sürümünde etkisizdir**: adres derleme sırasında `https://api.selwise.com` olarak sabitlenir ve bu öznitelik onu geçersiz kılamaz. Özel bir adres gerekiyorsa bkz. [npm paketi](#npm-paketi) |
| `data-env` | Hayır | `development` verilirse geliştirici tanılama araçları açılır. Üretimde kullanmayın |

`data-sentry-dsn`, `data-sentry-environment` ve `data-sentry-release` Selwise'in kendi hata raporlaması içindir; mağaza kurulumunda kullanılmaz.

### Script etiketinin bulunması

Widget kendi etiketini `document.currentScript` ile bulur. Bu değer bir etiket yöneticisinden enjekte edilen scriptte, bir modül scriptinde ve olay işleyicilerinde `null`'dır; bu durumda widget `data-site-key` taşıyan `script` etiketini kendisi arar (iki tane varsa sonuncuyu alır). Yani etiket yöneticisiyle kurulum çalışır.
## Etiket yöneticisi (Google Tag Manager) ile kurulum

GTM'de **Custom HTML** türünde yeni bir etiket oluşturun. Aşağıdaki kod, komut kuyruğunu kurar ve script'i enjekte eder:

```html
<script>
  (function () {
    window.Selwise = window.Selwise || {};
    window.Selwise.q = window.Selwise.q || [];
    ['track','trackOrder','identify','setTraits','pushDataLayer','grantConsent','revokeConsent','showConsentPreferences','withdrawConsent','endJourney']
      .forEach(function (m) {
        if (!window.Selwise[m]) window.Selwise[m] = function () { window.Selwise.q.push([m, arguments]); };
      });

    if (document.querySelector('script[data-site-key]')) return; // ikinci kez eklenmesin
    var s = document.createElement('script');
    s.async = true;
    s.src = 'https://widget.selwise.com/client.js';
    s.setAttribute('data-site-key', 'SITE_KEY');
    document.head.appendChild(s);
  })();
</script>
```

- **Tetikleyici:** **Initialization - All Pages** (ya da **All Pages - Page View**). Tek bir tetikleyici yeter; etiketin sayfa başına bir kez çalıştığından emin olun (**Tag firing options** ayarında *sayfa başına bir kez*).
- **Çerez izni.** Selwise kendi onay denetimini yönetir ([Onay Yönetimi](/docs/integration/consent)); etiketi GTM'in onay modu arkasına koyarsanız widget, onay verilene kadar hiç yüklenmez ve onay öncesi olayları bekletemez. Kendi onay çözümünüz varsa `grantConsent()` / `revokeConsent()` ile kararı bildirin.
- **Gizleme garanti edilmez.** GTM etiketleri çoğunlukla sayfanın ilk çiziminden sonra çalışır; bu yüzden A/B test ve kişiselleştirme değişiklikleri kısa süre orijinal sayfa görünerek uygulanabilir. İlk çizimden önce gizleme için panelin verdiği kodu ayrıca doğrudan sitenizin `<head>` içine ekleyin. Kanal sayfası bu kurulumu **GTM ile kurulu** olarak gösterir.
- **Verify Now**, GTM ile kurulan etiketi tanır: ham HTML'de bulamazsa sayfanın GTM kapsayıcılarının yayımlanmış sürümüne bakar (kapsayıcıyı yayımlayın).
- GTM'in kendi dataLayer'ı (`window.dataLayer`) olduğu gibi okunur: bkz. [Veri Katmanı](/docs/integration/data-layer).
- GTM etiketi geç yüklenir; bu yüzden `trackOrder` gibi çağrıların komut kuyruğundan geçmesi **şarttır**.
## npm paketi

Script etiketi yerine bir paket yöneticisiyle kurulum; dağıtılan dosyaların önbelleği, CSP ve service worker ayrı sayfada: [npm, Önbellek ve CSP](/docs/integration/advanced-installation).
## Başlatma akışı

Script yüklendiğinde widget şu istekleri bu sırayla ve çoğunu **paralel** yapar; hepsi `https://api.selwise.com/api/v1` altındadır:

1. `GET /public/sites/:siteKey/config?p=4`: kampanya, öneri, takip, arama, zenginleştirme, deney ve tema yapılandırmasının toplu yanıtı ([Public API](/docs/api-reference/bootstrap-endpoints#açılış-config)). Başarısız olursa widget `tracking-config`, `campaigns` ve `recommendations` uçlarına tek tek düşer.
2. `GET /public/sites/:siteKey/scripts?path=<sayfa yolu>`: o sayfaya tanımlı özel script'ler.
3. `GET /public/sites/:siteKey/integrations`: veri katmanı ve entegrasyon ayarları.
4. Yapılandırma geldikten sonra: deney ataması (`GET /public/experiments/assign`) ve segment değerlendirmesi (`POST /public/segments/evaluate`), yalnızca bunları kullanan kampanya ya da deney varsa.
5. Olaylar (`POST .../events/batch`), bir sayfa görüntülemeyle başlar. Yalnızca etkin özelliğin parçası indirilir.
6. Ürün sayfasında zenginleştirme kuralı varsa `GET .../enrichments?code=...`; kampanya metni ürün yer tutucusu kullanıyorsa `GET .../product-facts?code=...`; kanalda site içi teslimat yapan senaryo varsa `GET .../scenarios/inbox`.

Hepsinin istek ve yanıt ayrıntısı: [Public API](/docs/api-reference/public-api).
## Tek sayfa uygulamaları ve sayfa geçişleri

Widget, sayfa yenilemeden gezinen mağazalarda (Next.js, PZ Next, Turbo, React Router, Vue Router) URL değişimini kendisi algılar: `history.pushState` ve `history.replaceState`'i sarmalar ve `popstate` olayını dinler. URL (hash dahil) değiştiğinde:

1. Önceki sayfanın çizdiği kampanya kökleri, arama ve öneri modülleri, zenginleştirme blokları, sayfa üstü deney, Tab Talk ve özel script'ler **temizlenir**.
2. Veri katmanı yeniden kurulur; olay kuyrukları **atılmaz** (sayfadan ayrılırken sıradaki olaylar kaybolmaz).
3. 100 ms sonra yeni sayfa için arama, öneri, zenginleştirme ve kampanya değerlendirmesi yeniden yapılır; sayfa görüntüleme sayılır.

Yani `Selwise.init()`'i yeniden çağırmayın, script'i yeniden eklemeyin. Kendi router'ınız `history` API'sini kullanmıyorsa (yalnızca `hashchange` ya da özel bir mekanizma) geçiş algılanmaz; bu durumda `history.pushState` ile URL'i güncelleyin.

Turbo (Hotwire) gibi sayfa değiştirme kütüphaneleri her gezintide `<head>`'i ya da `<body>`'yi yeniden yazıyorsa script etiketinin **yeniden çalışmadığından** emin olun: widget bir sayfada iki örnek başlatılmasına karşı korunmaz, ikinci bir örnek çift olay ve çift çizim demektir. Etiket yöneticisiyle kuruyorsanız etiketin ateşleme seçeneğini sayfa başına bir kez olacak şekilde tutun.
## Kurulumu doğrulayın

1. **Alan adı doğrulaması** yapın. Doğrulanmamış kanalda widget içerik çizmez.
2. Tarayıcı konsolunda debug modunu açın:

```js
localStorage.setItem('selwise_debug', 'true');
location.reload();
```

3. DevTools **Network** sekmesinde şunları görün: `config?p=4` (`200`), `scripts?path=...`, `integrations`, sonra `events/batch` (`200`, yanıtta `"success": true`). Başarılı bir `config` yanıtı tek başına widget'ın yüklendiğini ve kanalın doğrulandığını kanıtlar.
4. Konsolda `window.Selwise` bir nesne olmalı (`window.Selwise.getVisitorId()` bir kimlik döndürmeli).

Bir şey yolunda gitmezse adım adım teşhis için [Takip Sorunları](/docs/troubleshooting/tracking-issues) ve [Widget Görünmüyor](/docs/troubleshooting/widget-not-showing) sayfalarına bakın.
## Kurulumu geri alma ve devre dışı bırakma

| Amaç | Yol |
| --- | --- |
| Widget'ı tamamen kaldırmak | `<script>` etiketini (ve komut kuyruğu satırını) şablonlarınızdan silin. Ziyaretçi tarafında `selwise_` önekli depolama anahtarları kalır ve zararsızdır |
| Çalışan bir sayfada geçici durdurmak | `window.Selwise.destroy()`: dinleyicileri, çizilmiş içeriği, modülleri ve `history` sarmalayıcısını geri alır; örnek `window.Selwise`'tan silinir |
| Kampanyaları yayından almak | Panelde kampanyayı **Paused** yapın ya da tarih penceresini kapatın; widget script'i olduğu gibi kalır |
| Çerez onayı gelene kadar beklemek | **Cookie Consent → Policy** sekmesinde **Require consent before tracking** ve **Hold events until the answer** ayarlarını açın; script yüklü kalır, olaylar onay gelene kadar gönderilmez |
| Domain'i değiştirmek | Kanal alan adını değiştirmek doğrulamayı sıfırlar; yeni alan adı doğrulanana kadar widget orada çalışmaz |

Ziyaretçide kalan depolama anahtarları: `selwise_vid`, `selwise_sid`, `selwise_suid`, `selwise_journey_*`, `selwise_experiments`, `selwise_frequency_caps`, `selwise_consent_<siteKey>`, `selwise_test_mode`, `selwise_debug` (tam liste: [JavaScript API](/docs/integration/javascript-api#depolama-anahtarları)). Bir kullanıcının silme talebinde bunları sizin temizlemeniz gerekmez; sunucu tarafı silme için [KVKK ve GDPR Talepleri](/docs/customers/gdpr).
