Sign inGet Started

Template email

Un template è un oggetto e un corpo email che salvi una volta e invii molte volte. Scrivi le parti variabili come segnaposto {{ variable }}, pubblichi il template e poi lo invii per slug invece di incollare lo stesso HTML in ogni chiamata API. Un template appartiene al tuo spazio di lavoro.

Crea e gestisci i template in Email > Templates, tramite /v1/email/templates, con il bird CLI, o tramite il server MCP. I metodi tipizzati sono disponibili negli SDK TypeScript, Python, PHP e Go sotto email.templates. Gli schemi completi di richiesta e risposta sono nel reference API. Invia un template pubblicato tramite il normale endpoint di invio.

Cosa contiene un template

Ogni template ha due nomi, e svolgono funzioni diverse:

  • slug è il nome con cui invii il template, ad esempio welcome-email. Lo scegli quando crei il template e non può essere modificato in seguito. Uno slug può contenere lettere minuscole, numeri, trattini e underscore, deve iniziare e finire con una lettera o un numero e può essere lungo fino a 63 caratteri. Due prefissi sono riservati: bird_, riservato ai nostri template predefiniti, e emt_, che è il formato usato per gli ID dei template. La dashboard chiama questo campo Alias.
  • name è un'etichetta di visualizzazione a testo libero. Per impostazione predefinita corrisponde allo slug, e puoi modificarla in qualsiasi momento. Nessuna risoluzione avviene tramite il nome, quindi rinominare un template a scopo di visualizzazione non interrompe mai un invio.

Oltre a questi, un template ha un ID emt_ permanente, fisso per tutta la sua vita. Ha anche una category, che può essere marketing o transactional, e un source di authoring: html, markup finito che fornisci tu, opzionalmente personalizzato con Liquid. La categoria e la sorgente sono entrambe fissate quando crei il template.

Forniamo un catalogo di template predefiniti, i cui slug iniziano tutti con bird_. Un template predefinito non appartiene ad alcuno spazio di lavoro, non può essere modificato ed è sempre inviabile così com'è. Copialo nel tuo spazio di lavoro per farlo tuo: diventa un template ordinario che puoi modificare. La copia arriva come bozza non pubblicata che eredita la categoria, la sorgente e le impostazioni di lingua dell'originale, quindi pubblicala prima di inviarla.

Bozze e versioni pubblicate

Ogni template ha esattamente una bozza, che è la copia di lavoro su cui apporti le modifiche. Ha anche un numero qualsiasi di versioni pubblicate, ciascuna numerata (1, 2, 3 e così via) e mai più modificata una volta creata. Le modifiche cambiano la bozza sul posto. La pubblicazione scatta un'istantanea della bozza corrente, la trasforma nella versione numerata successiva e rende quella versione quella usata dagli invii. La bozza stessa resta modificabile, così puoi continuare a lavorare sulla prossima.

La regola che conta per l'invio è questa: un invio usa sempre la versione pubblicata del template, e una bozza non viene mai inviata da sola. Puoi continuare a modificare la bozza mentre una versione stabile continua a essere inviata, e poi pubblicare quando la modifica è pronta. Pubblicare una nuova versione cambia ciò che gli invii successivi renderizzano. Un invio già accettato non è influenzato da una pubblicazione avvenuta dopo.

La scheda Versioni del template con una riga Bozza e le righe delle versioni pubblicate v3, v2 e v1 che mostrano le date di creazione e pubblicazione

Le versioni supportano altre due azioni. Scarta le modifiche della bozza per ripristinare la bozza allo stato della versione attualmente pubblicata. Oppure esegui un rollback per rendere una versione pubblicata precedente quella usata dagli invii. Puoi eseguire il rollback solo a una versione pubblicata, mai alla bozza stessa. Il rollback sostituisce la bozza con il contenuto di quella versione, quindi qualsiasi modifica non salvata nella bozza va persa, e le modifiche successive partono dalla versione a cui hai fatto rollback. Un rollback non crea una nuova versione.

