# Personalized images in email: one card per recipient

> Put each recipient's name, offer or ticket into an email image: signed image URLs stored in a contact field, or a batch rendered before the send.

Published 2026-11-04 · https://shareglint.com/en/use-cases/personalized-email-images

A **personalized email image** is a picture made for one recipient — their name on an event ticket, their discount code on a coupon, their certificate — placed in the email like any other image. With Shareglint you design the image once as a template, then give each contact an image URL with their values: a **signed URL** that renders the first time a mail client fetches it, or a file rendered beforehand in a **batch**. Either way the email itself only holds `<img src="…">` with that contact's URL, which your mailing tool fills in from a contact field.

## Why a contact field, not a merge tag in the URL

The obvious idea — put `*|FNAME|*` into the image address — does not work with signed URLs. A signed URL (`/i/{account}/{template}.png?name=Anna&s=…`) carries an HMAC of its path and every field value, so nobody can change the name in the link and render on your quota. Your mailing tool fills merge tags at send time but cannot compute an HMAC, so the signature would not match the filled-in values.

The fix is one step earlier: compute each contact's full URL in a script, upload it as a contact field (`CARD_URL`), and use that field in the template. Mailchimp, for example, turns every audience field into a merge tag such as `*|CARD_URL|*`, usable in links and image URLs ([Mailchimp merge tags](https://mailchimp.com/help/all-the-merge-tags-cheat-sheet/)); other tools have the same idea under another syntax.

```html
<img src="*|CARD_URL|*" width="600" height="315"
     alt="Your ticket for DevConf 2026, seat 14C" style="display:block;width:100%;max-width:600px;height:auto">
```

## Method 1: signed URLs, rendered on first fetch

A signed URL is computed locally from your account id and signing secret — no request to the API, no quota until someone fetches it:

```javascript
import { createHmac } from 'node:crypto';

// RFC 3986: encodeURIComponent leaves ! ' ( ) * alone.
const enc = (v) => encodeURIComponent(String(v))
  .replace(/[!'()*]/g, (c) => '%' + c.charCodeAt(0).toString(16).toUpperCase());

export function signedImageUrl(template, fields, ext = 'png') {
  const path = `/i/${process.env.ACCOUNT_ID}/${template}.${ext}`;
  const query = Object.keys(fields).sort()
    .map((name) => `${enc(name)}=${enc(fields[name])}`)
    .join('&');
  const s = createHmac('sha256', process.env.SIGNING_SECRET)
    .update(`${path}?${query}`).digest('hex').slice(0, 32);
  return `https://shareglint.com${path}?${query}&s=${s}`;
}

