DEV Community

Cover image for Meta Tag HTML — Catatan Pribadi
Sanudin
Sanudin

Posted on

Meta Tag HTML — Catatan Pribadi

🌐 Baca artikel ini dalam Bahasa Inggris di sini


Saya selalu mencari-cari lagi hal ini setiap memulai proyek baru, jadi ini tempat untuk mengumpulkan semuanya jadi satu — lengkap dengan catatan singkat kenapa masing-masing penting, supaya di masa depan tidak perlu memikirkan ulang dari nol.

Lompat ke:


Pengaturan Dasar Dokumen dan Responsif

<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
Enter fullscreen mode Exit fullscreen mode
  • charset="UTF-8" — harus berada di bagian atas <head>. Jika browser menemukan byte non-ASCII sebelum menemukan deklarasi charset, dokumen bisa saja di-parse ulang dari awal.
  • viewport — tanpa ini, tampilan mobile hanya menampilkan layout desktop yang di-zoom out. Wajib, selalu disertakan.

SEO dan Indexing Dasar

<meta name="description" content="...">
<meta name="robots" content="index, follow">
<link rel="canonical" href="https://sanudin.dev/">
Enter fullscreen mode Exit fullscreen mode
  • description — cuplikan yang muncul di bawah link pada hasil pencarian, sekitar 150–160 karakter. Tidak langsung memengaruhi ranking, tapi memengaruhi click-through rate.
  • robots — defaultnya sudah index, follow, jadi tag ini hanya perlu dipasang jika saya ingin sebaliknya (noindex, nofollow pada rute staging).
  • canonical — menunjuk ke URL "asli" ketika konten yang sama bisa diakses lewat beberapa URL (trailing slash, query parameter, dan sejenisnya).

Social Card (OG + X)

Open Graph adalah standar universal untuk preview card di Facebook, LinkedIn, Discord, dan Slack. X menggunakan fallback ke OG kecuali saya menambahkan tag twitter:* secara khusus.

Ukuran gambar yang perlu diingat: 1200×630px (rasio 1.91:1).

<meta property="og:type" content="website">
<meta property="og:title" content="Sanudin | Software Engineer">
<meta property="og:description" content="Backend-first software engineer writing about web development, from Indonesia.">
<meta property="og:image" content="https://sanudin.dev/og-cover.png">
<meta property="og:url" content="https://sanudin.dev/">
<meta property="og:site_name" content="Sanudin">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">

<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="Sanudin | Software Engineer">
<meta name="twitter:description" content="Backend-first software engineer writing about web development, from Indonesia.">
<meta name="twitter:image" content="https://sanudin.dev/og-cover.png">
Enter fullscreen mode Exit fullscreen mode

Pengingat: og:type sebaiknya article untuk halaman blog post, sementara website hanya untuk homepage atau landing page.


GEO / AI Crawler

Ada dua tempat terpisah untuk mengatur hal ini — meta tag (level halaman) dan robots.txt (level situs).

<meta name="robots" content="noai, noimageai">
Enter fullscreen mode Exit fullscreen mode
User-agent: GPTBot
Disallow: /

User-agent: ClaudeBot
Disallow: /

User-agent: Googlebot
Allow: /
Enter fullscreen mode Exit fullscreen mode

Catatan untuk diri sendiri: noai/noimageai bukan tag standar resmi (bermula dari DeviantArt, 2022) — adopsinya masih tidak merata. robots.txt adalah yang benar-benar berpengaruh jika saya peduli soal pemblokiran AI training.

JSON-LD untuk identitas — kenapa ini penting

