Bermigrasi ke Petunjuk Klien Agen Pengguna

Strategi untuk memigrasikan situs Anda dari mengandalkan string agen pengguna ke Petunjuk Klien Agen Pengguna yang baru.

String Agen Pengguna adalah platform pelacakan sidik jari pasif yang signifikan di browser, serta sulit diproses. Namun, ada segala jenis alasan yang valid untuk mengumpulkan dan memproses data agen pengguna, jadi yang diperlukan adalah jalur menuju solusi yang lebih baik. Petunjuk Klien Agen Pengguna menyediakan cara eksplisit untuk mendeklarasikan kebutuhan Anda akan data agen pengguna dan metode untuk menampilkan data dalam format yang mudah digunakan.

Artikel ini akan memandu Anda mengaudit akses ke data agen pengguna dan memigrasikan penggunaan string agen pengguna ke Petunjuk Klien Agen Pengguna.

Mengaudit pengumpulan dan penggunaan data agen pengguna

Seperti bentuk pengumpulan data lainnya, Anda harus selalu memahami alasan Anda mengumpulkannya. Langkah pertama, terlepas dari apakah Anda akan mengambil tindakan atau tidak, adalah memahami tempat dan alasan Anda menggunakan data agen pengguna.

Jika Anda tidak tahu di mana data agen pengguna digunakan, pertimbangkan untuk menelusuri kode frontend untuk penggunaan navigator.userAgent dan kode backend untuk penggunaan header HTTP User-Agent. Anda juga harus memeriksa kode front-end untuk mengetahui penggunaan fitur yang sudah tidak digunakan lagi, seperti navigator.platform dan navigator.appVersion.

Dari sudut pandang fungsional, pikirkan tentang di mana pun dalam kode tempat Anda merekam atau memproses:

  • Nama atau versi browser
  • Nama atau versi sistem operasi
  • Merek atau model perangkat
  • Jenis CPU, arsitektur, atau bitness (misalnya, 64-bit)

Anda juga mungkin menggunakan library atau layanan pihak ketiga untuk memproses agen pengguna. Dalam hal ini, periksa apakah instance tersebut diperbarui untuk mendukung Petunjuk Klien Agen Pengguna.

Apakah Anda hanya menggunakan data agen pengguna dasar?

Kumpulan default Petunjuk Klien Agen Pengguna mencakup:

  • Sec-CH-UA: nama browser dan versi utama/penting
  • Sec-CH-UA-Mobile: nilai boolean yang menunjukkan perangkat seluler
  • Sec-CH-UA-Platform: nama sistem operasi
    • Perhatikan bahwa perubahan ini telah diperbarui dalam spesifikasi dan akan ditampilkan di Chrome dan browser berbasis Chromium lainnya segera.

Versi yang lebih sedikit dari string agen pengguna yang diusulkan juga akan mempertahankan informasi dasar ini dengan cara yang kompatibel dengan versi lama. Misalnya, string akan menyertakan Chrome/90.0.0.0, bukan Chrome/90.0.4430.85.

Jika Anda hanya memeriksa string agen pengguna untuk nama browser, versi utama, atau sistem operasi, kode akan terus berfungsi meskipun Anda mungkin akan melihat peringatan penghentian penggunaan.

Meskipun Anda dapat dan sebaiknya bermigrasi ke Petunjuk Klien Agen Pengguna, Anda mungkin memiliki batasan resource atau kode lama yang mencegah hal ini. Pengurangan informasi dalam string agen pengguna dengan cara yang kompatibel dengan versi lama ini dimaksudkan untuk memastikan bahwa meskipun kode yang sudah ada akan menerima informasi yang kurang mendetail, kode tersebut tetap harus mempertahankan fungsi dasar.

Strategi: JavaScript API sisi klien on-demand

Jika saat ini Anda menggunakan navigator.userAgent, Anda harus beralih ke navigator.userAgentData sebelum kembali ke penguraian string agen pengguna.

if (navigator.userAgentData) {
  // use new hints
} else {
  // fall back to user-agent string parsing
}

Jika Anda memeriksa perangkat seluler atau desktop, gunakan nilai mobile boolean:

const isMobile = navigator.userAgentData.mobile;

userAgentData.brands adalah array objek dengan properti brand dan version tempat browser dapat mencantumkan kompatibilitasnya dengan merek tersebut. Anda dapat mengaksesnya langsung sebagai array atau menggunakan panggilan some() untuk memeriksa apakah entri tertentu ada:

function isCompatible(item) {
  // In real life you most likely have more complex rules here
  return ['Chromium', 'Google Chrome', 'NewBrowser'].includes(item.brand);
}
if (navigator.userAgentData.brands.some(isCompatible)) {
  // browser reports as compatible
}