Per scegliere un'immagine esistente, hai bisogno dell'accesso in lettura alla libreria multimediale dello spazio di lavoro. Per caricare, incollare o trascinare una nuova immagine, hai bisogno dell'accesso in scrittura. Se Inserisci immagine è disabilitato o non riesci a sfogliare o caricare, chiedi a un amministratore dello spazio di lavoro il permesso corrispondente per la libreria multimediale. Il solo permesso di modifica dei template non concede l'accesso alla libreria multimediale.

Nella dashboard, scegli Visual > Inserisci immagine per cercare nella libreria multimediale o caricare un'immagine PNG, JPEG, GIF o WebP fino a 5 MB. I caricamenti di WebP statici vengono convertiti in PNG o JPEG. Seleziona l'immagine per impostarne la Descrizione immagine, la larghezza di visualizzazione, l'allineamento e il link. Contrassegna un'immagine come Immagine decorativa solo quando non aggiunge informazioni; un'immagine con link ha bisogno di una descrizione che ne spieghi la destinazione. Ogni lingua mantiene le proprie descrizioni delle immagini e il proprio layout.

Usa Sostituisci immagine per cambiare un'immagine selezionata mantenendone descrizione, link, larghezza e allineamento. Puoi anche incollare o trascinare un file immagine nell'editor visuale. Attendi che il caricamento finisca, o annullalo, prima di salvare o inviare un test. Controlla l'anteprima, poi apri Altre azioni > Email di test per inviare il contenuto corrente a te stesso. Codice resta disponibile per modificare l'HTML.

Rimuovere un'immagine dalla libreria multimediale non la rimuove dalle email già inviate. La sostituzione di un'immagine usa un nuovo URL, quindi i messaggi precedenti continuano a mostrare l'originale.

Il salvataggio è protetto da un numero di revisione. Invia la revision che hai letto per ultima per la lingua che stai salvando. Se qualcun altro ha modificato quella lingua nel frattempo, il salvataggio viene rifiutato come conflitto anziché sovrascrivere il suo lavoro. Ometti revision per salvare incondizionatamente. La pubblicazione e il rollback usano la revision della bozza allo stesso modo.

Contenuto in più di una lingua

Un template contiene contenuto in un massimo di 25 lingue, ciascuna con il proprio oggetto e corpo, contrassegnata con un codice BCP-47 come en o pt-BR. Una lingua è quella predefinita del template. Pubblicare un template pubblica tutte le lingue che contiene contemporaneamente. Non puoi pubblicare una sola lingua, quindi devono essere tutte completate prima. Ogni lingua ha bisogno di un oggetto e di un corpo, e la lingua predefinita del template deve essere una di quelle che hai compilato. Se manca qualcosa, non viene pubblicato nulla, e l'errore ti indica cosa manca in ogni lingua così puoi correggere tutto in un solo passaggio. Non devi completare ogni lingua in anticipo: pubblica quelle pronte, e aggiungi le altre in seguito.

Una lingua ha bisogno di un corpo HTML. Puoi omettere il suo text: la pubblicazione crea automaticamente un'alternativa in testo semplice dall'HTML, così ottieni entrambe le parti senza scrivere la seconda tu stesso.

Ogni lingua può anche avere un testo di anteprima, a volte chiamato preheader: la riga che la casella di posta mostra dopo l'oggetto nell'elenco dei messaggi. È facoltativo, lungo fino a 255 caratteri, e accetta gli stessi segnaposto {{ variable }} dell'oggetto. Se lo ometti, la casella di posta ripiegherà sulla prima riga del corpo, che raramente è quella che sceglieresti. La pubblicazione rifiuta il testo di anteprima su una lingua il cui corpo non ha una parte HTML, perché un client di posta legge la riga di anteprima solo dal markup HTML nascosto, e rifiuta {{ bird.unsubscribe_url }} al suo interno per lo stesso motivo per cui l'oggetto non può contenerlo: nessuno dei due è un posto dove può andare un link.

Due impostazioni coprono un invio che non specifica una lingua per cui il template ha contenuto, e proteggono da errori diversi:

ImpostazioneCosa controlla
on_missing_languageCosa succede quando un invio richiede una lingua che il template non ha. fallback, il valore predefinito, serve la corrispondenza più vicina. Prima prova una forma più generica della stessa lingua, così un pt memorizzato può servire una richiesta per pt-BR. Poi ripiega sulla lingua predefinita del template. fail rifiuta l'invio, per contenuti in cui inviare nella lingua sbagliata è peggio che non inviare affatto.
language_source_requiredSe un invio deve specificare una lingua. Questa impostazione è disattivata per impostazione predefinita, quindi un invio che non ne specifica nessuna riceve la lingua predefinita. Attivala e l'invio viene rifiutato. Un broadcast specifica una lingua per tutto il suo pubblico, quindi un template con questa impostazione attiva richiede che la lingua sia scelta prima che il broadcast possa partire.

Puoi impostare le due opzioni in modo indipendente. Da solo, fail si applica solo quando un invio specifica una lingua che non abbiamo, quindi un invio senza lingua passa comunque. Attiva entrambe le impostazioni insieme quando vuoi che ogni invio specifichi una lingua intenzionalmente.

Personalizzazione con le variabili

Scrivi segnaposto {{ variable }} nell'oggetto, nel testo di anteprima e nel corpo. Li rileviamo automaticamente, combinati tra tutte le lingue, quindi non devi mai dichiararli separatamente. Il prefisso del segnaposto distingue i due tipi. Un percorso che inizia con bird. legge dai nostri dati, un record di contatto o il link di disiscrizione. Tutto il resto è un parametro a cui dai un valore quando invii.

Il nome di un parametro è una singola parola, come {{ animal }}. Un nome con punti cerca una struttura che un parametro non ha, quindi la pubblicazione lo rifiuta: scrivi il valore come parametro a sé, oppure leggi i dati del contatto con bird.contact.<attribute>.

In un invio singolo o in batch, il valore di un parametro proviene dall'oggetto template.parameters dell'invio, indicizzato per nome. Un unico set di valori copre tutti i destinatari di quell'invio. bird è l'unico nome che non puoi usare lì: una chiave template.parameters chiamata bird viene rifiutata con un 422.

Un broadcast non ha un oggetto parameters, quindi il suo contenuto può usare solo segnaposto bird.. bird.contact.<attribute> viene compilato dalle proprietà del contatto di ciascun destinatario, ed è questo che personalizza il contenuto per ogni destinatario. Ogni proprietà del contatto è disponibile tramite la propria chiave, così come i tre campi predefiniti: first_name, last_name e email.

Esempio di codice
Hi {{ bird.contact.first_name }},

Ogni parametro nel template deve avere un valore al momento dell'invio. In caso contrario, API restituisce un 422 che indica il parametro mancante. Fornisci i valori dei parametri per tutte le lingue, perché la lingua selezionata può dipendere dalle impostazioni di fallback. Una proprietà del contatto mancante viene resa come valore vuoto, quindi aggiungi un fallback per i contenuti visibili al cliente: {{ bird.contact.first_name | default: "there" }}.

Un broadcast è più restrittivo sui nomi che accetta, perché le proprietà del contatto sono tutto ciò di cui dispone per compilare i segnaposto. I suoi segnaposto bird.contact.* possono indicare solo un campo predefinito o una proprietà del contatto registrata nello spazio di lavoro. Qualsiasi altro segnaposto, incluso un parametro, è un valore che il broadcast non ha modo di compilare. L'invio viene rifiutato e l'errore indica il segnaposto.

Archiviare una proprietà la rimuove dal selettore delle proprietà nell'editor. Le nuove versioni del template che la leggono non possono essere pubblicate, e l'errore indica la proprietà. I template già pubblicati continuano a inviare. Annulla l'archiviazione della proprietà per usarla di nuovo nelle nuove versioni.

I segnaposto usano Liquid, quindi filtri e flussi di controllo funzionano insieme alla semplice sostituzione. Un condizionale {% if %} e un ciclo {% for %} su un valore array vanno entrambi bene. Alcuni costrutti vengono rifiutati alla pubblicazione, e l'errore indica esattamente cosa modificare:

  • Inclusioni parziali, con {% include %} o {% render %}.
  • I tag increment, decrement e ifchanged.
  • I filtri money, format_date, format_time, json, inspect e type.
  • Confronti con empty o blank. Usa .size == 0 al loro posto.
  • Blocchi annidati molto più in profondità di quanto il markup email richieda realmente.