Blok ini bukan untuk manusia, melainkan untuk search engine dan sistem AI yang mencoba mengenali siapa yang sedang berbicara. Halaman yang penuh teks "Saya Sanudin, software engineer" adalah sesuatu yang harus mereka simpulkan sendiri; blok JSON-LD langsung menyatakannya sebagai fakta terstruktur.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Person",
  "name": "Sanudin",
  "jobTitle": "Software Engineer",
  "url": "https://sanudin.dev",
  "sameAs": [
    "https://github.com/sanudin-dev",
    "https://linkedin.com/in/sanudin"
  ],
  "knowsAbout": ["TypeScript", "Next.js", "Node.js", "PHP", "Web Development"]
}
</script>
Enter fullscreen mode Exit fullscreen mode
  • @type: "Person" — menandai ini secara spesifik sebagai data tentang sebuah entitas, bukan sekadar konten halaman. Ini yang membedakan search engine menebak-nebak siapa penulisnya dengan diberi tahu secara langsung.
  • sameAs — field inilah yang benar-benar bekerja. Field ini yang memungkinkan search engine atau sistem AI menghubungkan "Sanudin di GitHub," "Sanudin di LinkedIn," dan "Sanudin di sanudin.dev" sebagai orang yang sama, bukan tiga sebutan yang tidak berhubungan. Tanpa array ini, setiap profil menjadi pulau tersendiri.
  • jobTitle — perlu sama persis dengan wording bio kanonik saya ("Software Engineer," bukan sinonimnya). Konsistensi di semua profil itulah yang sebenarnya membangun asosiasi entitas ini — jika tidak cocok, justru berlawanan dengan tujuan blok ini.
  • knowsAbout — sinyal topik, bukan keyword stuffing. Harus benar-benar merefleksikan apa yang didukung oleh konten situs, kalau tidak hanya menjadi noise.
  • Sebelum publish: periksa lewat Google Rich Results Test atau schema.org validator. JSON-LD gagalnya diam-diam — kesalahan penulisan hanya akan diabaikan, bukan memunculkan error yang akan saya sadari.
  • Ini adalah schema identitas situs. Jika nanti ingin setiap post memiliki structured data sendiri, itu tipe Article terpisah dengan field author yang menunjuk kembali ke Person ini — tambahan untuk nanti, bukan sesuatu yang perlu dikerjakan sekarang.

Header Keamanan

Content Security Policy — fungsi masing-masing bagiannya

<meta http-equiv="Content-Security-Policy"
      content="default-src 'self'; script-src 'self' https://trustedscripts.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:;">
Enter fullscreen mode Exit fullscreen mode
  • default-src 'self' — baseline: tidak ada yang boleh dimuat kecuali dari origin yang sama. Setiap directive di bawah ini adalah pengecualian dari aturan ini.
  • script-src 'self' https://trustedscripts.com — hanya script milik saya sendiri dan satu domain yang di-whitelist ini yang boleh berjalan. Ini directive yang benar-benar penting untuk menghentikan script hasil injeksi/XSS — fakta bahwa saya tidak menambahkan 'unsafe-inline' di sini adalah bagian pentingnya, bukan kelalaian.
  • style-src 'self' 'unsafe-inline''unsafe-inline' di sini adalah trade-off yang nyata, bukan default yang bisa diabaikan begitu saja. Diperlukan karena banyak framework menyuntikkan style="" saat runtime, tapi ini memang melemahkan proteksi terhadap inline style hasil injeksi (ada teknik CSS-based UI-redress/exfiltration nyata yang memanfaatkan celah ini). Risikonya jauh lebih kecil dibanding jika ini dipasang pada script-src, tapi jika suatu saat ingin menutup celah ini, solusinya adalah nonce atau hash per blok style, bukan sekadar menghapus directive-nya.
  • img-src 'self' data: https:data: mengizinkan gambar base64 inline (ikon kecil, placeholder), https: mengizinkan gambar dari domain HTTPS mana pun secara luas sehingga tidak perlu mempertahankan daftar allowlist untuk setiap domain gambar.

Pengingat soal keterbatasan lewat meta tag: frame-ancestors, report-uri/report-to, dan sandbox tidak berfungsi jika CSP diatur lewat <meta> — hanya bisa lewat HTTP header sesungguhnya. Alasannya soal timing: proteksi-proteksi spesifik itu harus sudah aktif sebelum halaman mulai memuat apa pun, dan meta tag yang berada di dalam HTML sudah terlambat untuk itu. Versi meta ini adalah fallback untuk kondisi di mana saya tidak memiliki kendali atas header server (static hosting), bukan pengganti penuh.

Referrer Policy — apa yang sebenarnya dikirim oleh strict-origin-when-cross-origin

<meta name="referrer" content="strict-origin-when-cross-origin">
Enter fullscreen mode Exit fullscreen mode

Rincian apa yang sebenarnya dilakukan value ini, karena "strict-origin-when-cross-origin" tidak menjelaskan dirinya sendiri:

  • Request same-origin → mengirim URL lengkap (path + query string).
  • Request cross-origin, tapi level keamanan protokol sama (https → https) → hanya mengirim origin-nya (scheme + host), bukan path-nya.
  • Request downgrade (https → http) → tidak mengirim apa pun.

Kenapa ini penting: tanpa ini, mengklik link keluar bisa membocorkan path internal dan query string situs ke situs tujuan link tersebut. Catatan untuk diri sendiri: sebagian besar browser modern sekarang sudah default ke kebijakan ini secara persis, jadi tag ini lebih soal eksplisit dan berjaga-jaga jika default-nya berubah (atau ada policy lain yang diatur di tempat lain yang berkonflik) daripada benar-benar wajib hari ini.

