Car Image API

Müşteriler · Car Image API

Hiç bozulmayan imzalı URL'lerle e-postalara araç görselleri nasıl eklenir

Car Image API, her müşterinin ilk render'ını otomatik yenilenen imzalı bir URL ile gelen kutusuna ulaştırıyor: mekanizma, hesap ve bunu kendiniz yapmanız için gereken kod.

Sorun: Mart'ta da işe yaraması gereken bir görsel

Car Image API'deki her hesap, ilk render'ından yaklaşık bir saat sonra Jonathan'dan kısa bir not alır. Bu e-postaya konulacak en bariz şey render'ın kendisidir: kişinin az önce istediği 2024 Porsche 911 ya da 2006 Dodge Charger'ın ta kendisi; hem entegrasyonun çalıştığının kanıtı hem de küçük bir övünme vesilesi olarak.

E-posta, imzalı bir URL için olabilecek en kötü ortamdır. Bir sayfa her ziyarette yeniden oluşturulur; bir e-posta ise bir kez oluşturulur ve okuyucu ne zaman fırsat bulursa, bir gün, bir ay veya bir yıl sonra, çoğu zaman Gmail’in görsel proxy’si üzerinden açılır. API’nin halihazırda sunduğu imzalı teslim URL’lerinin maksimum TTL’si yedi gündü; bu, bir tarayıcı için doğru üst sınırdır ancak gelen kutusunda ikinci haftaya varmadan bozuk bir görseli garanti eder. PNG’yi ek olarak göndermek veya satır içine gömmek ise her iletiyi şişirir.

İstediğimiz şey, barındırılan bir görsel gibi davranan, e-postayı açabilecek biri olduğu sürece çalışmaya devam eden ve yine de hesaba gerçekten sunduğu şey için adil ücret yansıtan bir URL'ydi.

Çözüm: otomatik yenilenen imzalı URL'ler

POST /api/v1/image-urls uç noktasına tek bir bayrak ekledik: renew: true. Yenilenebilir bir URL tam olarak diğerleri gibi oluşturulur, görselini ayın bir araç görseli olarak sayar ve ttl_seconds boyunca geçerlidir. Fark, TTL dolduktan sonra olanlardadır. 403 yerine, her yeni ttl_seconds penceresindeki ilk yükleme URL'yi yeniler ve görseli sunar; bir yenileme görseli denk geldiği ayda bir kez sayar, o ay zaten sayılmışsa başka bir şey saymaz. O penceredeki sonraki her yükleme, ilk pencerede olduğu gibi herkese açık olarak önbelleğe alınabilir. Bu durum, en fazla bir yıl sonrasına kadar, renews_until zamanına dek sürer.

Bu tasarımdan üç özellik ortaya çıktı ve her biri e-posta için önemliydi:

  • Yeniden gönderilecek ya da yeniden oluşturulacak bir şey yok. E-postadaki URL sonsuza dek aynı kalır. Kayıtlı bağlantıları yeniden yazan bir cron işi de, yeni görselle gönderilen ikinci bir e-posta da yok.
  • Süreyi değil, açılmaları sayın. Kimsenin açmadığı bir pencere hiçbir şey saymaz. Bir kişinin tek bir günde okuduğu bir e-posta, oluşturulduğu tek araç görselidir; bir yıl boyunca her hafta açılan bir e-posta ise o görseli açıldığı her ayda bir kez, en fazla on iki kez sayar.
  • İdempotent sayım. Her zaman aralığı, URL ve zaman aralığı başına benzersiz olan renew:<url id>:<window> anahtarıyla bir kez kaydedilir. Bir haftada elli açılma ya da ilk açılışta yarışan iki e-posta proxy'si tek sayılır.

Yaşam döngüsü e-postaları bu URL'leri, herkese açık uç noktanın kullandığı kod yolunun aynısı üzerinden platform token'ları olarak oluşturur. Bu token'lar hiçbir API anahtarına bağlı değildir ve bize ait oldukları için asla faturalandırılmaz. Ancak aynı GET /api/v1/delivery/{token} rotasıyla, aynı yedi günlük sürelerle ve aynı önbelleğe alma ayarlarıyla sunulurlar. İlk render e-postasındaki görsel, ürünün kendi kendini tanıtmasıdır.

Müşterinin ilk renderı için yenilenebilir bir URL üretin
curl -X POST https://carimage.dev/api/v1/image-urls \
  -H "Authorization: Bearer $CAR_IMAGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"images":[{"make":"porsche","model":"911","year":2024,"view":"front-3-4","color":"red","width":480}],"ttl_seconds":604800,"renew":true}'
201 Created
{
  "data": [
    {
      "id": "3f0c2a7e-1c1e-4c2a-9c39-4f1f0a4b2d10",
      "url": "https://carimage.dev/api/v1/delivery/eyJhbGciOi…",
      "expires_at": "2026-09-21T09:00:00.000Z",
      "max_uses": 0,
      "renews_until": "2027-09-14T09:00:00.000Z",
      "vehicle": {
        "make": "porsche",
        "model": "911",
        "year": 2024,
        "view": "front-3-4",
        "color": "red",
        "width": 480,
        "format": "png"
      }
    }
  ],
  "billing": {
    "charged_on": "creation",
    "credits_charged": 1,
    "credits_remaining": 4869,
    "credits_per_url": 1,
    "renewal": {
      "window_seconds": 604800,
      "credits_per_window": 1,
      "until": "2027-09-14T09:00:00.000Z"
    }
  },
  "request_id": "req_01j9x…"
}

E-postanın kendisi