Il template di un broadcast non può usare un ciclo {% for %}, perché un broadcast compila un solo valore per proprietà del contatto e non ha nulla su cui iterare. Se il tuo contenuto ha bisogno di un ciclo, invialo tramite l'API dei messaggi.

Ogni template usa Liquid, anche uno che contiene solo segnaposto {{ variable }}. Prima della pubblicazione, validiamo l'oggetto, il testo di anteprima, l'HTML e il contenuto in testo semplice come Liquid. Aggiungiamo inoltre il filtro escape a ogni output HTML che non termina già con escape o escape_once, in modo che un valore contenente & o < non possa alterare il markup circostante. L'output riservato per la disiscrizione resta invariato, così l'invio può sostituirlo. L'oggetto e il corpo in testo semplice restano come scritti. Poiché la pubblicazione aggiunge questi filtri, l'HTML che leggete da una versione pubblicata potrebbe non essere identico byte per byte a quello che avete inviato.

Inserite un URL completo direttamente in un href, ad esempio <a href="{{ sign_in_url }}">Sign in</a>. Non aggiungete url_encode all'intero valore. Codifica in percentuale https://, /, ? e &, il che impedisce al risultato di funzionare come link assoluto. L'escaping HTML viene aggiunto preservando la struttura dell'URL. Quando un parametro fornisce un singolo componente dell'URL, codificate quel componente esplicitamente: <a href="https://example.com/search?q={{ query | url_encode }}">Search</a>.

Anteprima prima della pubblicazione

Renderizzate un template con valori di esempio e ottenete l'oggetto e i corpi HTML e in testo semplice che un invio consegnerebbe. L'anteprima usa il nostro renderer Liquid locale e renderizza la bozza per impostazione predefinita, che è il modo per verificare una modifica prima che diventi attiva. Può renderizzare anche una versione pubblicata. Funziona sia con i vostri template sia con quelli integrati, e nulla viene inviato.

Potete anche fornire voi il contenuto anziché farlo leggere dalla bozza. Passate un oggetto e i corpi, e questi vengono renderizzati esattamente come una bozza, il che permette a un editor di mostrare una modifica mentre viene digitata senza prima salvare nulla.

La personalizzazione viene compilata per voi, così il risultato si legge come testo finito anziché come segnaposto {{ }}. Specificate un contact e ogni bird.contact.<attribute> viene risolto in base alle proprietà di quel contatto, il che vi permette di verificare il testo su un record reale prima che qualcuno lo riceva. I valori provengono dalla stessa proiezione che un broadcast usa per compilare i propri segnaposto, quindi l'anteprima risponde con ciò che risponderebbe un invio.

Omettete contact e vengono sostituiti valori segnaposto: Bird e Test per nome e cognome, bird.test@example.com per l'email e il fallback registrato di ogni altra proprietà. Una proprietà referenziata senza fallback viene renderizzata come la propria chiave tra parentesi quadre, ad esempio [loyalty_tier], il che indica sia che il valore è un segnaposto sia quale proprietà necessita ancora di un fallback.

Un contatto viene letto nel suo stato attuale. Questo rende l'anteprima lo strumento giusto per verificare contenuti che state per inviare, e quello sbagliato per vedere cosa conteneva un invio precedente. Per leggere cosa ha effettivamente consegnato un invio, aprite quel messaggio nel registro email, che lo renderizza dai valori che quell'invio conteneva.

Aggiungete language per renderizzare una lingua specifica, oppure omettetelo per usare quella predefinita del template. La risposta indica quale lingua è stata renderizzata, il che è importante quando quella richiesta non è disponibile e il on_missing_language del template ha servito una corrispondenza simile.

Se la bozza ha una personalizzazione che verrebbe rifiutata al momento della pubblicazione, l'anteprima restituisce lo stesso errore, fungendo anche da strumento per individuare i problemi in anticipo.

