gigafibre-fsm/scripts/campaigns/templates/gift-email-fr-native.html
louispaulb 0fd1e9f6b5 feat(campaigns/templates): Gemini-powered HTML→native converter
Scales the native-block migration from "one template per manual spec"
to "any compiled .html template, one CLI command, ~5 seconds, ~$0.001
per template" via Gemini Flash semantic interpretation.

Pipeline (ai-convert-to-native.js):
  1. Read existing compiled .html
  2. Send inner body to Gemini Flash with a tight JSON schema
     (block.type ∈ text/image/button/divider/html, plus type-specific
     fields like fontSize/color/padding/href).
  3. AI returns { preheader, ariaLabel, blocks: [...] }
  4. Deterministic emit of a templates-spec/<name>-native.js file —
     no AI-touched markup goes into the final compiled output.
  5. Validation: every {{var}} in source MUST survive into the spec;
     warn loudly if any are dropped (the AI occasionally omits minor
     placeholders like {{year}} in the copyright line).

Why deterministic emit matters:
  Gemini understands SEMANTICS reliably ("this paragraph is the
  greeting, this div is the CTA, this span is a chip") but
  hallucinates DETAILS when generating final HTML. Splitting the
  responsibilities means the AI only outputs structured JSON
  describing the layout, and build-native-template.js produces the
  bytes shipped to recipients.

First conversion: gift-email-fr → gift-email-fr-native
  - 15 blocks identified by Gemini in 3006 tokens (Flash, ~5s).
  - 4 row groups: view-in-browser, white card (intro/chips/CTA/
    footer copy), contact info, dark footer band.
  - 7 text + 1 image + 1 button + 6 html blocks (chips, multi-logo
    strip, brand-logo card, expiry section stay as raw HTML —
    correct, those have no native equivalent).
  - HTML payload: 19,664 bytes vs original 39,913 bytes — **-51%**.
  - One AI omission caught by the new sanity check: {{year}} was
    stripped from the © line in the dark footer. Hand-patched in the
    generated spec. Re-running with stricter prompt should reduce
    that occurrence rate.

Hub preview endpoint now defaults vars.year to current year (matches
the test-send endpoint that already did this), so the sample render
shows "© 2026 TARGO Communications" instead of "©  TARGO ...".

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-01 18:29:15 -04:00

182 lines
19 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
<head>
<!--[if gte mso 9]><xml><o:OfficeDocumentSettings><o:AllowPNG/><o:PixelsPerInch>96</o:PixelsPerInch></o:OfficeDocumentSettings></xml><![endif]-->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="x-apple-disable-message-reformatting">
<!--[if !mso]><!--><meta http-equiv="X-UA-Compatible" content="IE=edge"><!--<![endif]-->
<style type="text/css">
@media only screen and (min-width: 620px) { .u-row { width: 600px !important; } .u-row .u-col { vertical-align: top; } .u-row .u-col-100 { width: 600px !important; } }
@media only screen and (max-width: 620px) {
.u-row-container { max-width: 100% !important; padding-left: 0 !important; padding-right: 0 !important; }
.u-row { width: 100% !important; }
.u-row .u-col { display: block !important; width: 100% !important; min-width: 320px !important; max-width: 100% !important; }
.u-row .u-col > div { margin: 0 auto; }
}
body{margin:0;padding:0}table,td,tr{border-collapse:collapse;vertical-align:top}*{line-height:inherit}a[x-apple-data-detectors=true]{color:inherit!important;text-decoration:none!important}
table, td { color: #1B2E24; } #u_body a { color: #00C853; text-decoration: underline; }
</style>
<!--[if !mso]><!--><link href="https://fonts.googleapis.com/css?family=Plus+Jakarta+Sans:400,500,600,700" rel="stylesheet" type="text/css"><!--<![endif]-->
</head>
<body class="clean-body u_body" style="margin:0;padding:0;-webkit-text-size-adjust:100%;background-color:#F5FAF7;color:#1B2E24">
<!--[if IE]><div class="ie-container"><![endif]--><!--[if mso]><div class="mso-container"><![endif]-->
<table role="presentation" id="u_body" style="border-collapse:collapse;table-layout:fixed;border-spacing:0;mso-table-lspace:0pt;mso-table-rspace:0pt;vertical-align:top;min-width:320px;Margin:0 auto;background-color:#F5FAF7;width:100%" cellpadding="0" cellspacing="0">
<tbody>
<tr><td style="display:none !important;visibility:hidden;mso-hide:all;font-size:1px;color:#fff;line-height:1px;max-height:0;max-width:0;opacity:0;overflow:hidden;">Comme toi, on aime les connexions stables et les relations durables.</td></tr>
<tr style="vertical-align:top"><td style="word-break:break-word;border-collapse:collapse !important;vertical-align:top">
<!--[if (mso)|(IE)]><table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td align="center" style="background-color:#F5FAF7;" bgcolor="#F5FAF7"><table role="presentation" cellpadding="0" cellspacing="0" border="0" width="600" align="center"><tr><td><![endif]-->
<div aria-label="Une offre exclusive de TARGO" aria-roledescription="email" role="article" lang="und" dir="auto" style="word-spacing:normal;background-color:#F5FAF7;">
<div class="u-row-container" style="padding:0px;background-color:#F5FAF7;">
<div class="u-row" style="border:1px solid #e5e7eb;background:#F5FAF7;background-color:#F5FAF7;margin:0 auto;max-width:600px">
<div style="border-collapse:collapse;display:table;width:100%;height:100%;">
<!--[if (mso)|(IE)]><table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding:0px;background-color:#F5FAF7;"><table role="presentation" cellpadding="0" cellspacing="0" border="0" width="600" align="center" style="border-collapse:collapse;background:#F5FAF7;"><tr><td style="border:1px solid #e5e7eb;background-color:#F5FAF7;margin:0 auto;max-width:600px"><![endif]-->
<div class="u-col u-col-100" style="max-width:320px;min-width:600px;display:table-cell;vertical-align:top;">
<div style="height:100%;width:100% !important;">
<!--[if (!mso)&(!IE)]><!--><div style="box-sizing:border-box;height:100%;padding:0px;"><!--<![endif]-->
<table role="presentation" cellpadding="0" cellspacing="0" width="100%" border="0">
<tbody><tr><td style="padding:8px 36px 4px;">
{{#view_url}}<div style="margin:0px auto;max-width:600px;padding:8px 36px 4px;text-align:center;"><a href="{{view_url}}" style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:11px;color:#94a3b8;text-decoration:underline;">Affichage incorrect ? Voir dans le navigateur</a></div>{{/view_url}}
</td></tr></tbody>
</table>
<!--[if (!mso)&(!IE)]><!--></div><!--<![endif]-->
</div>
</div>
<!--[if (mso)|(IE)]></td></tr></table></td></tr></table><![endif]-->
</div>
</div>
</div>
<div class="u-row-container" style="padding:0px;background-color:#ffffff;">
<div class="u-row" style="border:1px solid #e5e7eb;background:#ffffff;background-color:#ffffff;margin:0 auto;max-width:600px">
<div style="border-collapse:collapse;display:table;width:100%;height:100%;">
<!--[if (mso)|(IE)]><table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding:0px;background-color:#ffffff;"><table role="presentation" cellpadding="0" cellspacing="0" border="0" width="600" align="center" style="border-collapse:collapse;background:#ffffff;"><tr><td style="border:1px solid #e5e7eb;background-color:#ffffff;margin:0 auto;max-width:600px"><![endif]-->
<div class="u-col u-col-100" style="max-width:320px;min-width:600px;display:table-cell;vertical-align:top;">
<div style="height:100%;width:100% !important;">
<!--[if (!mso)&(!IE)]><!--><div style="box-sizing:border-box;height:100%;padding:0px;"><!--<![endif]-->
<table role="presentation" cellpadding="0" cellspacing="0" width="100%" border="0">
<tbody><tr><td style="padding:28px 36px 22px;text-align:left;" align="left">
<img alt="TARGO" src="https://xqy3m.mjt.lu/img2/xqy3m/eed4d18c-8065-4c5f-b47c-58af63171cd0/content" width="140" style="display:block;border:0;height:auto;outline:none;text-decoration:none;width:140px;max-width:100%;" />
</td></tr></tbody>
</table>
<table style="font-family:'Plus Jakarta Sans', sans-serif;" role="presentation" cellpadding="0" cellspacing="0" width="100%" border="0">
<tbody><tr><td style="overflow-wrap:break-word;word-break:break-word;padding:10px 25px 14px;font-family:'Plus Jakarta Sans', sans-serif;" align="left">
<div class="u_content_text" style="font-size:16px;font-weight:400;color:#374151;text-align:left;line-height:150%;">Bonjour {{firstname}},</div>
</td></tr></tbody>
</table>
<table style="font-family:'Plus Jakarta Sans', sans-serif;" role="presentation" cellpadding="0" cellspacing="0" width="100%" border="0">
<tbody><tr><td style="overflow-wrap:break-word;word-break:break-word;padding:10px 25px 14px;font-family:'Plus Jakarta Sans', sans-serif;" align="justify">
<div class="u_content_text" style="font-size:16px;font-weight:400;color:#374151;text-align:justify;line-height:150%;">Avec l'arrivée de l'été, voici un <strong>cadeau pour toi, disponible pour un temps limité</strong>.<br><br>On veut te remercier pour ta loyauté envers l'achat local.<br />Comme toi, on aime les connexions stables et les relations durables.</div>
</td></tr></tbody>
</table>
<table style="font-family:'Plus Jakarta Sans', sans-serif;" role="presentation" cellpadding="0" cellspacing="0" width="100%" border="0">
<tbody><tr><td style="overflow-wrap:break-word;word-break:break-word;padding:10px 25px 0px;font-family:'Plus Jakarta Sans', sans-serif;" align="justify">
<div class="u_content_text" style="font-size:16px;font-weight:400;color:#374151;text-align:justify;line-height:150%;">Grâce à la confiance de nos clients, on offre maintenant les forfaits à <strong>la plus haute vitesse dans le secteur</strong>, jusqu'à <strong>3.5&nbsp;Gbit/s</strong>.<br />Que tu souhaites plus de vitesse, battre une autre offre ou faire optimiser des équipements, n'hésite pas. On est juste à côté et on aime aider.</div>
</td></tr></tbody>
</table>
<table role="presentation" cellpadding="0" cellspacing="0" width="100%" border="0">
<tbody><tr><td style="padding:18px 36px 8px;">
<div style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:left;color:#1B2E24;"><span style="display:inline-block;background:#E6F9EE;color:#00C853;font-size:13px;font-weight:700;padding:5px 12px;border-radius:6px;">✅ Option 1</span></div>
</td></tr></tbody>
</table>
<table role="presentation" cellpadding="0" cellspacing="0" width="100%" border="0">
<tbody><tr><td style="padding:18px 36px 22px;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="" width="100%"><tbody><tr><td align="left" style="font-size:0px;padding:0 0 8px;word-break:break-word;"><div style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;font-weight:700;line-height:1.5;text-align:left;color:#1B2E24;">🎁 {{amount}} chez des centaines de marques<br><br><span style="display:inline-block;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/4b0b2a4a-5f99-416c-8873-8d3e4389b6f7/content" width="32" alt="Tim Hortons" style="width:32px;max-width:32px;height:auto;display:inline-block;border:0;margin-right:6px;vertical-align:middle;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/14df433d-583c-4602-a403-d47ee84966a6/content" width="32" alt="Walmart" style="width:32px;max-width:32px;height:auto;display:inline-block;border:0;margin-right:6px;vertical-align:middle;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/b8d3db5a-d39e-43ce-a84a-2f5dddbf0192/content" width="32" alt="Home Depot" style="width:32px;max-width:32px;height:auto;display:inline-block;border:0;margin-right:6px;vertical-align:middle;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/9c9dfa18-2a3a-414a-b5ad-16d490c961b5/content" width="32" alt="IGA" style="width:32px;max-width:32px;height:auto;display:inline-block;border:0;margin-right:6px;vertical-align:middle;"><img src="https://xqy3m.mjt.lu/img2/xqy3m/a1e5f032-a192-4499-97ba-53b939712fa9/content" width="32" alt="Home Hardware" style="width:32px;max-width:32px;height:auto;display:inline-block;border:0;margin-right:6px;vertical-align:middle;"><span style="font-size:13px;color:#64748B;vertical-align:middle;font-weight:400;">et plus</span></span></div></td></tr><tr><td align="left" style="font-size:0px;padding:0 0 4px;word-break:break-word;"><div style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:14px;line-height:1.5;text-align:left;color:#64748B;">⚡ Disponible instantanément sur Giftbit en cliquant sur ton montant</div></td></tr><tr><td align="left" style="font-size:0px;padding:0;word-break:break-word;"><div style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:14px;line-height:1.5;text-align:left;color:#64748B;">🤝 Condition : Maintenir l'abonnement {{commitment_months}} mois ou +</div></td></tr></tbody></table>
</td></tr></tbody>
</table>
<table role="presentation" cellpadding="0" cellspacing="0" width="100%" border="0" style="border-collapse:separate;line-height:100%;">
<tbody><tr><td style="padding:10px 25px;text-align:center;" align="center">
<a href="{{gift_url}}" target="_blank" class="u_content_button" style="display:inline-block;background:#00C853;color:#ffffff;font-family:'Space Grotesk', Helvetica, Arial, sans-serif;font-size:32px;font-weight:700;line-height:120%;text-decoration:none;padding:30px 24px;border-radius:12px;">🎁&nbsp;&nbsp;{{amount}}</a>
</td></tr></tbody>
</table>
<table role="presentation" cellpadding="0" cellspacing="0" width="100%" border="0">
<tbody><tr><td style="padding:0 36px 4px;">
{{#expires_at_date}}
<div style="background:#ffffff;background-color:#ffffff;margin:0px auto;max-width:600px;">
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#ffffff;background-color:#ffffff;width:100%;">
<tbody><tr><td style="border-left:1px solid #e5e7eb;border-right:1px solid #e5e7eb;direction:ltr;font-size:0px;padding:0 36px 4px;text-align:center;">
<div style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:13px;line-height:1.4;text-align:center;color:#64748B;">
⏰ Cadeau valide jusqu'au <strong style="color:#1B2E24;">{{expires_at_date}}</strong>
</div>
</td></tr></tbody>
</table>
</div>
{{/expires_at_date}}
</td></tr></tbody>
</table>
<table style="font-family:'Plus Jakarta Sans', sans-serif;" role="presentation" cellpadding="0" cellspacing="0" width="100%" border="0">
<tbody><tr><td style="overflow-wrap:break-word;word-break:break-word;padding:10px 36px 22px;font-family:'Plus Jakarta Sans', sans-serif;" align="left">
<div class="u_content_text" style="font-size:14px;font-weight:400;color:#6b7280;text-align:left;line-height:150%;">🪂 Annulation avant {{commitment_months}} mois : seulement à rembourser au prorata des mois restants.</div>
</td></tr></tbody>
</table>
<table role="presentation" cellpadding="0" cellspacing="0" width="100%" border="0">
<tbody><tr><td style="padding:18px 36px 6px;">
<div style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;text-align:left;color:#1B2E24;"><span style="display:inline-block;background:#F5FAF7;color:#6b7280;font-size:13px;font-weight:700;padding:5px 12px;border-radius:6px;">⏭️ Option 2</span></div>
</td></tr></tbody>
</table>
<table style="font-family:'Plus Jakarta Sans', sans-serif;" role="presentation" cellpadding="0" cellspacing="0" width="100%" border="0">
<tbody><tr><td style="overflow-wrap:break-word;word-break:break-word;padding:6px 36px 22px;font-family:'Plus Jakarta Sans', sans-serif;" align="left">
<div class="u_content_text" style="font-size:15px;font-weight:400;color:#4b5563;text-align:left;line-height:155%;">Ne rien faire. Aucun changement à ton abonnement actuel.</div>
</td></tr></tbody>
</table>
<table style="font-family:'Plus Jakarta Sans', sans-serif;" role="presentation" cellpadding="0" cellspacing="0" width="100%" border="0">
<tbody><tr><td style="overflow-wrap:break-word;word-break:break-word;padding:18px 36px 28px;font-family:'Plus Jakarta Sans', sans-serif;" align="left">
<div class="u_content_text" style="font-size:15px;font-weight:400;color:#1B2E24;text-align:left;line-height:150%;">🤝 Merci de faire rouler l'économie de notre région avec nous !<br><br>L'équipe TARGO</div>
</td></tr></tbody>
</table>
<!--[if (!mso)&(!IE)]><!--></div><!--<![endif]-->
</div>
</div>
<!--[if (mso)|(IE)]></td></tr></table></td></tr></table><![endif]-->
</div>
</div>
</div>
<div class="u-row-container" style="padding:0px;background-color:#F5FAF7;">
<div class="u-row" style="border:1px solid #e5e7eb;background:#F5FAF7;background-color:#F5FAF7;margin:0 auto;max-width:600px">
<div style="border-collapse:collapse;display:table;width:100%;height:100%;">
<!--[if (mso)|(IE)]><table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding:0px;background-color:#F5FAF7;"><table role="presentation" cellpadding="0" cellspacing="0" border="0" width="600" align="center" style="border-collapse:collapse;background:#F5FAF7;"><tr><td style="border:1px solid #e5e7eb;background-color:#F5FAF7;margin:0 auto;max-width:600px"><![endif]-->
<div class="u-col u-col-100" style="max-width:320px;min-width:600px;display:table-cell;vertical-align:top;">
<div style="height:100%;width:100% !important;">
<!--[if (!mso)&(!IE)]><!--><div style="box-sizing:border-box;height:100%;padding:0px;"><!--<![endif]-->
<table style="font-family:'Plus Jakarta Sans', sans-serif;" role="presentation" cellpadding="0" cellspacing="0" width="100%" border="0">
<tbody><tr><td style="overflow-wrap:break-word;word-break:break-word;padding:18px 36px 8px;font-family:'Plus Jakarta Sans', sans-serif;" align="center">
<div class="u_content_text" style="font-size:12px;font-weight:400;color:#64748B;text-align:center;line-height:155%;">Tu reçois ce courriel parce que tu es client(e) TARGO à <strong style="color:#1B2E24;">{{description}}</strong>.<br />Une question ? N'hésite pas à nous écrire à <a href="mailto:support@targo.ca" style="color:#00C853;text-decoration:none;">support@targo.ca</a> ou nous appeler au <a href="tel:5144480773" style="color:#00C853;text-decoration:none;">514-448-0773</a>.</div>
</td></tr></tbody>
</table>
<!--[if (!mso)&(!IE)]><!--></div><!--<![endif]-->
</div>
</div>
<!--[if (mso)|(IE)]></td></tr></table></td></tr></table><![endif]-->
</div>
</div>
</div>
<div class="u-row-container" style="padding:0px;background-color:#1C1E26;">
<div class="u-row" style="border:1px solid #e5e7eb;background:#1C1E26;background-color:#1C1E26;margin:0 auto;max-width:600px">
<div style="border-collapse:collapse;display:table;width:100%;height:100%;">
<!--[if (mso)|(IE)]><table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding:0px;background-color:#1C1E26;"><table role="presentation" cellpadding="0" cellspacing="0" border="0" width="600" align="center" style="border-collapse:collapse;background:#1C1E26;"><tr><td style="border:1px solid #e5e7eb;background-color:#1C1E26;margin:0 auto;max-width:600px"><![endif]-->
<div class="u-col u-col-100" style="max-width:320px;min-width:600px;display:table-cell;vertical-align:top;">
<div style="height:100%;width:100% !important;">
<!--[if (!mso)&(!IE)]><!--><div style="box-sizing:border-box;height:100%;padding:0px;"><!--<![endif]-->
<table role="presentation" cellpadding="0" cellspacing="0" width="100%" border="0">
<tbody><tr><td style="padding:26px 36px 22px;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-collapse:collapse;border-spacing:0px;"><tbody><tr><td style="width:120px;"><img alt="TARGO" src="https://xqy3m.mjt.lu/img2/xqy3m/eed4d18c-8065-4c5f-b47c-58af63171cd0/content" style="border:0;display:block;outline:none;text-decoration:none;height:auto;width:100%;font-size:13px;" width="120" height="auto"/></td></tr></tbody></table><td align="center" style="font-size:0px;padding:18px 0 0;word-break:break-word;"><div style="font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:11px;line-height:1.55;text-align:center;color:rgba(255,255,255,0.55);"><a href="https://www.targo.ca" style="color:rgba(255,255,255,0.7);text-decoration:none;">www.targo.ca</a>&nbsp;·&nbsp; 1867 ch. de la rivière, Ste-Clotilde, QC<br />© {{year}} TARGO Communications · Tous droits réservés.</div></td>
</td></tr></tbody>
</table>
<!--[if (!mso)&(!IE)]><!--></div><!--<![endif]-->
</div>
</div>
<!--[if (mso)|(IE)]></td></tr></table></td></tr></table><![endif]-->
</div>
</div>
</div>
</div>
<!--[if (mso)|(IE)]></td></tr></table></td></tr></table><![endif]-->
</td></tr>
</tbody>
</table>
<!--[if mso]></div><![endif]--><!--[if IE]></div><![endif]-->
</body></html>