Klaro ve Consent İşlemleri
Çerezler ve kişisel veriler (PII) ile ilgili daha önce yayınladığım kullanıcı etkinliklerinin izlenmesi ve çerez izin/rıza yönetimi yönetimi yazılarına ek olarak kullanılabilecek bazı yardımcı araçlardan bahsetmiştim.
Elbette bahsi geçen bu konular sadece belirli bir bağlama odaklanmaktalar. Çerez ve kullancı verilerin toplanması, işlenmesi ve/veya paylaşılması gibi durumlar için esas olan konu hukuki destek alınması ve veri sorumlusu bildirimlerinin gerçekleştirilmesi olacaktır. İlgili araçlar planlama sürecinin ardından, kapsama göre (kullanılan araçlar, sorumluluklar, sınırlandırmalar, vb.) değerlendirilmesi gereken konular arasında yer almaktadır.
Bu yazı da yine ilgili çerez yönetim çözümlerine bir ekleme olarak ele alınabilir. Yazının kalan bölümünde bahsi geçecek olan Klaro da bu çözümlerden biri.
Klaro
Klaro, KIProtect tarafıdan geliştirilen, web siteleri için GDPR uyumlu açık kaynak bir izin/rıza yönetimi platformu (CMP)1. Platform, açık kaynak seçeneğin2 yanı sıra sunucu taraflı çözümler için de ek abonelik seçenekleri sunmakta3.
Alan adı tarama işleminin tamamlanmasının ardından4 görüntülenen çerezlerin ve yerel depolama (local storage) bildirimlerine yönelik kategori seçimi ve açıklama tanımlarının yapılması gerekmekte.
Taramanın ardından eğer eksiklik var ise bu eksikliklerin de belirlenmesi ile birlikte konfigürasyon aşamasına geçilebilir. O halde adım adım klasor ile rıza (consent) yönetiminin popüler etiketlerle ile ilişkili olarak nasıl gerçekleştirilebileceğine bir bakalım.
İlk işlem elbette etiket yönetimini gerçekleştirilecek JavaScript dosyasının indirilmesi olacaktır. Yayınlanan son sürüme ve örnek kullanımlara uygulamanın GitHub sayfası üzerinden ulaşmak mümkün2. Ayrıca CDN aracılığı ile kullanmak isterseniz Getting Started sayfasında belirtilen latest seçeneğini kullanarak güncel dosya bağlantısını görüntüleyebilirsiniz. Elbette bu seçeneği kullanmanız durumunda yine bildirimlerin iletileceği modal'a ait CSS içeriğini ayrıca ele almanız gerekir.
Konfigürasyon
Ön tanımlı olarak Klaro klaroConfig
global değişkenini temel alır. Ancak, bu değişken tanımı klaro.js
dosyasını çağırırken data-klaro-config
ile değiştirilebilir.
<script src="klaro.js" data-klaro-config="myConfigVariableName"></script>
İlgili JavaScript içeriğinin websitesine eklenmesinin ardından konfigürasyon işlemine geçilebilir5. Konfigürasyon dosyası (annotated-config-file.js
) en temel hali ile şu şekildedir:
window.klaroConfig = {
services : [...],
}
Consent sürecinin nasıl işleyeceği, Klaro çerez tanımı ve kullanılan servislerin tanımlanması (farklı dillerde açıklamalar ile) ile birlitke kod şu bölümlere sahip olacaktır:
var klaroConfig = {
testing: false,
elementID: 'klaro',
storageMethod: 'cookie',
storageName: 'klaro',
htmlTexts: false,
cookieDomain: '.example.com',
cookieExpiresAfterDays: 30,
default: false,
mustConsent: false,
acceptAll: true,
hideDeclineAll: false,
hideLearnMore: false,
translations: {
zz: { // zz ön anımlı dili ifade eder
privacyPolicyUrl: '/privacy',
},
en: {
privacyPolicyUrl: '/privacy',
consentModal: {
description:
'Here you can see and customize the information that we collect about you. ' +
'Entries marked as "Example" are just for demonstration purposes and are not ' +
'really used on this website.',
},
purposes: {
analytics: {
title: 'Analytics'
},
security: {
title: 'Security'
},
livechat: {
title: 'Livechat'
},
advertising: {
title: 'Advertising'
},
styling: {
title: 'Styling'
},
},
},
},
services: [
{
name: 'matomo',
default: true,
translations: {
zz: {
title: 'Matomo/Piwik'
},
en: {
description: 'Matomo is a simple, self-hosted analytics service.'
},
de: {
description: 'Matomo ist ein einfacher, selbstgehosteter Analytics-Service.'
},
},
purposes: ['analytics'],
cookies: [
[/^_pk_.*$/, '/', 'klaro.kiprotect.com'],
[/^_pk_.*$/, '/', 'localhost'],
'piwik_ignore',
],
callback: function(consent, service) {
console.log(
'User consent for service ' + service.name + ': consent=' + consent
);
},
required: false,
optOut: false,
onlyOnce: true,
},
{
name: 'youtube',
contextualConsentOnly: true,
},
],
callback: function(consent, service) {
console.log(
'User consent for service ' + service.name + ': consent=' + consent
);
},
};
Yukarıdaki örnek konfigürasyon tanımı içerisinde yer alan Matomo ile ilgili kod tanımı ise şu şekilde güncellendiğinde işlemler tamamlanmış olacaktır:
<script
type="text/plain"
data-type="application/javascript"
data-src="https://analytics.7scientists.com/matomo.js"
data-name="matomo">
</script>
Bu harici dosya (img, link, script, vb.) tanımında önemli olan data-name="matomo"
ile ilgili konfigürasyonun ilişkilendirilmesinin sağlanması. Konfigürasyon içerisinde yer alan services
nesnesi içerisinde yer alan name
ile aynı içeriğin kullanılması önemli. Konfigürasyon işleminde kullanılan parametreler ile ilgili olarak açıklamalara Klaro dokümantasyonu üzerinden ulaşılabilir5 6. Bu açıklamaların yanı sıra, aşağıda yer alan örnekler vasıtasıyla ayrıca kısa notlarımı ileteceğim.
Entegrasyon İşlemleri
Yukarıda bahsi geçen çerezlerin ve yerel depolama kullanımlarının listelenmesi ile birlikte konfigürasyon dosyasının içeriği netleşmiş olacaktır. Artından etiket yönetimine geçilebilir. Bu işlem için ilk olarak konfigürasyon ve Klaro kodunun çağırılması gerekli7.
<script
defer type="application/javascript"
src="config.js"></script>
<script
defer
data-config="klaroConfig"
type="application/javascript"
src="https://cdn.kiprotect.com/klaro/v0.7/klaro.js">
</script>
Bu aşamada etiketler ve bağlamsal onaylar üzerine düşünelim. Örneğin, bu sitede yayınlanan yazılar içerisine tweet paylaşımlarına ve youtube videolarına yer verilmeke. Bunun yanı sıra, yorum alanı disqus ile yönetilmekte. Etiket yönetimi Google Tag Manager aracılığı ile gerçekleştirilmekte, izleme işlemlerinde ise Google Analytics, Hotjar, HubSpot, Google Optimize, Facebook Pixel kullanılmakta. Dolayısıyla, consent sürecinin bu bilgiler ışığında ele alınması gerekmekte.
Klaro işlemleri etiketler ve bağlamsal onaylar şeklinde ele almakta. Etiketler bir kodun yüklenmesi ile başlayan süreci kaparsaken bağlamsal izinler bir kodun o an gösterimini kontrol eder. Bağlamsal iziler için web sayfanıza yerleştirilmiş (embed) bir YouTube videosunu düşünebilirsiniz. Elbette sadece video ile sınırlı değil; iframe ve inline-script'lerin tamamını bağlamsal izinler altında ele almak mümkün. Şimdi, bu iki konsepti ayrı başlıklar altında detaylandıralım.
Etiket Yönetimi
Klaro ile etiket yönetimi ilgili etikete ait kurulum kodu ve Klaro konfigürasyon dosyası aracılığı ile ele alınır. Websitesindeki bir etiketi Klaro ile kontrol etmek istediğimizde, ilk olarak ilgili etiket için bir ad ve açıklama belirtilmelidir.
var klaroConfig = {
//...
translations: {
zz: {
//... ön tanımlı dil içeriği
},
tr: {
etiketAdi: {
description: 'Etiket ile ilgili açıklama',
},
purposes: {
analytics: 'Analytics',
//...
},
},
en: {
//...
}
},
services: [{
name: 'etiketAdi',
title: 'etiketBasligi',
purposes: ['analytics'], // marketing, performans, ...
cookies: [ // ilgili çerezler
['/^_xy(_.*)?/'],
['/^_xyz(_.*)?/']
],
},
{
//...
}]
}
Bu bilgiler doğrultusunda popüler servislerle ilgili süreçleri örneklendirmeye geçebiliriz.
Google Analytics
Çerez İzin / Rıza (Cookie Consent) Yönetim Araçları başlıklı yazıda Google Analytics etiketine değinmiştim. Klaro bu yazıda da bahsi geçen consent mode desteğine sahip. Bu sayede kolay bir şekilde etiket yönetimini gerçekleştirebilmekteyiz. Google Analytics'in bizim için zorunlu servislerden biri olduğunu varsayalım. Elbette bu durumda kullanıcılara ait IP adresinin de anonimleştirilmiş olmasını tavsiye ederim8.
Yukarıda örneklendirilen konfigürasyon ile ilişkili olarak şu eklemeleri yapabiliriz:
var klaroConfig = {
mustConsent: true,
translations: {
en: {
googleAnalytics: {
description: 'Used by Google Analytics to collect data on the number of times a user has visited the website as well as dates for the first and most recent visit.',
},
purposes: {
analytics: 'Analytics'
},
},
},
services: [{
name: 'googleAnalytics',
title: 'Google Analytics',
purposes: ['analytics'],
cookies: [
['/^_ga(_.*)?/'],
['/^_gid(_.*)?/']
],
default: true,
required: true,
}]
}
Elbette bu tanımlarla ilişkili olarak Google Analytics kurulum koduna data-name
ile bu etiket tanımını eklememiz, src
özniteliğini data-src
ile değiştirmemiz gerekmekte.
<script
async type="opt-in"
data-type="application/javascript"
data-src="https://www.googletagmanager.com/gtag/js?id=UA-XXXXXXXX-Y"
data-name="googleAnalytics"
></script>
<script type="opt-in" data-type="application/javascript" data-name="googleAnalytics">
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-XXXXXXXX-Y');
</script>
Hotjar
Hotjar kullanıcı kimliği, oturum kaydı, anket işlemleri ve diğer pek çok özelliği için farklı çerezler oluşturmaka. Ekran kaydı sürecinde de aksi belirtilmediği sürece sayısal değerler ve form içerikleri kayıt edilmemekte9. Ancak, elbette ilgili çerezlerin ayrıca belirtilmesi ve kullanıcı iznine bağlanması önerilir.
var klaroConfig = {
mustConsent: true,
translations: {
en: {
hotjar: {
description: 'Optimizing the user experience, providing insights about how users use the website',
},
purposes: {
functional: 'Functional'
},
},
},
services: [{
name: 'hotjar',
title: 'Hotjar',
purposes: ['functional'],
cookies: [
['/^_hj(_.*)?/']
]
}]
}
Şimdi bu konfigürasyon tanımlarına göre kurulum etiketini düzenleyelim.
<script data-type="application/javascript" data-name="hotjar">
(function(h,o,t,j,a,r){
h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};
h._hjSettings={hjid:XXXXXXX,hjsv:6};
a=o.getElementsByTagName('head')[0];
r=o.createElement('script');r.async=1;
r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;
a.appendChild(r);
})(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');
</script>
Google Ads
Google Ads kurulum etiketi Google Analytics gibi Global Site Etiketi kullanmakta. Dolayısıyla, kurulum etiketinde (AW-
kimliği ile ilişkili olarak) benzer bir düzenleme yapmak yeterli olacaktır. Ancak, konfigürasyon aşamasında elbette farklılıklar söz konusu10.
var klaroConfig = {
mustConsent: true,
translations: {
en: {
ads: {
description: 'Marketing/target cookies are usually used to show you advertisements that meet your interests. The intention is to display ads that are relevant and engaging for the individual user and thereby more valuable for publishers and third party advertisers.',
},
purposes: {
marketing: 'Marketing'
},
},
},
services: [{
name: 'ads',
title: 'Google Ads',
purposes: ['marketing'],
cookies: [
['IDE'],
['FLC'],
['RUL'],
['/^ID'],
['test_cookie'],
['/^_ga(_.*)?/'],
['/^_gcl(_.*)?/'],
['/^ads(.*)?/'],
['/^ga-(.*)?/'],
]
}]
}
Facebook Pixel
Facebook Ads ve Facebook Analytics ile ilgili tüm işlemlerde pixel kodu kullanılmakta11. Bu nedenle, ilgili çerezleri hem pazarlama/reklam hem de analitik başlığı altında gruplandırmak mümkün.
var klaroConfig = {
mustConsent: true,
translations: {
en: {
ads: {
description: 'Marketing/target cookies are usually used to show you advertisements that meet your interests. The intention is to display ads that are relevant and engaging for the individual user and thereby more valuable for publishers and third party advertisers.',
},
purposes: {
marketing: 'Marketing',
analytics: 'Analytics'
},
},
},
services: [{
name: 'facebook',
title: 'Facebook Ads & Pixel',
purposes: ['marketing', 'analytics'],
cookies: [
['xs'],
['c_user'],
['dpr'],
['datr'],
['wd'],
['fr'],
['sb'],
['spin'],
['presence'],
['/^_fb(.*)?/'],
['/^_e(_.*)?/']
],
default: false
}]
}
Kurulum kodu standart olduğu için Klaro enterasyonu kolay bir şekilde gerçekleştirilebilmekte12.
<script opt-in="true" data-type="application/javascript" type="text/plain" data-name="facebook">
!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];n.agent='plideasoft';t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
document,'script','https://connect.facebook.net/en_US/fbevents.js');
fbq('init', 'XXXXXXXXXXXXXXXX');
fbq('track', 'PageView');
</script>
<noscript>
<img
height="1" width="1" style="display:none"
data-type="image/gif"
data-name="facebook"
data-src="https://www.facebook.com/tr?id=XXXXXXXXXXXXXXXX&ev=PageView&noscript=1" />
</noscript>
Google Tag Manager
Yukarıda ayrı ayrı öne çıkan servisler bağlamında kodların nasıl ele alınabileceğine değinmeye çalıştım. Peki, Google Tag Manager gibi bir etiket yöneticisi kullanıyorsak ne yapmalıyız? Esasında işlemlerde pek farklılık yok. Ancak, etiketlerin kullanım amaçlarına uygun olarak GTM'i farklı gruplar (performans, reklam, analitik, vb.) altında ya da zorunlu bir grup olarak değerlendirmek ve GTM içerisinde de ilgili etkinlikleri event
tanımlarına bağlı olarak tetiklemek gerekmekte.
İlk olarak GTM için kullanabileceğimiz konfigürasyona bakalım.
var klaroConfig = {
acceptAll: true,
services: [
{
name: 'googleTagManager',
purposes: ['marketing', 'analytics', 'functional'],
onAccept: `
// we notify the tag manager about all services that were accepted. You can define
// a custom event in GTM to load the service if consent was given.
for(let k of Object.keys(opts.consents)){
if (opts.consents[k]){
let eventName = 'klaro-'+k+'-accepted'
dataLayer.push({'event': eventName})
}
}
// if consent for Google Analytics was granted we enable analytics storage
if (opts.consents[opts.vars.googleAnalyticsName || 'googleAnalytics']){
console.log("Google analytics usage was granted")
gtag('consent', 'update', {'analytics_storage': 'granted'})
}
// if consent for Google Ads was granted we enable ad storage
if (opts.consents[opts.vars.adStorageName || 'googleAds']){
console.log("Google ads usage was granted")
gtag('consent', 'update', {'ad_storage': 'granted'})
}
`,
onInit: `
// initialization code here (will be executed only once per page-load)
window.dataLayer = window.dataLayer || [];
window.gtag = function(){dataLayer.push(arguments)}
gtag('consent', 'default', {'ad_storage': 'denied', 'analytics_storage': 'denied'})
gtag('set', 'ads_data_redaction', true)
`,
onDecline: `
// initialization code here (will be executed only once per page-load)
window.dataLayer = window.dataLayer || [];
window.gtag = function(){dataLayer.push(arguments)}
gtag('consent', 'default', {'ad_storage': 'denied', 'analytics_storage': 'denied'})
gtag('set', 'ads_data_redaction', true)
`,
vars: {
googleAnalytics: 'googleAnalytics'
}
},
{
// In GTM, you should define a custom event trigger named `klaro-googleAnalytics-accepted` which should trigger the Google Analytics integration.
name: 'googleAnalytics',
purposes: ['analytics'],
cookies: [
['/^_ga(_.*)?/'], // we delete the Google Analytics cookies if the user declines its use
['/^_gid(_.*)?/']
],
default: true,
required: true,
}
]
}
Görüldüğü üzere, GTM içerisinde ayrıca Google Analytics ile ilgili consent mode tanımı da yer almakta. Kullanıcı şayet GTM kurulumunu kabul etmez onDecline
alanında belirtildiği şekilde işlemler ele alınabilir. Örneğin, Google Analytics zorunlu olacaksa onDecline
içerisindeki consent mode ile ilişkili olarak ayrıca Google Analytics kurulum etiketine sayfada yer verilebilir. İlgili onay işlemlerinde klaro-google-tag-manager-accepted
ve klaro-google-analytics-accepted
etkinlikleri tetiklenir13.
<!-- Google Tag Manager -->
<script defer type="opt-in" data-type="application/javascript" type="text/plain" data-name="googleTagManager">
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXXX');
</script>
<!-- End Google Tag Manager -->
<script
defer type="opt-in"
data-type="application/javascript"
data-src="https://www.googletagmanager.com/gtag/js?id=UA-XXXXXXXX-Y"
data-name="googleAnalytics"
></script>
<script type="opt-in" data-type="application/javascript" data-name="googleAnalytics">
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-XXXXXXXX-Y');
</script>
Elbette GTM izinlerine bağlı olarak diğer zorunlu etiketleri de Google Analytics ile benzer şekilde haricen kullanmak mümkün. Sıklıkla kullanılan bu etiketlerin yanı sıra, yine zorunlu olarak kullanabildiğimiz font, harita ve benzeri diğer kaynakları da Klaro ile yönetebilmekteyiz.
Diğer
İçerik Yönetim Sistemi (CMS), güvenlik servisleri, harici font, JavaScript ve CSS dosyaları, Google Maps, iframe'ler gibi sayfa içerisinde yer alan kaynaklar için de Klaro consent konrolü sağlayabilmektedir. Aşağıda temel birkaç servis için oluşturduğum konfigürsyon içeriğini görebilirsiniz.
var klaroConfig = {
acceptAll: true,
translations: {
en: {
externalScript: {
description: 'Marketing/target cookies are usually used to show you advertisements that meet your interests. When you visit another website, your browser\'s cookie is recognized and selected ads are displayed to you based on the information stored in the cookies.'
},
externalMedia: {
description: 'These tags are required for the basic functions of the website. These are also listed here for informational purposes.',
},
purposes: {
marketing: 'Marketing',
analytics: 'Analytics',
externalScript: 'External Resources',
externalMedia: 'External Medias'
},
},
},
services: [
{
name: 'externalScript',
title: 'External Scripts',
purposes: ['styling', 'performance', 'security'],
cookies: [
['/^__cf(.*)?/'], // Codepen
['/^_jsfiddle(.*)?/'], // JSFiddle
['remember_user_token'],
['csrftoken'],
['/^amplitude(_.*)?/'],
['/^wp-settings(.*)?/'], // WordPress
['/^wordpress_(.*)?/'], // WordPress
],
},
{
name: 'googleMap',
title: 'Google Maps',
purposes: ['externalMedia'],
},
{
name: 'youTube',
title: 'YouTube',
purposes: ['externalMedia'],
contextualConsentOnly: true,
cookies: [
['/^_yt(-.*)?/'],
],
},
{
name: 'googleFonts',
title: 'Google Fonts',
purposes: ['styling'],
required: true,
default: true,
},
{
name: 'cloudflare',
title: 'Cloudflare',
purposes: ['security'],
required: true,
}
]
}
Bağlamsal Onay (Contextual Consent)
Klaro ile sayfa içine gömülü video, ses dosyası ve diğer zengin içerikleri sadece seçimle aktifleştirilecek şekilde sunabilmekteyiz. Bağlamsal onay (contextual consent) olarak ifade edilen bu işlem için konfigürasyon dosyası içerisinde yer alan ilgili servis tanımına contextualConsentOnly: true
tanımını yapmamız gerekir14.
var klarConfig = {
acceptAll: true,
services: [
{
purposes: ['marketing'],
name: "demo-youtube",
contextualConsentOnly: true,
},
{
purposes: ['marketing'],
name: "demo-twitter",
}
]
}
Bu konfigürasyon tanımı ile ilgili olarak örnek bir Youtube videosu ve Tweet kullanımına bakalım:
<iframe
width="560"
height="315"
data-name="demo-youtube"
data-src="https://www.youtube.com/embed/dQw4w9WgXcQ"
frameborder="0"
allow="accelerometer;
autoplay;
clipboard-write;
encrypted-media;
gyroscope;
picture-in-picture"
allowfullscreen>
</iframe>
<div data-name="demo-twitter">
<a
href="https://twitter.com/kiprotect?ref_src=twsrc%5Etfw"
class="twitter-follow-button"
data-show-count="false">Follow @kiprotect</a>
</div>
<script
data-type="application/javascript"
async
data-name="demo-twitter"
data-src="https://platform.twitter.com/widgets.js"
charset="utf-8">
</script>
JavaScript API ve Test İşlemleri
Yukarıda bahsi geçen tüm işlemleri test etmeden yayına almamanızı öneririm. Aksi durumda, izleme işlemleri başta olmak üzere verilerle ilgili kısmen ya da tamamen veri kayıpları yaşamak olası. Klaro bu amaçla çeşitli test özellikleri sunar. İlk özellik konfigürasyon dosyası içerisinde testing
değerinin tanımlanması ve true
değerinin verilmesi ile kullanılabilir. Bu işlemin ardından Klaro consent bildirimlerini ön tanımlı olarak aktifleştirmez. Böylelikle, ziyaretçiler işlemlerden etkilenmezler ve düzenlemeler URL'e eklenen #klaro-testing
ile kontrol edilir15.
JavaScript API ise bize konigürasyon kontrolü, modal işlemleri, etiket yönetimi başta olmak üzere konfigürasyon alanı da dahil olmak üzere tüm Klaro işlemlerini haricen yönetme imkanı sunar16. Örneğin, console alanına klaro
yazarak nesne içeriğini ve metotları görüntüleyebilir, klaro.show()
ile ilgili modal'ı görüntüleyebilir, klaro.getManager(klaroConfig)
ile konfigürasyon içeriğini kontrol edebilir ve klaro.getManager().resetConsents()
ile consent seçimlerini sıfırlayabiliriz.
- Klaro. KIProtect ↩
- kiprotect/klaro. GitHub ↩ ↩
- Prices. Klaro ↩
- Privacy Scanner ↩
- Annotated Config File. Klaro ve Annotated Config File JavaScipt dosyası ↩ ↩
- Getting Started. Klaro ↩
- Integrating Klaro ↩
- Google Analytics Cookie Usage on Websites. Google Analytics ↩
- Hotjar Cookie Information. Hotjar Documentation ↩
- How Google uses cookies? Google Privacy and Terms ↩
- Çerezler ve diğer depolama teknolojileri. Facebook ↩
- Implementation. Facebook for Developers ve Advanced. Facebook for Developers ↩
- Google Tag Manager (GTM). KIProject Documentation ↩
- Contextual Consent. KIProject Documentation ↩
- How To Test The Klaro Integration. KIProject Documentation ↩
- Javascript API ↩