Nel template builder della dashboard, Preview with contact data in fondo alla barra laterale sinistra mostra l'email renderizzata accanto a ciò che state modificando, sia nell'editor visuale sia in quello del codice. Il selettore sottostante sceglie i dati di quale contatto compilano i segnaposto, e Sample data corrisponde ai valori segnaposto descritti sopra.

Invio con un template

Imposta il campo template dell'invio su un oggetto che indica il template, tramite id (emt_...) oppure tramite slug, usando esattamente uno dei due. Inserisci i valori delle variabili in template.parameters. Aggiungi language per scegliere una lingua specifica, oppure omettilo per inviare nella lingua predefinita del template, a meno che il template non richieda che ogni invio ne specifichi una. Ometti del tutto subject, html e text, perché il template li fornisce già.

Esempio di codice
{
  "from": "hello@yourdomain.com",
  "to": ["delivered@messagebird.dev"],
  "category": "transactional",
  "template": {
    "slug": "welcome-email",
    "parameters": { "first_name": "Jane" }
  }
}

Un comportamento da tenere presente: la categoria del template è un valore predefinito, e il category dell'invio la sovrascrive. Se ometti category, l'invio eredita la categoria del template, quindi un template operativo viene inviato come transazionale senza doverlo ripetere a ogni chiamata. Se imposti category, il tuo valore prevale. Il resto del contratto lato invio è in invio con un template.

Creazione al di fuori della dashboard

L'intero ciclo di vita è disponibile al di fuori della dashboard: tramite API, gli SDK sotto email.templates, il bird CLI e gli strumenti email_templates_* MCP. Negli SDK, le operazioni su versioni e lingue si trovano sotto email.templates.versions e email.templates.versions.languages. Il passaggio di pubblicazione si chiama submit, e trasforma la bozza nella versione pubblicata successiva.

Puoi conservare i template nel tuo repository e sincronizzarli da uno step di build. Una bozza e una versione pubblicata restituiscono HTML diverso, quindi scegli la lettura adatta a ciò che serve al tuo strumento:

  • Una bozza restituisce esattamente ciò che hai salvato. L'HTML che salvi in una lingua della bozza viene restituito byte per byte dalla lettura di quella lingua (GET /v1/email/templates/{id}/versions/{draft_version_id}/languages/{language}) e dalla lettura della versione, inclusi il doctype, i blocchi <style>, i commenti, gli spazi, le terminazioni di riga e il testo non ASCII. Un salvataggio non restituisce contenuto, quindi rileggi la lingua quando devi confermare cosa è stato memorizzato.
  • Una versione pubblicata restituisce contenuto pronto per l'invio. La pubblicazione riscrive l'HTML in tre modi: ogni output {{ }} che non termina già con escape o escape_once riceve il filtro escape, tranne {{ bird.unsubscribe_url }}, che resta invariato; il testo di anteprima viene inserito in un blocco nascosto subito dopo il tag di apertura <body>, oppure all'inizio se l'HTML non ne ha uno; e un text vuoto viene riempito con un'alternativa in testo semplice derivata dall'HTML. La lettura di quella versione restituisce il contenuto riscritto, che quindi non corrisponderà al tuo file sorgente.

Per esportare il sorgente che hai scritto, leggi la bozza. La lettura di un template o l'elenco dei template restituisce metadati e stato per lingua, ma non l'HTML.

Gli esempi qui sotto usano {{ first_name }}, che è un parametro: l'invio fornisce il suo valore in template.parameters, come in "parameters": {"first_name": "Jane"}. Questo è adatto a un invio verso un indirizzo email. Un segnaposto {{ bird.contact.first_name }} legge invece il record di contatto del destinatario, che un broadcast riempie dalle proprietà di contatto di ciascun destinatario. Un invio verso un indirizzo email non ha un record di contatto, quindi rifiuta un template che legge bird.contact.* con un 422 (EmailTemplateContactUnavailable).