Jika memerlukan salah satu nilai agen pengguna entropi tinggi yang lebih mendetail, Anda harus menentukannya dan memeriksa hasilnya dalam Promise yang ditampilkan:

navigator.userAgentData.getHighEntropyValues(['model'])
  .then(ua => {
    // requested hints available as attributes
    const model = ua.model
  });

Anda juga dapat menggunakan strategi ini jika ingin beralih dari pemrosesan sisi server ke pemrosesan sisi klien. JavaScript API tidak memerlukan akses ke header permintaan HTTP, sehingga nilai agen pengguna dapat diminta kapan saja.

Strategi: Header sisi server statis

Jika menggunakan header permintaan User-Agent di server dan kebutuhan Anda terhadap data tersebut relatif konsisten di seluruh situs, Anda dapat menentukan klien petunjuk yang diinginkan sebagai kumpulan statis dalam respons Anda. Ini adalah pendekatan yang relatif sederhana karena biasanya Anda hanya perlu mengonfigurasinya di satu lokasi. Misalnya, hal ini mungkin ada di konfigurasi server web jika Anda sudah menambahkan header di sana, konfigurasi hosting, atau konfigurasi tingkat atas dari framework atau platform yang Anda gunakan untuk situs.

Pertimbangkan strategi ini jika Anda mengubah atau menyesuaikan respons yang ditayangkan berdasarkan data agen pengguna.

Browser atau klien lain dapat memilih untuk memberikan petunjuk default yang berbeda, jadi sebaiknya tentukan semua yang Anda perlukan, meskipun biasanya disediakan secara default.

Misalnya, default saat ini untuk Chrome akan ditunjukkan sebagai:

⬇️ Header respons

Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Platform, Sec-CH-UA

Jika Anda juga ingin menerima model perangkat dalam respons, Anda perlu mengirimkan:

⬇️ Header respons

Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platform, Sec-CH-UA

Saat memproses ini di sisi server, Anda harus memeriksa terlebih dahulu apakah header Sec-CH-UA yang diinginkan telah dikirim, lalu kembali ke penguraian header User-Agent jika tidak tersedia.

Strategi: Mendelegasikan petunjuk ke permintaan lintas origin

Jika Anda meminta subresource lintas origin atau lintas situs yang memerlukan Petunjuk Klien Agen Pengguna untuk dikirim pada permintaannya, Anda harus secara eksplisit menentukan petunjuk yang diinginkan menggunakan Kebijakan Izin.

Misalnya, https://blog.site menghosting resource di https://cdn.site yang dapat menampilkan resource yang dioptimalkan untuk perangkat tertentu. https://blog.site dapat meminta petunjuk Sec-CH-UA-Model, tetapi perlu mendelegasikannya secara eksplisit ke https://cdn.site menggunakan header Permissions-Policy. Daftar petunjuk yang dikontrol kebijakan tersedia di draf Infrastruktur Petunjuk Klien

⬇️ Respons dari blog.site yang mendelegasikan petunjuk

Accept-CH: Sec-CH-UA-Model
Permissions-Policy: ch-ua-model=(self "https://cdn.site")

⬆️ Permintaan ke subresource di cdn.site menyertakan petunjuk yang didelegasikan

Sec-CH-UA-Model: "Pixel 5"

Anda dapat menentukan beberapa petunjuk untuk beberapa origin, bukan hanya dari rentang ch-ua:

⬇️ Respons dari blog.site yang mendelegasikan beberapa petunjuk ke beberapa asal

Accept-CH: Sec-CH-UA-Model, DPR
Permissions-Policy: ch-ua-model=(self "https://cdn.site"),
                    ch-dpr=(self "https://cdn.site" "https://img.site")

Strategi: Mendelegasikan petunjuk ke iframe

iframe lintas origin berfungsi dengan cara yang sama dengan resource lintas origin, tetapi Anda menentukan petunjuk yang ingin didelegasikan dalam atribut allow.

⬇️ Respons dari blog.site

Accept-CH: Sec-CH-UA-Model

↪️ HTML untuk blog.site

<iframe src="https://widget.site" allow="ch-ua-model"></iframe>

⬆️ Permintaan ke widget.site

Sec-CH-UA-Model: "Pixel 5"

Atribut allow dalam iframe akan menggantikan header Accept-CH yang mungkin dikirim oleh widget.site, jadi pastikan Anda telah menentukan semua yang diperlukan situs iframe.

Strategi: Petunjuk sisi server dinamis

