Argomento

Guida rapida — Genera la tua prima immagine OG

Questa guida rapida di FastOG ti permette di pubblicare la tua prima immagine Open Graph dinamica in pochi minuti. La registrazione è gratuita: poi scegli un piano Dynamic API per la quota di rendering. Puoi creare la tua chiave API e il segreto HMAC su richiesta nella dashboard. Ogni rendering è pulito: nessuna filigrana su nessun piano, incluso il tester gratuito. Prova il Free OG Image Tester per vedere la pipeline in azione, poi firma i tuoi URL seguendo i passaggi qui sotto.

Come funziona — Architettura

FastOG è progettato per immagini OG on-demand: il tuo sito firma un URL al momento del rendering della pagina, il crawler lo recupera, FastOG renderizza la PNG una sola volta e Cloudflare la mette in cache, così ogni richiesta successiva è istantanea e gratuita.

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

Le tre regole che lo fanno funzionare "senza sforzo"

  1. Firma il contenuto, non l'orologio. La firma copre ogni parametro (titolo, template, …). Parametri identici producono sempre l'URL identico — è questo che fa funzionare la cache periferica: stesso contenuto → stesso URL → cache hit per sempre.
  2. L'immagine è permanente dopo il primo rendering. La firma controlla solo il primo rendering. Una volta che un'immagine è stata renderizzata, la periferia di FastOG la conserva per un anno, indicizzata sui parametri del contenuto — le richieste successive con gli stessi parametri vengono servite dalla periferia e non raggiungono mai il renderer (non contano contro la tua quota). Una firma non valida su contenuto in cache restituisce comunque la PNG in cache (la risposta indica quale livello ha risposto: X-FastOG-Worker-Cache: HIT o R2); solo un miss in cache riceve un 401.
  3. L'unico caso di errore. Un URL manomesso (qualcuno modifica title/template) riceve 401 da FastOG su un cache miss — quindi non può mai essere usato per consumare la tua quota. Gli URL legittimi non scadono mai: restano validi finché non ruoti il segreto HMAC della chiave.

1. Ottieni la tua chiave API e il segreto HMAC

  1. Vai su Dashboard FastOG → Chiavi API

  2. Clicca su "Crea nuova chiave API"

  3. Assegna un nome (es. "Sito di produzione")

  4. Copia entrambi i valori (mostrati solo una volta!):

    • Chiave API: sk_... (32 caratteri dopo il prefisso)
    • Segreto HMAC: stringa esadecimale di 64 caratteri
  5. Salvali nel tuo ambiente:

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. Implementare la funzione di firma URL

Per tutorial completi con più framework e pattern, consulta:

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. Utilizzo nel tuo blog/sito web

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>

Django Template

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. Testa la tua implementazione

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>"

Risultato atteso:

  • ✅ Firma valida → Restituisce l'immagine OG
  • ❌ Parametro alterato (es. title modificato) → {"code": "invalid_signature"}
  • ❌ Firma non valida → {"code": "invalid_signature"}

5. Checklist di sicurezza

  • [ ] Segreto HMAC archiviato nelle variabili d'ambiente (non nel codice)
  • [ ] Utilizzo di HTTPS per tutte le richieste
  • [ ] Segreto mai esposto nel JavaScript lato client
  • [ ] Monitoraggio dei tentativi di firma falliti

6. Gestione degli errori

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;
    }
}

Passaggi successivi

  1. Implementa la firma nel backend del tuo sito web (vedi i tutorial)
  2. Testa con l'API FastOG
  3. Monitora i log per i tentativi di firma falliti
  4. Configura avvisi per fallimenti ripetuti

Per la documentazione completa, consulta la Guida alla firma HMAC.

Riferimento API Completo

Provalo gratis — nessuna registrazione richiesta

Anteprima e test delle immagini OG dinamiche in pochi secondi.

Apri il tester gratuito di immagini OG

A BeCaSimulations site