Güventik Widget'ı sitenizde ne yapar?
Sitenize üçüncü taraf bir script eklemek bir güven kararıdır. Bu doküman, widget'ın kaynak kodunda gerçekte ne yaptığını — hangi DOM düğümlerini eklediğini, hangi ağ isteklerini attığını, hangi verileri sakladığını ve hangilerini asla toplamadığını — teknik ekiplerin doğrulayabileceği düzeyde açıklar.
boyutu
DOM düğümü
(cookie)
pikseli
IP adresi
fonksiyonu
Özet
Güventik Widget, mağazanızın doğrulanmış müşteri yorumlarını ziyaretçilerinize gösteren ve ödeme sayfasında yorum daveti sunan tek dosyalık bir JavaScript bileşenidir. Sayfanıza tek satırla eklenir:
<!-- Güventik Widget -->
<script src="https://guventik.com/widget/widget.js" data-slug="123"></script>
Teknik açıdan üç cümlelik özeti şudur:
-
İzole çalışır. Tüm arayüz bir
Shadow DOMiçinde oluşturulur. Sitenizin CSS'i widget'ı, widget'ın CSS'i sitenizi etkileyemez. Sayfanızın<body>ağacına tek bir boş<div>eklenir. - Pasif veri toplamaz. Çerez kullanmaz, parmak izi çıkarmaz, form alanlarını, sepet içeriğini veya DOM'unuzu okumaz. Sunucuya yalnızca sayfa URL'si, referrer ve anonim bir oturum kimliği gider.
- Kişisel veri yalnızca açık rızayla alınır. E-posta ve telefon, ziyaretçi bunları ödeme sonrası açılan pencereye kendisi yazdığında ve KVKK onay kutusunu işaretlediğinde toplanır — sayfanızdaki alanlardan okunarak değil.
Widget'ın kaynağı küçültülmemiş (unminified) ve yorum
satırlarıyla birlikte yayınlanır.
widget.js
dosyasını doğrudan açıp bu dokümandaki her iddiayı satır satır
karşılaştırabilirsiniz. Ağ trafiğini de tarayıcı geliştirici
araçlarının Network sekmesinden api.guventik.com
filtresiyle gözlemleyebilirsiniz.
Yükleme akışı
Script bir IIFE olarak paketlenmiştir; global kapsama sızıntı yapmaz. Yürütme sırası tam olarak şöyledir:
-
Yapılandırma okunur. Mağaza kimliği
data-slugözniteliğinden veyawindow.guventikSlugdeğişkeninden alınır. Sunucu adresi,localhostdışında her zamanhttps://api.guventik.com/apiolarak sabittir. -
DOM hazır olması beklenir. Yürütme
DOMContentLoadedsonrasına ertelenir. Bu noktaya kadar sayfanızın render'ına hiçbir müdahale olmaz. -
Oturum kaydı açılır.
POST /api/stores/{id}/sessionsçağrısıyla anonim bir oturum GUID'i alınır vesessionStorage'a yazılır (bkz. § 04). -
Mağaza verisi çekilir. Puan, yorum listesi ve widget
ayarları paralel
fetchistekleriyle alınır. Hepsi salt okunur uçlardır. -
Shadow host oluşturulur.
<div id="__gvntk_host" style="all:initial">düğümü yaratılır ve üzerine bir shadow root iliştirilir. Tüm markup ve stil bu kökün içinde kalır. -
Görünürlük kontrolü yapılır. Widget yalnızca mağaza
aktifse ve sayfanın origin'i mağazanın kayıtlı alan
adıyla eşleşiyorsa
<body>'ye eklenir. Eşleşme yoksa host düğümü DOM'a hiç eklenmez. -
Görünür hale getirilir. Widget, kendi stil dosyası
uygulanana kadar
visibility: hiddendurumunda tutulur; böylece stilsiz bir an (FOUC) yaşanmaz. Stil dosyası hiç gelmezse 3 saniyelik emniyet zamanlayıcısı devreye girer.
Script etiketini async veya defer ile
yüklerseniz tarayıcı document.currentScript
değerini null döndürür ve data-slug
okunamaz. Bu durumda mağaza kimliğini script'ten önce global
değişkenle verin:
<script>window.guventikSlug = "123";</script>
Sitenize etkisi
Bu bölüm, "bu script sitemi yavaşlatır mı, bir şeyleri bozar mı" sorusunun ölçülebilir cevabıdır.
Ağırlık
| Dosya | Ham | Gzip | Not |
|---|---|---|---|
| widget.js | 62 KB | 15,7 KB | Ana bileşen; bağımlılığı yoktur |
| widget.css | 13 KB | 3,6 KB | Shadow root içine yüklenir |
| widget-nav.js | 25 KB | 7,0 KB | Opsiyonel — menü içi rozet varyantı |
Framework, bundler veya çalışma zamanı kütüphanesi yoktur — saf JavaScript. Karşılaştırma için: tipik bir jQuery kopyası gzip'li 30 KB civarındadır.
DOM ayak izi
| Eklenen düğüm | Nereye | Ne zaman |
|---|---|---|
| div#__gvntk_host | body sonu | Her zaman (görünürlük kontrolü geçerse) |
| link[Font Awesome] | head | Yalnızca sayfanızda Font Awesome yoksa |
| link[DM Sans] | head | Yalnızca sayfanızda bu font yoksa |
| div#gvntk-overlay | body sonu | Yalnızca ödeme sayfasında; kapatılınca kaldırılır |
Host düğümüne all: initial uygulanır, yani sitenizden
hiçbir stil miras almaz. Font Awesome ve DM Sans, sayfanızda zaten
varsa tekrar yüklenmez — sürüm çakışması yaratmamak için
bu kontrol bilinçlidir.
Global kapsam
Widget yalnızca üç fonksiyon tanımlar:
window.widgetOpen, window.widgetClose,
window.widgetAction. Başka hiçbir global değişken,
prototip genişletmesi veya polyfill eklenmez.
Tarayıcı API'lerine müdahale
Mağazanız için bir ödeme sayfası URL'si tanımlıysa,
widget history.pushState ve
history.replaceState fonksiyonlarını sarmalar.
Bunun tek amacı, tam sayfa yenilemesi olmadan adım değiştiren
SPA checkout akışlarını yakalamaktır. Sarmalayıcı önce orijinal
fonksiyonu değiştirmeden çağırır, ardından yalnızca URL
eşleşmesini kontrol eder; dönüş değerini veya davranışını
değiştirmez. Ödeme URL'si tanımlı değilse bu sarmalama hiç
yapılmaz.
Hata dayanıklılığı
-
Tüm ağ çağrıları
try/catchve.catch()ile sarılıdır. API erişilemezse widget sessizce görünmez — sayfanıza istisna fırlatmaz,window.onerrortetiklemez. -
Hiçbir istek sayfanın render'ını veya
loadolayını bloke etmez; tamamı asenkronfetch'tir. - Widget konumu, yapılandırılmış kaydırma değerleri ne olursa olsun ekran dışına taşmayacak şekilde sınırlanır (her eksende en fazla görünüm alanının yarısı).
-
Konsola birkaç tanılama satırı yazılır
(
[Widget] v2 loaded…). Destek taleplerini hızlandırmak içindir; hata seviyesinde değildir.
Toplanan veriler
Toplanan alanların tamamı aşağıdadır. Liste veritabanı şemasından birebir çıkarılmıştır; başka bir alan yazılmaz.
Oturum kaydı — Sessions
| Alan | Değer | Nasıl elde edilir |
|---|---|---|
| SessionId | Rastgele GUID | Sunucuda üretilir; kişiden türetilmez |
| StoreId | Mağaza numarası | Script etiketindeki slug |
| StartedAt / LastSeenAt | UTC zaman damgası | Sunucu saati |
| DeviceType | mobile / desktop | User-Agent başlığından sunucu tarafında sınıflandırılır; UA metni saklanmaz |
| WidgetOpened | 0 / 1 | Ziyaretçi paneli fiilen açtığında 1 olur |
| PaymentPageVisited | 0 / 1 | Ödeme sayfası URL eşleşmesinde 1 olur |
| ReviewRequested | 0 / 1 | Ziyaretçi yorum daveti formunu gönderdiğinde 1 olur |
Sayfa görüntüleme — PageViews
| Alan | Değer | Sınır |
|---|---|---|
| PageUrl | window.location.href | 2000 karakterde kesilir |
| Referrer | document.referrer | 2000 karakterde kesilir; boşsa null |
| ViewedAt | UTC zaman damgası | — |
Sayfa URL'si sorgu parametreleriyle birlikte kaydedilir. Checkout URL'lerinizde token, oturum anahtarı veya müşteri kimliği gibi hassas parametreler taşıyorsanız, bunları bize iletmemek için mağaza panelinden yalnızca yol bazlı bir ödeme URL'si tanımlamanızı öneririz.
Oturum kimliğinin saklanması
-
Çerez kullanılmaz. Kimlik tek bir
sessionStorageanahtarında tutulur:gvntk_session_<magazaId>. -
sessionStoragesekme kapandığında silinir — kalıcı takip yoktur. - Depolama origin bazlıdır; kimlik sitenizin origin'inde kalır, başka bir siteye taşınmaz. Siteler arası takip teknik olarak mümkün değildir.
- Kimlik mağaza bazında ayrılır; aynı ziyaretçi başka bir Güventik mağazasında farklı bir oturum kimliği alır.
Kişisel veri — yalnızca açık rızayla
Ödeme sayfasında açılan pencerede ziyaretçi kendi yazdığı e-posta adresini ve (yalnızca SMS onayı işaretlenmişse) telefon numarasını gönderebilir. E-posta için KVKK onay kutusu işaretlenmeden gönder düğmesi etkinleşmez; telefon alanı SMS onayı verilmeden açılmaz bile. İki rıza birbirinden bağımsız kaydedilir. Ayrıntı için KVKK Aydınlatma Metni.
Toplamadıklarımız
Güvenlik incelemelerinde en sık sorulan başlıklar. Aşağıdakilerin hiçbirini yapan kod widget'ta bulunmaz:
Ödeme sayfası tespiti
Yorum daveti penceresi rastgele değil, mağaza panelinden sizin tanımladığınız URL'de açılır. Eşleştirme kuralı katıdır:
- Origin ve yol birebir eşleşmeli. Karşılaştırma büyük/küçük harf duyarsızdır ve sondaki eğik çizgi yok sayılır.
- Tanımladığınız sorgu parametrelerinin tamamı mevcut URL'de aynı değerle bulunmalıdır. Sayfadaki fazladan parametreler eşleşmeyi bozmaz.
-
Ödeme URL'si tanımlı değilse pencere hiçbir koşulda
açılmaz ve
historysarmalaması da yapılmaz. - Pencere oturum başına en fazla bir kez gösterilir; ziyaretçi checkout adımları arasında gidip gelse bile tekrar açılmaz.
- Eşleşme sağlandığında pencere 800 ms gecikmeyle açılır, böylece sayfanızın kendi yükleme animasyonlarının üzerine binmez.
Pencere, ziyaretçinin ödeme akışını kesmez: ödeme formunuzun üzerine modal olarak gelir, kapatılabilir ve kapatıldığında DOM'dan tamamen kaldırılır. Ödeme işleminizin hiçbir aşamasına müdahale etmez.
Güvenlik önlemleri
İstemci tarafı
| Önlem | Uygulama |
|---|---|
| XSS koruması | API'den gelen her dinamik metin (< > & ") DOM'a yazılmadan önce HTML entity'lerine dönüştürülür. Yorum metni, isim ve kupon açıklaması dahil istisnasız uygulanır. |
| Stil izolasyonu | Shadow DOM sınırı iki yönlüdür — sayfanızın stilleri içeri, widget'ın stilleri dışarı sızamaz. |
| Alan adı doğrulaması | Widget yalnızca mağazanın kayıtlı web sitesinde render edilir. Script'i kopyalayıp başka bir alan adına koyan biri mağazanızın arayüzünü elde edemez. |
| Kod çalıştırma yok | API'den gelen değerler veri olarak işlenir (konum, tema, metin). Sunucudan gelen hiçbir içerik kod olarak yorumlanmaz. |
| Kişisel veri maskeleme | Yorumcu adı hem sunucuda hem istemcide temizlenir: @ içeren her parça atılır ve isim Ahmet Y. biçimine indirgenir. |
Sunucu tarafı
| Önlem | Uygulama |
|---|---|
| Taşıma güvenliği | Tüm trafik HTTPS üzerindedir; API yalnızca TLS ile yayınlanır. |
| CORS allowlist | Access-Control-Allow-Origin: * kullanılmaz. İzinli origin listesi veritabanından okunur ve çalışma zamanında yenilenir; yalnızca kayıtlı mağaza alan adları API'ye erişebilir. |
| SQL enjeksiyonu | Tüm sorgular Dapper ile parametrelidir; kullanıcı girdisi hiçbir zaman SQL metnine gömülmez. |
| Hız sınırlama | Kimlik doğrulama uçları IP başına 10 istek/dakika; form gönderim uçları 5 istek/dakika. Aşımda 429 döner. |
| Yetkilendirme | JWT tabanlı, rol kapsamlı (admin / mağaza / kullanıcı ayrı audience). Widget'ın kullandığı uçlar anonimdir ve yalnızca okuma + kendi oturumuna ekleme yapabilir. |
| Güvenlik başlıkları | X-Content-Type-Options: nosniff X-Frame-Options: DENY Referrer-Policy: strict-origin-when-cross-origin X-XSS-Protection: 1; mode=block |
| Hata sızıntısı | Global istisna yakalayıcı, üretimde yığın izi veya SQL parçası döndürmez; ayrıntı yalnızca sunucu günlüğüne yazılır. |
| Veri erişimi | Oturum ve ziyaret verilerini okuyan tüm uçlar kimlik doğrulaması ister. Bir mağaza yalnızca kendi verisini görür. |
Widget'ın anonim olarak erişebildiği yazma işlemleri yalnızca
şunlardır: yeni bir oturum satırı açmak, o oturuma sayfa
görüntüleme eklemek ve o oturumun üç boolean bayrağını 1 yapmak.
Var olan hiçbir kaydı güncelleyemez, silemez veya başka bir
mağazanın verisine dokunamaz — her sorgu StoreId
ile kısıtlıdır.
API yüzeyi
Widget'ın attığı isteklerin tam listesi. Hepsi
https://api.guventik.com adresine gider; başka hiçbir
uç noktaya çağrı yapılmaz.
| Uç nokta | Tür | Ne zaman | Gönderilen |
|---|---|---|---|
| GET /Dealers/Detail | Okuma | Her sayfa yüklemesi | Mağaza slug'ı |
| GET /Comments/Dealer | Okuma | Her sayfa yüklemesi | Mağaza slug'ı |
| POST /AdminWidgetSetting/Get | Okuma | Her sayfa yüklemesi | Boş gövde |
| GET /stores/{id} | Okuma | Her sayfa yüklemesi | Mağaza numarası |
| POST /stores/{id}/sessions | Yazma | Her sayfa yüklemesi | Oturum GUID'i, sayfa URL'si, referrer |
| PATCH …/widget-opened | Yazma | Panel ilk kez açıldığında | Gövde yok |
| PATCH …/payment-visited | Yazma | Ödeme sayfası eşleşmesinde | Gövde yok |
| PATCH …/review-requested | Yazma | Form gönderildiğinde | Gövde yok |
| POST /stores/{id}/review-requests | Yazma | Ziyaretçi formu gönderdiğinde | E-posta, sayfa URL'si |
| POST /contact-consent | Yazma | Ziyaretçi formu gönderdiğinde | E-posta, telefon (varsa), rıza bayrakları |
İlk sekiz çağrı ziyaretçi etkileşimi olmadan gerçekleşir ve hiçbiri kişisel veri taşımaz. Son iki çağrı yalnızca ziyaretçi formu doldurup KVKK onayını işaretlediğinde tetiklenir.
Dış bağımlılıklar ve CSP
Widget üç dış kaynağa bağlıdır. Hiçbiri analitik veya reklam amaçlı değildir; ikisi yalnızca görsel varlıklar içindir.
| Kaynak | Amaç | Koşul |
|---|---|---|
| api.guventik.com | Yorum verisi ve oturum kaydı | Her zaman |
| cdnjs.cloudflare.com | Font Awesome 6.4.0 ikonları | Shadow root'a her zaman; sayfanıza yalnızca Font Awesome yoksa |
| fonts.googleapis.com fonts.gstatic.com | DM Sans yazı tipi | Sayfanızda bu font yoksa |
Content-Security-Policy için gereken izinler
Katı bir CSP uyguluyorsanız aşağıdaki kaynakları eklemeniz yeterlidir:
script-src https://guventik.com;
connect-src https://api.guventik.com;
style-src https://cdnjs.cloudflare.com https://fonts.googleapis.com;
font-src https://fonts.gstatic.com https://cdnjs.cloudflare.com;
img-src https://guventik.com data:;
Ödeme sayfası penceresi, stillerini bir
<style> etiketiyle enjekte eder.
style-src direktifinizde
'unsafe-inline' yoksa bu pencere stilsiz görünür.
Nonce tabanlı bir CSP kullanıyorsanız
bize yazın — dağıtımınıza özel bir
yapılandırma sağlayabiliriz.
Teknoloji yığını
| Katman | Teknoloji | Not |
|---|---|---|
| Widget | Vanilla JS (ES2020) | Framework, bundler veya çalışma zamanı bağımlılığı yok |
| İzolasyon | Shadow DOM v1 | Yerel tarayıcı API'si; polyfill kullanılmaz |
| API | ASP.NET Core (.NET 7) | REST, JSON |
| Veri erişimi | Dapper | Parametreli sorgular |
| Veritabanı | SQL Server | Mağaza bazlı satır izolasyonu |
| Kimlik doğrulama | JWT (HS256) | Rol kapsamlı audience ayrımı |
| E-posta | MailKit / SMTP | Yorum hatırlatmaları ve kupon teslimi |
Tarayıcı desteği: Shadow DOM, fetch ve
sessionStorage destekleyen tüm modern tarayıcılar
(Chrome, Edge, Firefox, Safari — masaüstü ve mobil).
Desteklemeyen bir tarayıcıda widget sessizce devre dışı kalır;
sayfanız etkilenmez.
KVKK ve rıza
- Ayrık rıza. E-posta ve SMS izinleri iki ayrı onay kutusudur. Tek bir "hepsini kabul ediyorum" kutusu yoktur.
- Rıza olmadan alan yok. E-posta onayı işaretlenmeden gönder düğmesi etkinleşmez; SMS onayı işaretlenmeden telefon alanı açılmaz ve boş bırakılır.
- Aydınlatma metni erişilebilir. Her iki onay kutusu da KVKK metnine doğrudan bağlantı içerir.
- Rıza kaydı tutulur. Hangi iznin verildiği, kayıtla birlikte saklanır.
- Veri minimizasyonu. Anonim oturum verisinden kişiye ulaşmak mümkün değildir; IP saklanmaz, çerez yazılmaz, kalıcı tanımlayıcı üretilmez.
- Silme talepleri. Bir ziyaretçi verisinin silinmesini talep ederse e-posta adresi üzerinden ilgili tüm kayıtlar kaldırılır.
Ziyaretçi sözleşmeniz açısından: widget çerez kullanmadığı için çerez rıza bandınıza yeni bir kategori eklemeniz gerekmez. Yine de gizlilik politikanızda Güventik'i bir yorum altyapısı sağlayıcısı olarak anmanızı öneririz.
Kurulum ve kaldırma
Kurulum
Script'i </body> etiketinden hemen önce ekleyin.
Şablonunuzda tek bir yere koymanız yeterlidir — ödeme sayfası dahil
tüm sayfalarda çalışır.
<script
src="https://guventik.com/widget/widget.js"
data-slug="123"
data-position="right"></script>
Doğrulama
- Tarayıcı konsolunda
[Widget] v2 loadedsatırını görün. - Network sekmesinde
api.guventik.comfiltreleyin; § 08'deki listenin dışında istek olmadığını doğrulayın. - Application → Storage'da tek bir
gvntk_session_*anahtarı ve hiç çerez olmadığını görün. - Elements sekmesinde
div#__gvntk_hostdüğümünü ve altındaki#shadow-root'u inceleyin.
Kaldırma
Script satırını silin. Geriye hiçbir iz kalmaz: çerez yazılmadığı
için temizlenecek çerez yoktur, sessionStorage anahtarı
sekme kapandığında kendiliğinden silinir ve DOM'a eklenen düğümler
sayfa yenilendiğinde yeniden oluşturulmaz. Servis worker, kalıcı
önbellek veya arka plan görevi bırakılmaz.
Güvenlik ekipleri için sık sorulanlar
Sitemizin DOM'unu veya form alanlarını okuyabilir mi?
Hayır. Widget sayfanızda yalnızca iki şeye bakar: mevcut URL
(ödeme sayfası eşleşmesi için) ve <head>
içinde Font Awesome / DM Sans bağlantısı olup olmadığı (çift
yükleme yapmamak için). Hiçbir input, form, metin düğümü veya
veri özniteliği okunmaz.
Müşterimizin sepetini veya sipariş tutarını görüyor musunuz?
Hayır. Ürün, tutar, adet veya müşteri bilgisi hiçbir şekilde okunmaz ve iletilmez. Bize ulaşan tek şey sayfa URL'sidir — bu yüzden § 04'te URL'lerde hassas parametre taşımama önerimiz var.
API'niz çökerse sitemiz etkilenir mi?
Hayır. Tüm çağrılar asenkron ve hata korumalıdır. API yanıt
vermezse widget görünmez; sayfanızın render'ı,
load olayı veya JavaScript yürütmesi
etkilenmez. Konsola bir hata satırı düşer, o kadar.
Script'i güncellediğinizde sitemize istediğiniz kodu gönderebilir misiniz?
Bu, her üçüncü taraf script'i için geçerli olan gerçek bir
tedarik zinciri riskidir ve dürüst cevabı şudur: teknik
olarak evet, çünkü dosya bizim sunucumuzdan servis edilir.
Bu riski kaldırmak isteyen ekipler için iki seçeneğimiz var —
(a) widget.js ve widget.css
dosyalarını kendi sunucunuzdan barındırın (script kendi
konumunu algılayıp CSS'i oradan yükler, ek yapılandırma
gerekmez); (b) script etiketine integrity
ile SRI hash ekleyin — sürüm sabitlenmiş bir kopya ve hash'i
talep üzerine sağlıyoruz.
Sitemizin performans skorunu (Core Web Vitals) düşürür mü?
Ölçülebilir etkisi minimumdur. Widget
DOMContentLoaded sonrasında çalışır, dolayısıyla
LCP'yi etkilemez. Sabit konumlu ve boyutlu tek bir katman
eklediği için CLS'ye katkısı yoktur. Toplam transfer yükü
gzip'li ~19 KB'dır.
Widget'ın gösterdiği yorumlar sizin kontrolünüzde mi?
Yorumlar bağımsız bir sistemde tutulur ve yalnızca onaylı olanlar yayınlanır. Bu, sistemin güvenilirliğinin temelidir: mağaza olumsuz yorumları silemez. Panelinizden kural ihlali içeren yorumları raporlayabilirsiniz; değerlendirme Güventik tarafında yapılır.
Bir penetrasyon testi yapmak istiyoruz. Mümkün mü?
Evet. Kendi mağaza hesabınız ve alan adınız kapsamında test yapabilirsiniz. Test öncesi bize bildirin ki hız sınırlama uyarılarımız yanlış alarm üretmesin. Bulguları sorumlu ifşa kapsamında değerlendirir ve süre taahhüdüyle yanıtlarız.
Ekibinizin başka bir sorusu mu var?
Bu doküman widget'ın çalışan kaynak kodundan çıkarılmıştır. Güvenlik incelemeniz için ek bilgi, SRI hash'i, sürüm sabitlenmiş kopya veya özel CSP yapılandırması gerekiyorsa teknik ekibimize yazın.