D
P
0
← Semua artikel Read in English

SEO Teknis, Redirect & Migrasi

Migrasi URL Situs dengan Better Search Replace Melewatkan Blok Gutenberg, Butuh Bentuk `\/` yang Di-escape

· · 4 menit baca
Migrasi URL Situs dengan Better Search Replace Melewatkan Blok Gutenberg, Butuh Bentuk `\/` yang Di-escape

Migrasi domain di sebuah situs editorial yang saya pindahkan ke WordPress kelihatannya berjalan mulus. Saya jalankan Better Search Replace, tukar https://old-site.com/ jadi domain baru, klik "replace all", dan plugin melaporkan ribuan perubahan. Selesai, pikir saya. Lalu saya klik-klik beberapa halaman dan setengah link internal masih mengarah ke domain lama. Bukan link acak. Polanya rapi: link di dalam paragraf biasa berhasil, tapi link di dalam blok-blok Gutenberg tertentu tidak. Tombol, galeri, dan blok dengan atribut semuanya masih menunjuk old-site.com.

Yang bikin saya hampir tertipu: Better Search Replace bilang sukses. Tidak ada error, tidak ada baris merah. Search-replace-nya benar-benar berjalan. Masalahnya, dia tidak menemukan apa yang saya kira sudah dia temukan.

Trigger-nya kira-kira begini. Inilah string yang saya cari, dan inilah bentuk yang sebenarnya tersimpan di database untuk konten Gutenberg:

Yang saya cari:
https://old-site.com/
 
Yang tersimpan di markup blok Gutenberg:
<!-- wp:button -->
... "url":"https:\/\/old-site.com\/contact" ...
<!-- /wp:button -->

Lihat slash-nya. Di paragraf biasa URL-nya literal: https://old-site.com/. Tapi di dalam atribut blok, setiap forward slash di-escape jadi \/, sehingga URL yang sama disimpan sebagai https:\/\/old-site.com\/. Pencarian saya untuk bentuk polos tidak akan pernah cocok dengan bentuk yang di-escape itu.

Kenapa ini terjadi

Gutenberg menyimpan atribut blok sebagai JSON yang ditempelkan ke dalam komentar HTML di post_content. Dan di JSON, forward slash boleh di-escape jadi \/. Sifatnya opsional, tapi WordPress (lewat wp_json_encode / json_encode PHP) memang melakukannya secara default. Jadi URL yang Anda tulis di editor sebagai https://old-site.com/contact berakhir di database sebagai https:\/\/old-site.com\/contact begitu masuk ke atribut blok seperti wp:button, wp:image, atau apa pun yang menyimpan href di JSON-nya.

Better Search Replace itu pencocokan string mentah terhadap isi kolom database. Dia tidak mem-parse JSON, tidak meng-unescape apa pun, tidak "paham" bahwa https:\/\/old-site.com dan https://old-site.com adalah URL yang sama. Bagi dia itu dua string berbeda. Jadi ketika saya hanya mencari bentuk polos, dia dengan patuh mengganti setiap kemunculan bentuk polos di paragraf, link klasik, dan custom field yang tidak diserialisasi, lalu diam-diam melewati setiap URL yang slash-nya di-escape di dalam blok. Setengah situs ter-update, setengahnya tidak, dan laporan "berhasil" tetap hijau karena memang teknisnya berhasil untuk apa yang dia cocokkan.

Ini bukan kuirk khusus Gutenberg saja. Data ter-serialisasi atau JSON apa pun menyimpan slash sebagai \/: atribut blok, data widget di wp_options, sampai array meta ter-serialisasi. Pola yang sama akan menggigit Anda di mana pun.

Perbaikannya

Jalankan operasi search-replace dua kali: sekali untuk bentuk polos, sekali untuk bentuk yang di-escape. Konkretnya, dua pasang ini:

# Pass 1 — bentuk polos (paragraf, link klasik, dll.)
Cari:    https://old-site.com
Ganti:   https://new-site.com
 
# Pass 2 — bentuk ter-escape (atribut blok Gutenberg, data widget, JSON)
Cari:    https:\/\/old-site.com
Ganti:   https:\/\/new-site.com

Pass kedua itu yang menyentuh blok Gutenberg. Anda mencari slash yang di-escape secara harfiah dan menggantinya dengan slash yang di-escape juga, jadi JSON tetap valid setelahnya. Anda tidak pernah mencampur kedua bentuk di dalam satu atribut.

Ada satu jebakan kalau domain Anda rawan tabrakan, misalnya satu URL adalah substring dari yang lebih panjang, atau Anda punya old-site.com dan blog.old-site.com. Pencocokan string yang naif akan merusak URL yang lebih panjang. Jangkar pencariannya. Saya tambahkan tanda kutip penutup atau pakai konteks href="..." penuh supaya hanya kecocokan yang tepat yang kena:

# Diberi jangkar supaya tidak menyentuh sub-path atau subdomain yang lebih panjang
Cari:    href="https://old-site.com"
Ganti:   href="https://new-site.com"

Dua hal lagi yang menyelamatkan saya dari menebak-nebak. Pertama, selalu jalankan dry run dulu. Better Search Replace punya mode "dry run" yang menghitung tanpa menulis ke database. Saya pakai itu di setiap pass sebelum melepasnya beneran. Kedua, perhatikan apa yang dilaporkan plugin: dia melaporkan jumlah PERUBAHAN, bukan jumlah kecocokan. Jadi cara mengonfirmasi kelengkapan adalah dengan menjalankan ulang pass yang sama sampai dia melaporkan 0 perubahan. Nol perubahan berarti tidak ada lagi yang tersisa dari bentuk itu. Selama angkanya bukan nol, masih ada yang ketinggalan.

Setelah pass ter-escape, saya jalankan ulang, dapat angka besar, jalankan lagi sampai nol, lalu cek halaman-halaman yang tadinya bermasalah. Link tombol dan galeri akhirnya menunjuk domain baru.

Pelajaran

Migrasi URL bukan satu operasi find-replace. Minimal dua, karena konten ter-serialisasi dan JSON (blok Gutenberg, data widget, meta ter-serialisasi) menyimpan slash sebagai \/. Kalau Anda hanya mengganti bentuk polos, Anda meninggalkan setengah link Anda secara diam-diam, dan laporan "sukses" akan menutupinya. Selalu jalankan bentuk mentah dan bentuk \/ yang di-escape, jangkar pencarian yang rawan tabrakan dengan konteks href="...", mulai dengan dry run, dan jalankan ulang sampai plugin melaporkan nol perubahan. Yang dia hitung itu perubahan, bukan kecocokan. Hijau bukan berarti selesai; nol berarti selesai.