Şablon, satır içi stillerle React Email kullanır; çünkü e-posta istemcileri stil sayfalarını kaldırır. Render, yumuşak bir arka plan üzerindeki kenarlıklı bir tablo hücresinde yer alır; retina ekranlarda net kalması için 480 piksel olarak istenir ve 240 piksel olarak gösterilir; üstünde bir etiket, altında iki satır açıklama bulunur. Şeffaf PNG ürünün asıl amacıdır, bu yüzden onu koruyoruz; alfa kanalını siyaha boyayan eski Outlook sürümlerinde ise düz renkli bir hücre arka planı üzerinde format: "jpg" render yedek çözümdür.

Düz HTML olarak kart
<!-- inline styles only: mail clients strip stylesheets -->
<table role="presentation" width="100%" cellpadding="0" cellspacing="0">
  <tr>
    <td align="center" style="padding:24px;background:#fafaf9;border:1px solid #e7e5e4;border-radius:16px;">
      <img
        src="https://carimage.dev/api/v1/delivery/eyJhbGciOi…"
        alt="2024 Porsche 911, red, front three-quarter view"
        width="240" height="240"
        style="display:block;margin:0 auto;max-width:100%;height:auto;"
      />
      <p style="margin:14px 0 2px;font:700 18px/26px -apple-system,Segoe UI,Roboto,sans-serif;color:#1c1917;">2024 Porsche 911</p>
      <p style="margin:0;font:13px/20px ui-monospace,Menlo,monospace;color:#78716c;">Front three-quarter · Red</p>
    </td>
  </tr>
</table>

Mesajdaki diğer her şey metindir: URL'nin ne olduğu, neden çalışmaya devam ettiği, kendi araçları için bir URL oluşturmak üzere gönderilecek POST isteğinin tam hâli ve bu sayfaya bir bağlantı. E-postada bir abonelikten çıkma bağlantısı ve List-Unsubscribe başlıkları bulunur; her ürün bağlantısı etiketlenir, böylece edinim raporunda okuduğunuz bu hikâyenin birini geri getirip getirmediğini görebiliriz.

Üç adımda kendiniz yapın

  1. E-postayı oluştururken sunucu tarafında üretin. Araç başına bir çağrı ya da özet e-posta için çağrı başına elliye kadar. url ve renews_until değerlerini mesajla birlikte saklayın.
  2. URL'yi genişlik, yükseklik ve alt metinle birlikte bir <img> içine yerleştirin. Alt metin "araba" değil, aracın adını vermelidir ("2024 Porsche 911, kırmızı, ön üç çeyrek görünüm").
  3. Hesabınızda yeterli kota bulundurun. Bir yenileme, görseli denk geldiği ayda bir kez sayar; planın araç görselleri tükenmişse kota ayın 1'inde sıfırlanana kadar 402 yanıtı verir, bu yüzden planı sunduğunuz görsellere göre boyutlandırın.
TypeScript SDK ile
import { CarImageClient } from "@meterapp/car-image-sdk";

const client = new CarImageClient({ apiKey: process.env.CAR_IMAGE_API_KEY });

// One call per email: the vehicle the person rendered, at 2x the display width.
const { data } = await client.createImageUrls(
  [{ make: "porsche", model: "911", year: 2024, view: "front-3-4", color: "red", width: 480 }],
  { ttlSeconds: 604_800, renew: true, renewDays: 365 }
);
const src = data[0].url; // drop into <img src>, store data[0].renews_until next to it

Tüm parametre referansı, önbellek başlıkları ve hata kodları imzalı URL belgelerinde yer alır. Eklentiyle birlikte gelen ajan becerisi de aynı kuralları bilir; böylece "bu aracı bültene ekle" denen bir asistan, şablona anahtar yapıştırmak yerine yenilenebilir bir URL oluşturur.

Sıkça sorulan sorular

Görsel neden ek olarak eklenmiyor veya base64 ile satır içine gömülmüyor?
Ekler ve base64 her mesajı şişirir. İmzalı bir URL yalnızca birkaç yüz bayttır ve barındırılan diğer görseller gibi e-posta istemcisinin görsel proxy'si üzerinden yüklenir.
Otomatik yenilenen bir URL'nin maliyeti nedir?
Oluşturulduğunda ayın bir araç görseli; ardından renews_until tarihine kadar, bir yenileme penceresinin gerçekten açıldığı sonraki her ayda aynı görsel bir kez sayılır; e-postayı kimsenin açmadığı bir ayda hiçbir şey sayılmaz. Ayda $49 olan Pro, ayda 2.500 araç görseli içerir.
Ayın araç görselleri tükendiğinde ne olur?
Yükleme 402 döndürür ve aylık kota sıfırlanana ya da plan yükseltilene kadar görsel bozuk görünür; URL'nin kendisi geçerliliğini korur ve bir sonraki yüklemede yeniden çalışır. Bu ay zaten sayılmış bir görsel sunulmaya devam eder.
Bu yöntem Gmail, Outlook ve Apple Mail'de çalışıyor mu?
Evet. Teslim uç noktası; Cache-Control, ETag ve CORS başlıkları içeren, herkese açık sade bir GET isteğidir ve görsel proxy'lerinin beklediği de tam olarak budur. PNG saydamlığı tüm güncel istemcilerde doğru görüntülenir; çok eski Outlook sürümleri için düz arka planlı jpg biçimini isteyin.
Bir URL iptal edilebilir mi?
URL'yi üreten API anahtarını iptal ettiğinizde, o anahtardan üretilen her URL bir sonraki yüklemede, yenilemeler dahil, 403 döndürür. Paylaşılan önbellekler bundan sonra en fazla bir saat daha sunmaya devam eder.