Crea il template con la sua prima lingua. La risposta contiene l'id del template e il draft_version_id, usati dalle operazioni su versioni e lingue. L'esempio imposta anche preview_text, il testo di anteprima che un client di posta mostra dopo l'oggetto nell'elenco dei messaggi. La pubblicazione lo inserisce nell'HTML come blocco nascosto, ed è uno dei motivi per cui una versione pubblicata restituisce HTML diverso dalla bozza:

const template = await bird.email.templates.create({
  slug: "welcome-email",
  category: "transactional",
  source: "html",
  languages: {
    en: {
      subject: "Welcome, {{ first_name }}",
      preview_text: "Your account is ready",
      html: "<!DOCTYPE html>\n<html>\n<body>\n<p>Hi {{ first_name }}, thanks for signing up.</p>\n</body>\n</html>\n",
    },
  },
});
console.log(template.id, template.draft_version_id);

Per modificare una lingua in seguito, salvala di nuovo con bird email templates versions languages set o un PUT sullo stesso percorso della lingua. Il corpo è piatto: subject, che è obbligatorio, più preview_text, html e text. Un campo che ometti viene cancellato. Aggiungi il revision che hai letto per ultimo per rifiutare il salvataggio se qualcun altro ha modificato quella lingua nel frattempo.

Il layout dell'editor visuale della dashboard è uno dei campi cancellati in questo modo, perché API, gli SDK e CLI non possono inviarlo. Salvare una lingua creata nell'editor visuale ne conserva l'HTML ma rimuove il layout, quindi la dashboard riapre quella lingua nell'editor di codice.

I passaggi seguenti usano TEMPLATE_ID e DRAFT_VERSION_ID per id e draft_version_id restituiti dalla chiamata di creazione. Leggete la lingua della bozza per ottenere l'HTML esattamente com'è memorizzato:

const language = await bird.email.templates.versions.languages.get(
  "TEMPLATE_ID",
  "DRAFT_VERSION_ID",
  "en",
);
console.log(language.content?.html);

jq -j scrive la stringa senza aggiungere un a capo finale, quindi il file contiene gli stessi byte memorizzati da API.

Inviate la bozza prima con validate_only. Esegue gli stessi controlli di un invio reale su tutte le lingue e riporta i problemi trovati in un'unica risposta, senza pubblicare nulla. Poi inviate senza validate_only per pubblicare la versione successiva, che i send useranno:

const templateId = "TEMPLATE_ID";
const draftVersionId = "DRAFT_VERSION_ID";
const check = await bird.email.templates.versions.submit(templateId, draftVersionId, {
  validate_only: true,
});
for (const problem of check.errors) {
  console.log(problem.language, problem.field, problem.message);
}
if (check.valid) {
  const result = await bird.email.templates.versions.submit(templateId, draftVersionId);
  console.log(result.version?.version_number);
}

Il corpo dell'invio accetta validate_only e expected_revision. Passate la revision del template come expected_revision per rifiutare la pubblicazione se la bozza è cambiata dall'ultima lettura.

Elencate i template del vostro spazio di lavoro per trovare lo slug indicato da un send:

for await (const tpl of bird.email.templates.list({ scope: "workspace" })) {
  console.log(tpl.slug, tpl.name);
}

Inviate il template pubblicato tramite slug, con un valore in template.parameters per ogni parametro che utilizza, qui first_name:

const msg = await bird.email.send({
  from: { email: "onboarding@messagebird.dev", name: "Bird" },
  to: ["delivered@messagebird.dev"],
  category: "transactional",
  template: {
    slug: "welcome-email",
    parameters: { first_name: "Jane" },
  },
});
console.log(msg.id, msg.status);

Passaggi successivi

  • Invio di email: il payload completo di invio e come i send con template si inseriscono in esso
  • Categorie: scegliere marketing o transactional per ogni invio
  • bird email templates: gestire i template dal terminale
  • Riferimento API: schemi completi di richiesta e risposta per tutte le diciotto operazioni sui template
  • SDK: i metodi tipizzati email.templates in TypeScript, Python, PHP e Go
  • Server MCP: consentire a un agente di creare e pubblicare template
  • Come creare un template email: un video che ne costruisce uno nella dashboard e poi ne fa costruire un altro a un agente

Continua con la documentazione, le guide e gli esempi per questo argomento.