FastOG
Topik

Panduan Memulai — Buat Gambar OG Pertama Anda

Panduan memulai FastOG ini membantu Anda menayangkan gambar Open Graph dinamis pertama dalam hitungan menit. Pendaftaran gratis — lalu pilih paket Dynamic API untuk kuota render. Anda membuat kunci API dan rahasia HMAC sesuai kebutuhan di dasbor. Setiap render bersih — tanpa tanda air di paket mana pun, termasuk penguji gratis. Coba Penguji Gambar OG Gratis untuk melihat alur kerja secara langsung, lalu tandatangani URL Anda sendiri dengan langkah-langkah di bawah ini.

Cara kerjanya — Arsitektur

FastOG dibangun untuk gambar OG sesuai permintaan: situs web Anda menandatangani URL saat waktu render halaman, crawler mengambilnya, FastOG merender PNG sekali, dan Cloudflare menyimpannya dalam cache sehingga setiap pengambilan berikutnya bersifat instan dan gratis.

sequenceDiagram
    participant You as You share a link
    participant Crawler as Social crawler
    participant Site as Your website
    participant FastOG as FastOG API
    participant Edge as Edge cache

    You->>Crawler: share a link to your post
    Crawler->>Site: GET the page without JavaScript
    Site->>Site: sign the og:image URL at render time
    Site-->>Crawler: HTML with signed og:image URL
    Crawler->>Edge: fetch the og:image URL
    Edge->>FastOG: cache miss, first time
    FastOG->>FastOG: verify the HMAC covers the exact params
    FastOG-->>Edge: render PNG, counts 1 toward monthly quota, cached for 1 year
    Edge-->>Crawler: PNG
    Crawler-->>You: image shown in the post preview
    Note over Edge, Crawler: identical params and URL mean a cache hit with no render

Tiga aturan yang membuatnya "langsung berfungsi"

  1. Tandatangani kontennya, bukan waktunya. Tanda tangan mencakup setiap parameter (judul, template, …). Parameter yang identik selalu menghasilkan URL yang identik — itulah yang membuat cache edge berfungsi: konten yang sama → URL yang sama → cache hit selamanya.
  2. Gambar bersifat permanen setelah render pertama. Tanda tangan hanya menggerbang render pertama. Setelah gambar dirender, edge FastOG menyimpannya selama satu tahun dengan kunci pada parameter konten — permintaan berikutnya dengan parameter yang sama dilayani dari edge dan tidak pernah mengenai renderer (tidak dihitung ke kuota Anda). Tanda tangan yang salah pada konten yang sudah di-cache tetap mengembalikan PNG yang di-cache (respons melaporkan tier mana yang menjawab: X-FastOG-Worker-Cache: HIT atau R2); hanya cache miss yang mendapat 401.
  3. Satu-satunya mode kegagalan. URL yang dirusak (seseorang mengubah title/template) mendapat 401 di FastOG saat cache miss — sehingga tidak akan pernah bisa digunakan untuk menghabiskan kuota Anda. URL yang sah tidak pernah kedaluwarsa: URL tetap valid sampai Anda memutar rahasia HMAC kunci.

1. Dapatkan Kunci API dan Rahasia HMAC Anda

  1. Buka Dasbor FastOG → Kunci API

  2. Klik "Buat Kunci API Baru"

  3. Beri nama (misalnya, "Situs Produksi")

  4. Salin kedua nilai (hanya ditampilkan sekali!):

    • Kunci API: sk_... (32 karakter setelah awalan)
    • Rahasia HMAC: string heksadesimal 64 karakter
  5. Simpan keduanya di lingkungan Anda:

env
# Your website backend .env
FASTOG_API_KEY=sk_your_full_api_key
FASTOG_HMAC_SECRET=a1b2c3d4e5f6...  # 64 chars
FASTOG_API_URL=https://fastog.com/api/v1/og

2. Implementasikan Fungsi Penandatanganan URL

Untuk tutorial lengkap dengan berbagai framework dan pola, lihat:

Node.js / Next.js

javascript
// lib/fastog-signer.js
import crypto from "crypto";

