Email embed

Embed a finished render in an HTML email as a clickable GIF thumbnail.

The thumbnail is an animated GIF of the recipient's own video, so the personalization is visible in the inbox before anyone clicks. The embed is one <a> around one <img>, with no stylesheet and no external assets beyond the GIF.

The two URLs

On the POST /renders path the terminal webhook carries both. outputUrl is always an Outvo play link, and the thumbnail is that same URL plus /thumb.gif, a durable proxy that re-signs itself on every request so it keeps loading in mail sent weeks ago.

javascript
// render.completed
// { "data": { "renderId": "rnd_abc123", "outputUrl": "https://share.outvo.io/v/abc123" } }

const videoUrl = payload.data.outputUrl;
const gifUrl = videoUrl + '/thumb.gif';
Do not send the thumbnailUrl from GET /renders/:id. That is the raw signed storage URL: it expires, and mail already in an inbox starts showing a broken image. Its one use is a null check, since null means the render produced no thumbnail at all.

The markup

html
<p style="margin: 0 0 12px;">I recorded a video just for you. Check it out:</p>

<a href="VIDEO_URL" target="_blank" rel="noopener" style="display: block; margin: 8px 0 24px; text-decoration: none;">
  <img src="GIF_URL" width="480" alt="Watch your video, Sarah" style="display: block; width: 100%; max-width: 480px; height: auto; margin: 0; border: 0; border-radius: 12px;">
</a>

<p style="margin: 0 0 12px;"><a href="VIDEO_URL">VIDEO_URL</a></p>

What to watch

  • The play button is painted into every frame of the GIF at render time. Do not overlay your own, or the email shows two buttons.
  • Keep the width attribute next to the CSS and keep height: auto. Outlook reserves layout from the attribute, and mobile-mode recordings are portrait, so a fixed height distorts them.
  • Keep the plain link under the image. Outlook desktop shows only the GIF's first frame, and enterprise inboxes still block images by default.
  • No thumbnail means no <img>. Fall back to the text-only body rather than emitting <img src="">.
  • The GIF is gated by the same retention window as the video, so it stops resolving when the video does.

On the campaign path the same two values arrive ready-made: as videoLink and videoThumbnail in the preset=sequencer export, and as outputUrl and thumbnailUrl on the recipient.rendered webhook and GET /recipients/:id.