Value lain yang perlu diingat jika membutuhkan yang lebih ketat atau lebih longgar: no-referrer (tidak mengirim apa pun sama sekali — paling privat, tapi bisa mengganggu analytics atau alur auth berbasis referrer), same-origin (tidak ada yang cross-origin sama sekali), unsafe-url (selalu mengirim URL lengkap — sebaiknya dihindari, paling banyak bocor).


PWA / Browser

<meta name="theme-color" media="(prefers-color-scheme: light)" content="#ffffff">
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#09090b">
Enter fullscreen mode Exit fullscreen mode

Mewarnai UI chrome browser itu sendiri (address bar mobile, kartu task-switcher OS) agar sesuai dengan halaman. Dua deklarasi karena prefers-color-scheme adalah media query — satu tag tanpa itu akan memakai warna yang sama terlepas dari tema sistem.

<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="Sanudin">
Enter fullscreen mode Exit fullscreen mode
  • mobile-web-app-capable — membuat halaman masuk ke standalone mode (tanpa URL bar, tanpa navigasi browser) saat dibuka dari home screen. Ini tag yang sekarang berlaku, tanpa prefix — Chrome DevTools sekarang secara aktif menandai apple-mobile-web-app-capable yang lama sebagai deprecated dan meminta beralih ke versi ini. Safari secara historis hanya mengenali versi apple-prefixed, jadi mungkin masih perlu keduanya untuk iOS lama — perlu dicek ulang dukungan Safari terkini sebelum benar-benar meninggalkan tag lama. Selain itu: mulai iOS 26, Safari sekarang secara default membuat semua situs yang ditambahkan ke home screen langsung terbuka dalam mode web-app, sehingga tag ini pengaruhnya lebih kecil di iOS dibanding sebelumnya.
  • apple-mobile-web-app-status-bar-style — masih Apple-only, belum ada pengganti standar. black-translucent membuat konten halaman bisa scroll edge-to-edge di bawah status bar; default/black mempertahankan bar yang solid.
  • apple-mobile-web-app-title — juga masih Apple-specific, mengatur label di bawah ikon home screen. Pendekatan modernnya adalah mengatur ini lewat name/short_name di manifest.json — tag meta ini dipertahankan sebagai fallback karena Safari tidak selalu membaca nama dari manifest secara konsisten.

Catatan yang lebih besar untuk diri sendiri: panduan resmi saat ini (Chrome/web.dev) adalah lebih mengandalkan Web App Manifest untuk semua ini dalam jangka panjang, bukan meta tag-meta tag ini — mereka sudah ada sebelum spesifikasi manifest dan bisa menghasilkan fallback behavior yang lebih buruk jika manifest gagal dimuat. Anggap semua di atas sebagai lapisan kompatibilitas praktis, bukan kondisi ideal.

<link rel="manifest" href="/manifest.json">
<link rel="apple-touch-icon" href="/icons/apple-icon-180.png">
<link rel="icon" href="/favicon.ico" sizes="any">
<link rel="icon" href="/icon.svg" type="image/svg+xml">
Enter fullscreen mode Exit fullscreen mode

Ini fondasi sebenarnya — manifest.json adalah tempat name, icons, start_url, display mode, dan theme color seharusnya berada ke depannya. apple-touch-icon tetap dipisah sebagai link karena Safari memperlakukannya sebagai override, bukan membaca icon dari manifest secara konsisten.


Tabel Referensi

Tag Fungsi
charset Encoding karakter yang benar
viewport Rendering responsif di mobile
description Teks cuplikan SERP
robots Instruksi index/crawl
canonical Menghindari masalah duplicate-content
og:* Preview card (FB, LinkedIn, Discord)
twitter:* Preview card di X
robots: noai, noimageai Sinyal opt-out AI training (sukarela)
robots.txt (GPTBot, dll) Blokir AI crawler level situs
JSON-LD (Person) Data identitas terstruktur untuk AI/search
Content-Security-Policy Membatasi sumber script/style/media yang diizinkan
referrer Mengontrol data referrer yang keluar
theme-color Warna chrome browser mobile
mobile-web-app-capable Mode standalone (tag yang berlaku sekarang)
apple-mobile-web-app-* Perilaku home screen khusus iOS
manifest Kemampuan install PWA

Yang Saya Pakai

Selalu: charset, viewport, description, canonical, og:/twitter:.

Setelah dasarnya beres: robots (hanya jika benar-benar butuh noindex), theme-color, tag PWA, CSP.

Situasional, dicek ulang jika relevan: tag GEO, JSON-LD.


Originally published at: HTML Meta Tags: My Reference Notes

Top comments (0)