// RFC-3986 encode (encodeURIComponent leaves !'()* unencoded).
const enc = (s) =>
    encodeURIComponent(s).replace(
        /[!'()*]/g,
        (c) => "%" + c.charCodeAt(0).toString(16).toUpperCase(),
    );

export function generateOgImageUrl(params) {
    const baseUrl = process.env.FASTOG_API_URL;
    const apiKey = process.env.FASTOG_API_KEY;
    const hmacSecret = process.env.FASTOG_HMAC_SECRET;

    const all = { ...params, key: apiKey };

    // Canonical: every param (except s), sorted, RFC-3986 encoded, joined with "&".
    const pairs = [];
    for (const [k, v] of Object.entries(all)) {
        for (const vv of Array.isArray(v) ? v : [v])
            pairs.push(`${enc(k)}=${enc(vv)}`);
    }
    pairs.sort();
    const canonical = pairs.join("&");

    // Content-signed: message = path + canonical query. No timestamp.
    const signature = crypto
        .createHmac("sha256", hmacSecret)
        .update(`GET/api/v1/og\n${canonical}`)
        .digest("hex");

    const url = new URL(baseUrl);
    for (const [k, v] of Object.entries(all)) {
        for (const vv of Array.isArray(v) ? v : [v])
            url.searchParams.append(k, vv);
    }
    url.searchParams.set("s", signature);
    return url.toString();
}

PHP (Laravel)

php
// app/Services/QuickogSigner.php
function generateOgImageUrl(array $params): string
{
    $baseUrl = config('services.fastog.api_url', 'https://fastog.com/api/v1/og');
    $apiKey = config('services.fastog.api_key');
    $hmacSecret = config('services.fastog.hmac_secret');

    $all = array_merge($params, ['key' => $apiKey]);

    // Canonical: every param except s, keys sorted (array values sorted too),
    // RFC-3986 encoded, joined with '&'. Content-signed — no timestamp.
    $pairs = [];
    foreach ($all as $k => $v) {
        $values = is_array($v) ? $v : [$v];
        sort($values, SORT_STRING);
        foreach ($values as $vv) {
            $pairs[] = rawurlencode((string) $k) . '=' . rawurlencode((string) $vv);
        }
    }
    sort($pairs, SORT_STRING);
    $canonical = implode('&', $pairs);

    $signature = hash_hmac('sha256', 'GET/api/v1/og' . "\n" . $canonical, $hmacSecret);

    return $baseUrl . '?' . http_build_query(array_merge($all, ['s' => $signature]));
}

Python (Django/FastAPI)

python
# utils/fastog.py
import hmac
import hashlib
import os
from urllib.parse import quote, urlencode

def _enc(s):
    return quote(str(s), safe='-._~')  # RFC-3986: only unreserved chars

def generate_og_image_url(params: dict) -> str:
    base_url = os.environ['FASTOG_API_URL']
    api_key = os.environ['FASTOG_API_KEY']
    hmac_secret = os.environ['FASTOG_HMAC_SECRET']

    all_params = {**params, 'key': api_key}

    # Canonical: every param except s, sorted, RFC-3986 encoded, joined with '&'.
    pairs = []
    for k, v in all_params.items():
        for vv in sorted(v if isinstance(v, list) else [v]):
            pairs.append(f"{_enc(k)}={_enc(vv)}")
    canonical = '&'.join(sorted(pairs))

    # Content-signed: message = path + canonical query. No timestamp.
    signature = hmac.new(
        hmac_secret.encode(),
        f"GET/api/v1/og\n{canonical}".encode(),
        hashlib.sha256,
    ).hexdigest()

    return f"{base_url}?{urlencode({**all_params, 's': signature})}"

3. Penggunaan di Blog/Situs Web Anda

Next.js App Router

tsx
// app/blog/[slug]/page.tsx
import { generateOgImageUrl } from "@/lib/fastog-signer";

export async function generateMetadata({ params }) {
    const post = await getPost(params.slug);

    const ogImageUrl = generateOgImageUrl({
        template: "blog",
        title: post.title,
        subtitle: post.excerpt,
        author: post.author.name,
    });

    return {
        title: post.title,
        description: post.excerpt,
        openGraph: {
            images: [ogImageUrl],
        },
    };
}

Laravel Blade

blade
{{-- resources/views/blog/show.blade.php --}}
@php
    $ogImageUrl = generateOgImageUrl([
        'template' => 'blog',
        'title' => $post->title,
        'subtitle' => $post->excerpt,
        'author' => $post->author->name,
    ]);
@endphp

<head>
    <meta property="og:image" content="{{ $ogImageUrl }}" />
    <meta property="og:title" content="{{ $post->title }}" />
    <meta property="og:description" content="{{ $post->excerpt }}" />
</head>

Template Django

django
{# blog/post_detail.html #}
{% load fastog_tags %}

<head>
    <meta property="og:image" content="{% generate_og_image_url post %}" />
    <meta property="og:title" content="{{ post.title }}" />
    <meta property="og:description" content="{{ post.excerpt }}" />
</head>

4. Uji Implementasi Anda

bash
# Generate a test URL
node -e "
const { generateOgImageUrl } = require('./lib/fastog-signer');
console.log(generateOgImageUrl({ title: 'Test', template: 'default' }));
"

# Test with curl
curl "https://fastog.com/api/v1/og?title=Test&key=sk_quick_123abc&s=<sig>"

Hasil yang diharapkan:

  • ✅ Tanda tangan valid → Mengembalikan gambar OG
  • ❌ Parameter yang diubah (misalnya title diubah) → {"code": "invalid_signature"}
  • ❌ Tanda tangan tidak valid → {"code": "invalid_signature"}

5. Daftar Periksa Keamanan

  • [ ] Rahasia HMAC disimpan dalam variabel lingkungan (bukan di dalam kode)
  • [ ] Menggunakan HTTPS untuk semua permintaan
  • [ ] Rahasia tidak pernah terekspos dalam JavaScript sisi klien
  • [ ] Memantau upaya tanda tangan yang gagal

6. Menangani Kesalahan

javascript
if (response.status === 401) {
    const error = await response.json();

    switch (error.code) {
        case "missing_signature":
            // URL is missing `key` or `s` — re-generate it with your signer.
            break;
        case "invalid_signature":
            // A param changed after signing, or the secret doesn't match.
            // Re-sign the URL after any content change; verify the secret on both sides.
            break;
    }
}

Langkah Berikutnya

  1. Implementasikan penandatanganan (signing) di backend situs web Anda (lihat tutorial)
  2. Uji dengan API FastOG
  3. Pantau log untuk percobaan tanda tangan yang gagal
  4. Siapkan peringatan (alerting) untuk kegagalan berulang

Untuk dokumentasi lengkap, lihat Panduan Tanda Tangan HMAC.

Referensi API Lengkap

Coba gratis — tanpa perlu mendaftar

Pratinjau dan uji gambar OG dinamis dalam hitungan detik.

Buka Penguji Gambar OG Gratis

A BeCaSimulations site