Jika Anda memiliki bagian tertentu dari perjalanan pengguna saat Anda memerlukan pilihan petunjuk yang lebih banyak daripada di bagian lain situs, Anda dapat memilih untuk meminta petunjuk tersebut secara on demand, bukan secara statis di seluruh situs. Cara ini lebih rumit untuk dikelola, tetapi jika Anda sudah menetapkan header yang berbeda untuk setiap rute, hal ini mungkin dapat dilakukan.

Hal penting yang perlu diingat di sini adalah setiap instance header Accept-CH akan menimpa kumpulan yang ada secara efektif. Jadi, jika Anda menyetel header secara dinamis, setiap halaman harus meminta serangkaian petunjuk lengkap yang diperlukan.

Misalnya, Anda mungkin memiliki satu bagian di situs tempat Anda ingin memberikan ikon dan kontrol yang sesuai dengan sistem operasi pengguna. Untuk itu, Anda mungkin juga perlu menarik Sec-CH-UA-Platform-Version untuk menyalurkan subresource yang sesuai.

⬇️ Header respons untuk /blog

Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Platform, Sec-CH-UA

⬇️ Header respons untuk /app

Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Platform, Sec-CH-UA-Platform-Version, Sec-CH-UA

Strategi: Petunjuk sisi server diperlukan pada permintaan pertama

Mungkin ada kasus saat Anda memerlukan lebih dari kumpulan petunjuk default pada permintaan pertama, tetapi ini mungkin jarang terjadi, jadi pastikan Anda telah meninjau alasannya.

Permintaan pertama sebenarnya berarti permintaan tingkat teratas pertama untuk origin tersebut yang dikirim dalam sesi penjelajahan tersebut. Kumpulan petunjuk default mencakup nama browser dengan versi utama, platform, dan indikator seluler. Jadi pertanyaan yang harus diajukan di sini adalah, apakah Anda memerlukan data yang diperluas saat pemuatan halaman awal?

Untuk petunjuk tambahan pada permintaan pertama, ada dua opsi. Pertama, Anda dapat menggunakan header Critical-CH. Fungsi ini menggunakan format yang sama dengan Accept-CH, tetapi memberi tahu browser bahwa permintaan harus segera dicoba lagi jika permintaan pertama dikirim tanpa petunjuk penting.

⬆️ Permintaan awal

[With default headers]

⬇️ Header respons

Accept-CH: Sec-CH-UA-Model
Critical-CH: Sec-CH-UA-Model

🔃 Browser mencoba ulang permintaan awal dengan header tambahan

[With default headers + …]
Sec-CH-UA-Model: Pixel 5

Tindakan ini akan menimbulkan overhead percobaan ulang pada permintaan pertama, tetapi biaya implementasinya relatif rendah. Kirim header tambahan dan serahkan sisanya kepada browser.

Untuk situasi ketika Anda benar-benar memerlukan petunjuk tambahan pada pemuatan halaman pertama, proposal Keandalan Petunjuk Klien menyusun rute untuk menentukan petunjuk dalam setelan tingkat koneksi. API ini memanfaatkan ekstensi Setelan Protokol Lapisan Aplikasi(ALPS) ke TLS 1.3 untuk memungkinkan penerusan petunjuk awal pada koneksi HTTP/2 dan HTTP/3. Ini masih dalam tahap awal, tetapi jika Anda secara aktif mengelola TLS dan setelan koneksi Anda sendiri, ini adalah waktu yang ideal untuk berkontribusi.

Strategi: Dukungan lama

Anda mungkin memiliki kode lama atau kode pihak ketiga di situs yang bergantung pada navigator.userAgent, termasuk bagian dari string agen pengguna yang akan dikurangi. Dalam jangka panjang, Anda harus berencana untuk berpindah ke panggilan navigator.userAgentData yang setara, tetapi ada solusi sementara.

UA-CH retrofill adalah library kecil yang memungkinkan Anda menimpa navigator.userAgent dengan string baru yang dibuat dari nilai navigator.userAgentData yang diminta.

Misalnya, kode berikut akan menghasilkan string agen pengguna yang juga menyertakan petunjuk "model":

import { overrideUserAgentUsingClientHints } from './uach-retrofill.js';
overrideUserAgentUsingClientHints(['model'])
  .then(() => { console.log(navigator.userAgent); });

String yang dihasilkan akan menampilkan model Pixel 5, tetapi masih menunjukkan 92.0.0.0 yang dikurangi karena petunjuk uaFullVersion tidak diminta:

Mozilla/5.0 (Linux; Android 10.0; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.0.0 Mobile Safari/537.36

Dukungan lebih lanjut

Jika strategi ini tidak mencakup kasus penggunaan Anda, mulai Diskusi di repositori dukungan privacy-sandbox-dev-support dan kita dapat mempelajari masalah Anda bersama.

Foto oleh Ricardo Rocha di Unsplash