SEO & Analytics Skill
Skill untuk optimasi mesin pencari, meta tags, tracking analytics, dan performa web.
Meta Tags Essentials
HTML Head Template
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- SEO Basic -->
<title>{Judul Halaman} | {Nama Brand}</title>
<meta name="description" content="{Deskripsi 150-160 karakter}" />
<meta name="keywords" content="{keyword1, keyword2, keyword3}" />
<meta name="author" content="{Nama Usaha}" />
<link rel="canonical" href="https://example.com/halaman" />
<!-- Open Graph (Facebook, WhatsApp, dll) -->
<meta property="og:title" content="{Judul}" />
<meta property="og:description" content="{Deskripsi}" />
<meta property="og:image" content="https://example.com/og-image.jpg" />
<meta property="og:url" content="https://example.com/halaman" />
<meta property="og:type" content="website" />
<meta property="og:locale" content="id_ID" />
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="{Judul}" />
<meta name="twitter:description" content="{Deskripsi}" />
<meta name="twitter:image" content="https://example.com/og-image.jpg" />
<!-- Favicon -->
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
<!-- Fonts preload -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
</head>
React Helmet / Dynamic Meta
// Untuk React SPA — pakai react-helmet-async
import { Helmet } from 'react-helmet-async'
function ProductPage({ product }) {
return (
<>
<Helmet>
<title>{product.nama} | Toko Online</title>
<meta name="description" content={product.deskripsi.slice(0, 160)} />
<meta property="og:title" content={product.nama} />
<meta property="og:image" content={product.gambar} />
</Helmet>
{/* ... page content */}
</>
)
}
Structured Data (Schema.org)
Local Business
{
"@context": "https://schema.org",
"@type": "LocalBusiness",
"name": "Nama Usaha",
"description": "Deskripsi usaha",
"url": "https://example.com",
"telephone": "+6281234567890",
"address": {
"@type": "PostalAddress",
"streetAddress": "Jl. Contoh No.1",
"addressLocality": "Jakarta",
"addressRegion": "DKI Jakarta",
"postalCode": "12345",
"addressCountry": "ID"
},
"geo": {
"@type": "GeoCoordinates",
"latitude": -6.2088,
"longitude": 106.8456
},
"openingHours": "Mo-Sa 08:00-20:00",
"priceRange": "Rp"
}
Product
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Nama Produk",
"description": "Deskripsi produk",
"image": "https://example.com/produk.jpg",
"offers": {
"@type": "Offer",
"price": "150000",
"priceCurrency": "IDR",
"availability": "https://schema.org/InStock"
}
}
Breadcrumb
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{ "@type": "ListItem", "position": 1, "name": "Home", "item": "https://example.com" },
{ "@type": "ListItem", "position": 2, "name": "Katalog", "item": "https://example.com/katalog" },
{ "@type": "ListItem", "position": 3, "name": "Bolu Coklat" }
]
}
Sitemap & Robots
sitemap.xml
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://example.com/</loc>
<lastmod>2024-01-01</lastmod>
<changefreq>daily</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>https://example.com/katalog</loc>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
</urlset>
robots.txt
User-agent: *
Allow: /
Disallow: /admin
Disallow: /api/
Sitemap: https://example.com/sitemap.xml
Google Analytics 4 (GA4)
Setup
<!-- Global tag di index.html -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXXXXXXXX');
</script>
Track Custom Events
// Track pembelian
gtag('event', 'purchase', {
transaction_id: pesanan.nomorInvoice,
value: pesanan.total,
currency: 'IDR',
items: pesanan.items.map(i => ({
item_id: i.produkId,
item_name: i.nama,
price: i.harga,
quantity: i.jumlah,
}))
})
// Track add to cart
gtag('event', 'add_to_cart', {
currency: 'IDR',
value: item.harga,
items: [{ item_id: item.id, item_name: item.nama }]
})
// Track search
gtag('event', 'search', { search_term: query })
React SPA — Track Page Views
import { useEffect } from 'react'
import { useLocation } from 'react-router-dom'
function usePageTracking() {
const location = useLocation()
useEffect(() => {
gtag('event', 'page_view', {
page_path: location.pathname,
page_title: document.title,
})
}, [location])
}
Core Web Vitals
3 Metrik Utama
| Metrik | Apa Itu | Target | Cara Fix |
|---|---|---|---|
| LCP (Largest Contentful Paint) | Waktu load elemen terbesar | < 2.5s | Optimize images, preload fonts, SSR |
| INP (Interaction to Next Paint) | Responsivitas interaksi | < 200ms | Reduce JS, defer non-critical, web workers |
| CLS (Cumulative Layout Shift) | Stabilitas visual layout | < 0.1 | Set image dimensions, no dynamic inject above fold |
Optimasi Performa
Image Optimization
<!-- Lazy load images -->
<img src="photo.jpg" loading="lazy" width="400" height="300" alt="Deskripsi" />
<!-- Responsive images -->
<img
srcset="photo-400.webp 400w, photo-800.webp 800w, photo-1200.webp 1200w"
sizes="(max-width: 768px) 100vw, 50vw"
src="photo-800.webp"
alt="Deskripsi"
/>
<!-- Preload hero image -->
<link rel="preload" as="image" href="/hero.webp" />
Code Splitting (React + Vite)
import { lazy, Suspense } from 'react'
const Dashboard = lazy(() => import('./modules/dashboard/Dashboard'))
const Laporan = lazy(() => import('./modules/laporan/Laporan'))
// Dalam routes
<Suspense fallback={<LoadingSpinner />}>
<Dashboard />
</Suspense>
Bundle Analysis
# Vite
npx vite-bundle-visualizer
# Webpack
npx webpack-bundle-analyzer stats.json
Lighthouse Checklist
Performance (target > 90)
- Images dalam format WebP/AVIF
- Lazy load images & iframes
- Code splitting per route
- Minify CSS & JS (otomatis di Vite production)
- Gzip/Brotli compression di server
- Cache headers untuk static assets
SEO (target 100)
-
<title>unik per halaman -
<meta description>per halaman - Heading hierarchy (h1 → h2 → h3)
-
alttext pada semua images -
<link rel="canonical"> - sitemap.xml & robots.txt
- Structured data (JSON-LD)
Accessibility (target > 90)
- Kontras warna ≥ 4.5:1
- Focus visible pada interactive elements
- Semantic HTML (
nav,main,button) -
aria-labelpada icon buttons - Skip navigation link
- Form labels
Best Practices (target 100)
- HTTPS
- No console errors
- No deprecated APIs
- Security headers (CSP, X-Frame-Options)