// One row per contact → CSV to import into your mailing tool.
for (const c of contacts) {
  const url = signedImageUrl('event-ticket', { title: 'DevConf 2026', admit: c.name, seat: c.seat }, 'jpg');
  console.log(`${c.email},${url}`);
}
```

The canonical string is the path, `?` and every parameter except `s`, sorted by name and RFC 3986-encoded; `s` is the first 32 hex characters of HMAC-SHA256 with your signing secret. The [docs](https://shareglint.com/en/docs#signed) describe it with examples in other languages; the account id is public, the signing secret is not.

What happens at send time: mail clients fetch the image soon after delivery, not when the email is opened. Gmail shows images automatically after scanning them, and senders cannot use image loading to learn about the reader's computer or location ([Google](https://support.google.com/mail/answer/145919)) — the request comes from Google, not from the reader, and Apple Mail with Mail Privacy Protection "privately downloads remote content in the background when you receive a message" ([Apple](https://support.apple.com/guide/mail/protect-email-privacy-mlhlp1205/mac)). So the first fetch — and the render — comes right after the send, for most recipients, whether they open the email or not. A render takes about a second; later fetches are redirects to the cached file.

## Method 2: render everything before the send

If you would rather have every file in hand before you press send — to check them, or because your list is large and you want the renders out of the way — use a batch:

```bash
curl -X POST "https://shareglint.com/v1/batches" \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "template": "event-ticket", "format": "jpeg", "csv_url": "https://example.com/attendees.csv" }'
```

Put the contact's email in an `id` column; each row's result comes back with that `id` and the image URL, so you can write the URLs back into the mailing tool as `CARD_URL`. Rows per batch by plan: Free 50, Starter 500, Pro 1,000, Scale 2,000, Business 5,000. A rendered image's URL stays valid for as long as we keep the file (365 days on paid plans, 30 on Free), which outlasts most campaigns — but an email opened after that would show a broken image, which a signed URL never does: it renders again.

## Make the image work in email

- **Format.** Use JPEG or PNG. WebP is not supported by Outlook for Windows and is converted by Gmail ([Can I email](https://www.caniemail.com/features/image-webp/)). A signed URL picks the format by its extension: `.jpg` for photos and gradients, `.png` for flat colours and sharp text.
- **Size.** Email bodies are usually around 600 px wide. A 1200×630 template displayed at `width="600"` is sharp on high-density screens. Raster files from signed URLs are twice the template size, so for a lighter file make a template at 600×315 and keep the same `width`.
- **Alt text.** Many clients block images until the reader allows them, and screen readers read the `alt`. Put the essential text — the seat, the code — in `alt` and in the email body too; never only in the image.
- **Dark mode.** Some clients change colours in dark mode. A design with its own solid background (not transparent) keeps its look; built-in templates take `theme` (`dark` or `light`) if you want a dark version.

## Cost

Each distinct image is one render; contacts with the same values share one file, and repeat fetches are free. With signed URLs, budget for nearly every recipient's image to be rendered, because the prefetching described above happens on delivery. For a 5,000-contact campaign that is about 5,000 renders: the Free plan's 100 a month is for testing, Starter is $9 for 2,000, Pro $29 for 10,000, and a one-off pack of 1,000 costs $8 ([pricing](https://shareglint.com/en/pricing)). The Free plan also adds a watermark, which you do not want in a customer email.

## What it does not do

- **No live content.** The same URL always returns the same image, and clients cache it: no countdowns that tick on each open, no prices that change after the send.
- **No open tracking.** Prefetching makes image requests a poor signal of opens anyway, and we do not report per-recipient fetches.
- **No sending.** We render images; your mailing tool sends the email.
- **No native integration with mailing tools.** Contact fields and CSV imports are the bridge; there is no Mailchimp or Kit app.

## Ideas that fit

- Event tickets with name, seat and a QR code image you generate.
- Coupons with each customer's code — the code also in the text, so it can be copied.
- Course certificates linked from the completion email, as a PNG preview and a [one-page PDF](https://shareglint.com/en/pdf-generation-api).
- "Your year in numbers" cards with three or four of the contact's own stats.

Templates for most of these are in the [gallery](https://shareglint.com/en/templates); your own HTML and CSS works as well, with a free preview before you save it.

## FAQ

### Can I put a merge tag straight into the image URL?

Not with a signed URL: the signature is computed over the final field values, and a mailing tool cannot compute an HMAC at send time. Compute each contact's signed URL in a script, store it in a contact field, and put that field's merge tag in the img src.

### When is the image rendered?

With a signed URL, the first time anyone fetches it — usually right after delivery, because Gmail fetches images through its proxy and Apple Mail with Mail Privacy Protection downloads remote content in the background when the message arrives. With a batch, before the send.

### How much does a personalized email image cost?

One render per distinct image. Contacts with identical values share one file, and fetching the same image again is free. With signed URLs, plan for most recipients' images to be rendered, since mail clients prefetch them whether or not the email is opened.

### Which image format should I use in email?

PNG or JPEG. WebP is not supported by Outlook for Windows and is converted by Gmail, so the signed URL should end in .png or .jpg.

### Can the image change on every open, like a live countdown?

No. A signed URL always returns the same image for the same values, and mail clients cache images, so a per-open countdown or live price is not possible this way.
