Bermigrasi ke Petunjuk Klien Agen Pengguna

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

String Agen Pengguna adalah platform pelacakan sidik jari pasif yang signifikan di browser, serta sulit untuk diproses. Namun, ada segala jenis alasan yang valid untuk mengumpulkan dan memproses data agen pengguna sehingga yang diperlukan adalah jalur menuju solusi yang lebih baik. Petunjuk Klien Agen Pengguna menyediakan cara eksplisit untuk mendeklarasikan kebutuhan Anda akan data dan metode agen pengguna 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 segala bentuk pengumpulan data, Anda harus selalu memahami alasan mengumpulkannya. Langkah pertama, terlepas dari apakah Anda akan mengambil tindakan apa pun, adalah memahami di mana dan mengapa Anda menggunakan data agen pengguna.

Jika Anda tidak tahu apakah atau 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, pertimbangkan bagian mana pun dalam kode tempat Anda merekam atau memproses:

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

Anda mungkin juga menggunakan library atau layanan pihak ketiga untuk memproses agen pengguna. Dalam kasus ini, periksa apakah update 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/signifikan
  • Sec-CH-UA-Mobile: nilai boolean yang menunjukkan perangkat seluler
  • Sec-CH-UA-Platform: nama sistem operasi
    • Perlu diketahui bahwa hal ini telah diperbarui dalam spesifikasi dan akan segera ditampilkan di Chrome dan browser berbasis Chromium lainnya.

Versi terbatas 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 melihat peringatan penghentian penggunaan.

Meskipun dapat dan harus 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 ada akan menerima informasi yang kurang mendetail, kode tersebut harus tetap mempertahankan fungsi dasar.

Strategi: JavaScript API sisi klien on-demand

Jika saat ini Anda menggunakan navigator.userAgent, Anda harus beralih untuk memilih 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 yang dapat digunakan browser untuk mencantumkan kompatibilitasnya dengan merek tersebut. Anda dapat mengaksesnya secara langsung sebagai array atau menggunakan panggilan some() untuk memeriksa apakah ada entri tertentu:

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 yang lebih mendetail dan entropi tinggi, 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 Anda 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 untuk data tersebut relatif konsisten di seluruh situs, Anda dapat menentukan client hints yang diinginkan sebagai set statis dalam respons Anda. Ini adalah pendekatan yang relatif sederhana karena umumnya Anda hanya perlu mengonfigurasinya di satu lokasi. Misalnya, mungkin ada di konfigurasi server web jika Anda sudah menambahkan header di sana, konfigurasi hosting, atau konfigurasi tingkat atas 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 menyediakan petunjuk default yang berbeda. Jadi, sebaiknya tentukan semua yang Anda perlukan meskipun umumnya disediakan secara default.

Misalnya, default saat ini untuk Chrome akan ditampilkan 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, sebaiknya kirim:

⬇️ 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 header User-Agent yang mengurai jika tidak tersedia.

Strategi: Mendelegasikan petunjuk ke permintaan lintas origin

Jika Anda meminta subresource lintas asal atau lintas situs yang memerlukan Petunjuk Klien Agen Pengguna untuk dikirimkan pada permintaan mereka, 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 mendelegasikan 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, dan 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 mirip dengan resource lintas origin, tetapi Anda menentukan petunjuk yang ingin didelegasikan dalam atribut allow.

⬇️ Jawaban 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 di iframe akan menggantikan header Accept-CH apa pun yang mungkin dikirim widget.site sendiri. Jadi, pastikan Anda telah menentukan semua yang diperlukan oleh situs iframe.

Strategi: Petunjuk sisi server dinamis

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

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

Misalnya, Anda mungkin memiliki satu bagian di situs tempat Anda ingin menyediakan ikon dan kontrol yang cocok dengan sistem operasi pengguna. Untuk itu, Anda mungkin 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 hal ini kemungkinan jarang terjadi, jadi pastikan Anda telah meninjau alasannya.

Permintaan pertama benar-benar 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 tambahan pada pemuatan halaman awal?

Ada dua opsi untuk petunjuk tambahan pada permintaan pertama. Pertama, Anda dapat menggunakan header Critical-CH. Tindakan ini menggunakan format yang sama dengan Accept-CH, tetapi memberi tahu browser bahwa permintaan harus segera mencoba 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 kembali permintaan awal dengan header ekstra

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

Hal ini akan menimbulkan overhead percobaan ulang pada permintaan pertama, tetapi biaya implementasinya relatif rendah. Kirimkan header tambahan dan browser akan mengerjakan sisanya.

Jika Anda benar-benar memerlukan petunjuk tambahan saat pemuatan halaman pertama dilakukan, proposal Keandalan Petunjuk Klien menjabarkan rute untuk menentukan petunjuk di setelan tingkat koneksi. Ini memanfaatkan ekstensi Application-Layer Protocol Settings(ALPS) ke TLS 1.3 untuk memungkinkan penerusan awal petunjuk ini pada koneksi HTTP/2 dan HTTP/3. Ini masih dalam tahap awal, tetapi jika Anda aktif mengelola setelan TLS dan koneksi sendiri, inilah 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 merencanakan untuk beralih ke panggilan navigator.userAgentData yang setara, tetapi ada solusi sementara.

Retrofill UA-CH 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 menampilkan 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 repo terkait privacy-sandbox-dev-support dan kita dapat mempelajari masalah Anda bersama-sama.

Foto oleh Ricardo Rocha di Unsplash