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>
This commit is contained in:
louispaulb 2026-06-01 18:29:15 -04:00
parent 2919fa86af
commit 0fd1e9f6b5
7 changed files with 1952 additions and 0 deletions

View File

@ -0,0 +1,182 @@
<!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>

View File

@ -0,0 +1,665 @@
{
"counters": {
"u_row": 4,
"u_column": 4,
"u_content_text": 7,
"u_content_image": 1,
"u_content_button": 1,
"u_content_divider": 0,
"u_content_html": 6
},
"body": {
"id": "u_body",
"rows": [
{
"id": "u_row_1",
"cells": [
1
],
"columns": [
{
"id": "u_column_1",
"contents": [
{
"id": "u_content_html_1",
"type": "html",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "8px 36px 4px",
"anchor": "",
"_meta": {
"htmlID": "u_content_html_1",
"htmlClassNames": "u_content_html"
},
"html": "{{#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}}"
}
}
],
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"_meta": {
"htmlID": "u_column_1",
"htmlClassNames": "u_column"
},
"padding": "0px",
"border": {},
"borderRadius": "0px",
"backgroundColor": ""
}
}
],
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"columns": false,
"backgroundColor": "#F5FAF7",
"columnsBackgroundColor": "",
"backgroundImage": {
"url": "",
"fullWidth": true,
"repeat": "no-repeat",
"size": "custom",
"position": "center"
},
"padding": "0px",
"anchor": "",
"borderRadius": "",
"_meta": {
"htmlID": "u_row_1",
"htmlClassNames": "u_row"
}
}
},
{
"id": "u_row_2",
"cells": [
1
],
"columns": [
{
"id": "u_column_2",
"contents": [
{
"id": "u_content_image_1",
"type": "image",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "28px 36px 22px",
"anchor": "",
"src": {
"url": "https://xqy3m.mjt.lu/img2/xqy3m/eed4d18c-8065-4c5f-b47c-58af63171cd0/content",
"width": 140,
"height": "auto",
"autoWidth": false,
"maxWidth": "140px"
},
"textAlign": "left",
"altText": "TARGO",
"action": {
"name": "web",
"values": {
"href": "",
"target": "_blank"
}
},
"_meta": {
"htmlID": "u_content_image_1",
"htmlClassNames": "u_content_image"
}
}
},
{
"id": "u_content_text_1",
"type": "text",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "10px 25px 14px",
"anchor": "",
"fontWeight": 400,
"fontSize": "16px",
"color": "#374151",
"textAlign": "left",
"lineHeight": "150%",
"linkStyle": {
"inherit": true
},
"_meta": {
"htmlID": "u_content_text_1",
"htmlClassNames": "u_content_text"
},
"text": "Bonjour {{firstname}},"
}
},
{
"id": "u_content_text_2",
"type": "text",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "10px 25px 14px",
"anchor": "",
"fontWeight": 400,
"fontSize": "16px",
"color": "#374151",
"textAlign": "justify",
"lineHeight": "150%",
"linkStyle": {
"inherit": true
},
"_meta": {
"htmlID": "u_content_text_2",
"htmlClassNames": "u_content_text"
},
"text": "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."
}
},
{
"id": "u_content_text_3",
"type": "text",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "10px 25px 0px",
"anchor": "",
"fontWeight": 400,
"fontSize": "16px",
"color": "#374151",
"textAlign": "justify",
"lineHeight": "150%",
"linkStyle": {
"inherit": true
},
"_meta": {
"htmlID": "u_content_text_3",
"htmlClassNames": "u_content_text"
},
"text": "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."
}
},
{
"id": "u_content_html_2",
"type": "html",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "18px 36px 8px",
"anchor": "",
"_meta": {
"htmlID": "u_content_html_2",
"htmlClassNames": "u_content_html"
},
"html": "<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>"
}
},
{
"id": "u_content_html_3",
"type": "html",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "18px 36px 22px",
"anchor": "",
"_meta": {
"htmlID": "u_content_html_3",
"htmlClassNames": "u_content_html"
},
"html": "<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>"
}
},
{
"id": "u_content_button_1",
"type": "button",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "10px 25px",
"anchor": "",
"href": {
"name": "web",
"values": {
"href": "{{gift_url}}",
"target": "_blank"
}
},
"buttonColors": {
"color": "#ffffff",
"backgroundColor": "#00C853",
"hoverColor": "#ffffff",
"hoverBackgroundColor": "#005026"
},
"size": {
"autoWidth": false,
"width": "100%"
},
"fontSize": "32px",
"fontWeight": 700,
"textAlign": "center",
"lineHeight": "120%",
"padding": "30px 24px",
"border": {},
"borderRadius": "12px",
"_meta": {
"htmlID": "u_content_button_1",
"htmlClassNames": "u_content_button"
},
"text": "<span style=\"font-size: 32px; line-height: 120%; font-weight: 700;\">🎁&nbsp;&nbsp;{{amount}}</span>"
}
},
{
"id": "u_content_html_4",
"type": "html",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "0 36px 4px",
"anchor": "",
"_meta": {
"htmlID": "u_content_html_4",
"htmlClassNames": "u_content_html"
},
"html": "{{#expires_at_date}}\n <div style=\"background:#ffffff;background-color:#ffffff;margin:0px auto;max-width:600px;\">\n <table align=\"center\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\" style=\"background:#ffffff;background-color:#ffffff;width:100%;\">\n <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;\">\n <div style=\"font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:13px;line-height:1.4;text-align:center;color:#64748B;\">\n ⏰ Cadeau valide jusqu'au <strong style=\"color:#1B2E24;\">{{expires_at_date}}</strong>\n </div>\n </td></tr></tbody>\n </table>\n </div>\n {{/expires_at_date}}"
}
},
{
"id": "u_content_text_4",
"type": "text",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "10px 36px 22px",
"anchor": "",
"fontWeight": 400,
"fontSize": "14px",
"color": "#6b7280",
"textAlign": "left",
"lineHeight": "150%",
"linkStyle": {
"inherit": true
},
"_meta": {
"htmlID": "u_content_text_4",
"htmlClassNames": "u_content_text"
},
"text": "🪂 Annulation avant {{commitment_months}} mois : seulement à rembourser au prorata des mois restants."
}
},
{
"id": "u_content_html_5",
"type": "html",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "18px 36px 6px",
"anchor": "",
"_meta": {
"htmlID": "u_content_html_5",
"htmlClassNames": "u_content_html"
},
"html": "<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>"
}
},
{
"id": "u_content_text_5",
"type": "text",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "6px 36px 22px",
"anchor": "",
"fontWeight": 400,
"fontSize": "15px",
"color": "#4b5563",
"textAlign": "left",
"lineHeight": "155%",
"linkStyle": {
"inherit": true
},
"_meta": {
"htmlID": "u_content_text_5",
"htmlClassNames": "u_content_text"
},
"text": "Ne rien faire. Aucun changement à ton abonnement actuel."
}
},
{
"id": "u_content_text_6",
"type": "text",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "18px 36px 28px",
"anchor": "",
"fontWeight": 400,
"fontSize": "15px",
"color": "#1B2E24",
"textAlign": "left",
"lineHeight": "150%",
"linkStyle": {
"inherit": true
},
"_meta": {
"htmlID": "u_content_text_6",
"htmlClassNames": "u_content_text"
},
"text": "🤝 Merci de faire rouler l'économie de notre région avec nous !<br><br>L'équipe TARGO"
}
}
],
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"_meta": {
"htmlID": "u_column_2",
"htmlClassNames": "u_column"
},
"padding": "0px",
"border": {},
"borderRadius": "0px",
"backgroundColor": ""
}
}
],
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"columns": false,
"backgroundColor": "#ffffff",
"columnsBackgroundColor": "",
"backgroundImage": {
"url": "",
"fullWidth": true,
"repeat": "no-repeat",
"size": "custom",
"position": "center"
},
"padding": "0px",
"anchor": "",
"borderRadius": "",
"_meta": {
"htmlID": "u_row_2",
"htmlClassNames": "u_row"
}
}
},
{
"id": "u_row_3",
"cells": [
1
],
"columns": [
{
"id": "u_column_3",
"contents": [
{
"id": "u_content_text_7",
"type": "text",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "18px 36px 8px",
"anchor": "",
"fontWeight": 400,
"fontSize": "12px",
"color": "#64748B",
"textAlign": "center",
"lineHeight": "155%",
"linkStyle": {
"inherit": true
},
"_meta": {
"htmlID": "u_content_text_7",
"htmlClassNames": "u_content_text"
},
"text": "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>."
}
}
],
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"_meta": {
"htmlID": "u_column_3",
"htmlClassNames": "u_column"
},
"padding": "0px",
"border": {},
"borderRadius": "0px",
"backgroundColor": ""
}
}
],
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"columns": false,
"backgroundColor": "#F5FAF7",
"columnsBackgroundColor": "",
"backgroundImage": {
"url": "",
"fullWidth": true,
"repeat": "no-repeat",
"size": "custom",
"position": "center"
},
"padding": "0px",
"anchor": "",
"borderRadius": "",
"_meta": {
"htmlID": "u_row_3",
"htmlClassNames": "u_row"
}
}
},
{
"id": "u_row_4",
"cells": [
1
],
"columns": [
{
"id": "u_column_4",
"contents": [
{
"id": "u_content_html_6",
"type": "html",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "26px 36px 22px",
"anchor": "",
"_meta": {
"htmlID": "u_content_html_6",
"htmlClassNames": "u_content_html"
},
"html": "<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>"
}
}
],
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"_meta": {
"htmlID": "u_column_4",
"htmlClassNames": "u_column"
},
"padding": "0px",
"border": {},
"borderRadius": "0px",
"backgroundColor": ""
}
}
],
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"columns": false,
"backgroundColor": "#1C1E26",
"columnsBackgroundColor": "",
"backgroundImage": {
"url": "",
"fullWidth": true,
"repeat": "no-repeat",
"size": "custom",
"position": "center"
},
"padding": "0px",
"anchor": "",
"borderRadius": "",
"_meta": {
"htmlID": "u_row_4",
"htmlClassNames": "u_row"
}
}
}
],
"values": {
"popupPosition": "center",
"popupWidth": "600px",
"popupHeight": "auto",
"borderRadius": "10px",
"contentAlign": "center",
"contentVerticalAlign": "center",
"contentWidth": "600px",
"fontFamily": {
"label": "Plus Jakarta Sans",
"value": "'Plus Jakarta Sans', sans-serif",
"url": "https://fonts.googleapis.com/css?family=Plus+Jakarta+Sans:400,500,600,700"
},
"textColor": "#1B2E24",
"popupBackgroundColor": "#FFFFFF",
"backgroundColor": "#F5FAF7",
"preheaderText": "Comme toi, on aime les connexions stables et les relations durables.",
"linkStyle": {
"body": true,
"linkColor": "#00C853",
"linkHoverColor": "#005026",
"linkUnderline": true,
"linkHoverUnderline": true
},
"_meta": {
"htmlID": "u_body",
"htmlClassNames": "u_body"
}
}
},
"schemaVersion": 16
}

View File

@ -1912,6 +1912,7 @@ async function handle (req, res, method, path) {
description: '123 Rue de Test', gift_url: 'http://gtbt.co/PREVIEW',
amount: '60 $', expiry: '31 décembre 2026', commitment_months: '3',
expires_at_date: sampleExpAt, expires_in_days: '30',
year: new Date().getFullYear(),
view_url: '',
...(body.vars || {}),
}

View File

@ -0,0 +1,213 @@
#!/usr/bin/env node
'use strict'
/**
* ai-convert-to-native.js interpret an existing compiled .html template
* via Gemini Flash and produce a native-block templates-spec/<name>.js file
* that can be built by build-native-template.js.
*
* The AI handles SEMANTIC interpretation only (which paragraph is a
* greeting? which div is the CTA? which span is a chip?) the conversion
* to specific Unlayer JSON / HTML markup is then deterministic in
* build-native-template.js. This split prevents AI hallucinations in the
* final markup that gets sent to recipients.
*
* Usage:
* AI_API_KEY=... node ai-convert-to-native.js gift-email-fr
*
* Output:
* scripts/templates-spec/gift-email-fr-native.js (generated)
* templates/gift-email-fr-native.html + .json (built from the spec)
*/
const fs = require('fs')
const path = require('path')
const { aiCall } = require('../lib/ai')
// The AI returns an array of "block descriptors". Our deterministic builder
// then maps each one to the matching factory in build-native-template.js.
// Keeping the schema TIGHT means less surface for the model to invent things.
const SYSTEM_PROMPT = `You are an email-template interpreter. Given the inner-body HTML of a transactional email, identify the SEMANTIC BLOCKS and return ONLY a JSON object: { "preheader": "...", "ariaLabel": "...", "blocks": [ ... ] }.
Each block is an object with:
- "type" one of: "text", "image", "button", "html", "divider"
- "purpose" short label like "greeting", "intro", "cta", "expiry-badge", "prorata", "signature", "contact-info", "header-logo", "footer-logo", "option-1-chip", "option-2-chip", "brand-logos-card", "view-in-browser-link", "footer-text", "footer-band"
- type-specific fields (see below)
For type "text":
- "html" : the rich HTML content (preserve <strong>, <em>, <br/>, <a>, Mustache {{vars}} like {{firstname}}, etc.)
- "fontSize" : e.g. "16px", "14px", "13px"
- "fontWeight": 400 / 500 / 600 / 700
- "color" : hex like "#374151" or "#1B2E24"
- "textAlign" : "left" / "center" / "right" / "justify"
- "padding" : CSS shorthand for container padding, e.g. "10px 36px 14px"
- "background": (optional) row background color hex; default "#ffffff" if part of the white card
- "lineHeight": (optional) e.g. "150%" or "140%"
For type "image":
- "src" : full URL
- "alt" : alt text
- "width" : pixel width as number (e.g. 140)
- "padding" : container padding
- "textAlign": "left" / "center" / "right"
- "background": (optional) row background
- "href" : (optional) link URL
For type "button":
- "text" : button label HTML (often with Mustache like "🎁 {{amount}}")
- "href" : link URL (often "{{gift_url}}")
- "bgColor" : background hex
- "color" : text color hex
- "padding" : container padding
- "buttonPadding": inner button padding (e.g. "30px 24px")
- "borderRadius": e.g. "12px"
- "fontSize": e.g. "32px"
- "background": (optional) row background
For type "html":
- "html" : the raw HTML markup (keep this for chips, multi-image rows, anything too custom for native blocks)
- "padding" : container padding
- "background": (optional) row background
For type "divider":
- "padding" : container padding
- "background": (optional) row background
ROW STYLING if multiple consecutive blocks share the same card (white background, side borders, etc.), they should each carry the SAME "background" value so the deterministic builder groups them into one row with that background.
CRITICAL CONSTRAINTS:
- Preserve ALL Mustache placeholders verbatim: {{firstname}}, {{amount}}, {{gift_url}}, {{expires_at_date}}, {{commitment_months}}, {{description}}, {{year}}, {{view_url}}.
- Preserve all Mustache section blocks: {{#view_url}}...{{/view_url}} these go inside an "html" block as-is.
- Preserve external image URLs verbatim (xqy3m.mjt.lu/...).
- The "preheader" is the hidden div at the top of the body extract its inner text.
- The "ariaLabel" is the aria-label of the role="article" outer div.
- Output VALID JSON, no markdown fences, no commentary.`
function buildUserPrompt (innerHtml) {
return `Inner body HTML to interpret:
\`\`\`html
${innerHtml.slice(0, 60000)}
\`\`\`
Return the JSON now.`
}
function extractInnerBody (fullHtml) {
const m = fullHtml.match(/<body[^>]*>([\s\S]*?)<\/body>/i)
return m ? m[1] : fullHtml
}
// Map AI block descriptors → templates-spec JS source. The spec is a JS
// module so the operator can hand-tweak before re-running the builder.
function generateSpec (aiResult) {
const { preheader, ariaLabel, blocks } = aiResult
if (!Array.isArray(blocks)) throw new Error('AI did not return blocks[]')
// Group consecutive blocks sharing the same background into one row.
const rows = []
let current = null
for (const b of blocks) {
const bg = b.background || ''
if (!current || current.bg !== bg) {
if (current) rows.push(current)
current = { bg, blocks: [] }
}
current.blocks.push(b)
}
if (current) rows.push(current)
const factoryFor = (b) => {
switch (b.type) {
case 'text':
return `textBlock({ html: ${JSON.stringify(b.html || '')}, padding: ${JSON.stringify(b.padding || '10px')}, fontSize: ${JSON.stringify(b.fontSize || '16px')}, fontWeight: ${JSON.stringify(b.fontWeight || 400)}, color: ${JSON.stringify(b.color || '#374151')}, textAlign: ${JSON.stringify(b.textAlign || 'left')}${b.lineHeight ? `, lineHeight: ${JSON.stringify(b.lineHeight)}` : ''} })`
case 'image':
return `imageBlock({ src: ${JSON.stringify(b.src || '')}, alt: ${JSON.stringify(b.alt || '')}, width: ${b.width || 140}, padding: ${JSON.stringify(b.padding || '10px')}, textAlign: ${JSON.stringify(b.textAlign || 'center')}${b.href ? `, href: ${JSON.stringify(b.href)}` : ''} })`
case 'button':
return `buttonBlock({ text: ${JSON.stringify(b.text || '')}, href: ${JSON.stringify(b.href || '')}, padding: ${JSON.stringify(b.padding || '10px 25px')}, buttonPadding: ${JSON.stringify(b.buttonPadding || '30px 24px')}, bgColor: ${JSON.stringify(b.bgColor || '#00C853')}, color: ${JSON.stringify(b.color || '#FFFFFF')}, borderRadius: ${JSON.stringify(b.borderRadius || '12px')}, fontSize: ${JSON.stringify(b.fontSize || '32px')} })`
case 'divider':
return `dividerBlock({ padding: ${JSON.stringify(b.padding || '10px')} })`
case 'html':
default:
return `htmlBlock({ html: ${JSON.stringify(b.html || '')}, padding: ${JSON.stringify(b.padding || '0')} })`
}
}
const rowSrcs = rows.map(r => {
const blockSrcs = r.blocks.map(b => ` ${factoryFor(b)}, // ${b.purpose || b.type}`).join('\n')
const opts = r.bg ? `, { backgroundColor: ${JSON.stringify(r.bg)}, border: '1px solid #e5e7eb' }` : ''
return ` row([\n${blockSrcs}\n ]${opts}),`
})
return `'use strict'
/**
* AUTO-GENERATED by ai-convert-to-native.js review before deploying.
*
* The AI identified ${blocks.length} semantic block(s) in ${rows.length} row(s).
* Each text/image/button block is individually editable in Unlayer.
* html blocks (chips, multi-image strips) require raw HTML edits.
*/
module.exports = {
preheader: ${JSON.stringify(preheader || '')},
ariaLabel: ${JSON.stringify(ariaLabel || '')},
rows: ({ textBlock, imageBlock, buttonBlock, htmlBlock, dividerBlock, row }) => [
${rowSrcs.join('\n\n')}
],
}
`
}
// ── CLI ───────────────────────────────────────────────────────────────────
async function main () {
const srcName = process.argv[2]
if (!srcName) { console.error('Usage: ai-convert-to-native.js <template-name>'); process.exit(1) }
const tplDir = path.resolve(__dirname, '..', 'templates')
const srcPath = path.join(tplDir, srcName + '.html')
if (!fs.existsSync(srcPath)) {
console.error(`✗ Source not found: ${srcPath}`); process.exit(1)
}
const innerHtml = extractInnerBody(fs.readFileSync(srcPath, 'utf8'))
console.log(`→ Source: ${srcName}.html (${innerHtml.length}b inner body)`)
console.log('→ Asking Gemini Flash to identify blocks...')
const aiResult = await aiCall(SYSTEM_PROMPT, buildUserPrompt(innerHtml), {
jsonMode: true, maxTokens: 32768, temperature: 0.2,
})
if (aiResult.error || aiResult.raw) {
console.error('✗ AI returned unparseable output:', aiResult); process.exit(1)
}
console.log(`→ AI identified ${aiResult.blocks?.length || 0} blocks`)
const outName = srcName + '-native'
const specPath = path.resolve(__dirname, 'templates-spec', outName + '.js')
const specSrc = generateSpec(aiResult)
fs.writeFileSync(specPath, specSrc, 'utf8')
console.log(`✓ Spec written: scripts/templates-spec/${outName}.js (${specSrc.length}b)`)
// Sanity check: every {{var}} present in the source must survive into the
// generated spec. The AI occasionally drops minor placeholders ({{year}}
// in a copyright line is the canonical miss) — warn loudly so the
// operator can patch the spec before building.
const srcVars = new Set([...innerHtml.matchAll(/\{\{\s*[#/]?\s*([a-z0-9_]+)\s*\}\}/gi)].map(m => m[1].toLowerCase()))
const specVars = new Set([...specSrc.matchAll(/\{\{\s*[#/]?\s*([a-z0-9_]+)\s*\}\}/gi)].map(m => m[1].toLowerCase()))
const missing = [...srcVars].filter(v => !specVars.has(v))
if (missing.length) {
console.warn(`${missing.length} Mustache variable(s) NOT preserved in spec — review before building:`)
for (const v of missing) console.warn(` - {{${v}}}`)
console.warn(' The AI sometimes drops minor placeholders. Edit the spec file to restore them.')
} else {
console.log(`✓ All ${srcVars.size} Mustache variable(s) preserved in spec`)
}
console.log()
console.log('Next step: review the spec, then build the files:')
console.log(` node scripts/build-native-template.js ${outName}`)
console.log()
console.log('If the layout is good, deploy by copying the generated')
console.log(`templates/${outName}.html and .json to prod.`)
}
main().catch(e => { console.error('Fatal:', e); process.exit(1) })

View File

@ -0,0 +1,44 @@
'use strict'
/**
* AUTO-GENERATED by ai-convert-to-native.js review before deploying.
*
* The AI identified 15 semantic block(s) in 4 row(s).
* Each text/image/button block is individually editable in Unlayer.
* html blocks (chips, multi-image strips) require raw HTML edits.
*/
module.exports = {
preheader: "Comme toi, on aime les connexions stables et les relations durables.",
ariaLabel: "Une offre exclusive de TARGO",
rows: ({ textBlock, imageBlock, buttonBlock, htmlBlock, dividerBlock, row }) => [
row([
htmlBlock({ html: "{{#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}}", padding: "8px 36px 4px" }), // view-in-browser-link
], { backgroundColor: "#F5FAF7", border: '1px solid #e5e7eb' }),
row([
imageBlock({ src: "https://xqy3m.mjt.lu/img2/xqy3m/eed4d18c-8065-4c5f-b47c-58af63171cd0/content", alt: "TARGO", width: 140, padding: "28px 36px 22px", textAlign: "left" }), // header-logo
textBlock({ html: "Bonjour {{firstname}},", padding: "10px 25px 14px", fontSize: "16px", fontWeight: 400, color: "#374151", textAlign: "left", lineHeight: "150%" }), // greeting
textBlock({ html: "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.", padding: "10px 25px 14px", fontSize: "16px", fontWeight: 400, color: "#374151", textAlign: "justify", lineHeight: "150%" }), // intro
textBlock({ html: "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.", padding: "10px 25px 0px", fontSize: "16px", fontWeight: 400, color: "#374151", textAlign: "justify", lineHeight: "150%" }), // intro
htmlBlock({ html: "<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>", padding: "18px 36px 8px" }), // option-1-chip
htmlBlock({ html: "<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>", padding: "18px 36px 22px" }), // brand-logos-card
buttonBlock({ text: "🎁&nbsp;&nbsp;{{amount}}", href: "{{gift_url}}", padding: "10px 25px", buttonPadding: "30px 24px", bgColor: "#00C853", color: "#ffffff", borderRadius: "12px", fontSize: "32px" }), // cta
htmlBlock({ html: "{{#expires_at_date}}\n <div style=\"background:#ffffff;background-color:#ffffff;margin:0px auto;max-width:600px;\">\n <table align=\"center\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\" style=\"background:#ffffff;background-color:#ffffff;width:100%;\">\n <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;\">\n <div style=\"font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:13px;line-height:1.4;text-align:center;color:#64748B;\">\n ⏰ Cadeau valide jusqu'au <strong style=\"color:#1B2E24;\">{{expires_at_date}}</strong>\n </div>\n </td></tr></tbody>\n </table>\n </div>\n {{/expires_at_date}}", padding: "0 36px 4px" }), // expiry-badge
textBlock({ html: "🪂 Annulation avant {{commitment_months}} mois : seulement à rembourser au prorata des mois restants.", padding: "10px 36px 22px", fontSize: "14px", fontWeight: 400, color: "#6b7280", textAlign: "left", lineHeight: "150%" }), // prorata
htmlBlock({ html: "<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>", padding: "18px 36px 6px" }), // option-2-chip
textBlock({ html: "Ne rien faire. Aucun changement à ton abonnement actuel.", padding: "6px 36px 22px", fontSize: "15px", fontWeight: 400, color: "#4b5563", textAlign: "left", lineHeight: "155%" }), // option-2-text
textBlock({ html: "🤝 Merci de faire rouler l'économie de notre région avec nous !<br><br>L'équipe TARGO", padding: "18px 36px 28px", fontSize: "15px", fontWeight: 400, color: "#1B2E24", textAlign: "left", lineHeight: "150%" }), // signature
], { backgroundColor: "#ffffff", border: '1px solid #e5e7eb' }),
row([
textBlock({ html: "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>.", padding: "18px 36px 8px", fontSize: "12px", fontWeight: 400, color: "#64748B", textAlign: "center", lineHeight: "155%" }), // contact-info
], { backgroundColor: "#F5FAF7", border: '1px solid #e5e7eb' }),
row([
htmlBlock({ html: "<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>", padding: "26px 36px 22px" }), // footer-band
], { backgroundColor: "#1C1E26", border: '1px solid #e5e7eb' }),
],
}

View File

@ -0,0 +1,182 @@
<!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>

View File

@ -0,0 +1,665 @@
{
"counters": {
"u_row": 4,
"u_column": 4,
"u_content_text": 7,
"u_content_image": 1,
"u_content_button": 1,
"u_content_divider": 0,
"u_content_html": 6
},
"body": {
"id": "u_body",
"rows": [
{
"id": "u_row_1",
"cells": [
1
],
"columns": [
{
"id": "u_column_1",
"contents": [
{
"id": "u_content_html_1",
"type": "html",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "8px 36px 4px",
"anchor": "",
"_meta": {
"htmlID": "u_content_html_1",
"htmlClassNames": "u_content_html"
},
"html": "{{#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}}"
}
}
],
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"_meta": {
"htmlID": "u_column_1",
"htmlClassNames": "u_column"
},
"padding": "0px",
"border": {},
"borderRadius": "0px",
"backgroundColor": ""
}
}
],
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"columns": false,
"backgroundColor": "#F5FAF7",
"columnsBackgroundColor": "",
"backgroundImage": {
"url": "",
"fullWidth": true,
"repeat": "no-repeat",
"size": "custom",
"position": "center"
},
"padding": "0px",
"anchor": "",
"borderRadius": "",
"_meta": {
"htmlID": "u_row_1",
"htmlClassNames": "u_row"
}
}
},
{
"id": "u_row_2",
"cells": [
1
],
"columns": [
{
"id": "u_column_2",
"contents": [
{
"id": "u_content_image_1",
"type": "image",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "28px 36px 22px",
"anchor": "",
"src": {
"url": "https://xqy3m.mjt.lu/img2/xqy3m/eed4d18c-8065-4c5f-b47c-58af63171cd0/content",
"width": 140,
"height": "auto",
"autoWidth": false,
"maxWidth": "140px"
},
"textAlign": "left",
"altText": "TARGO",
"action": {
"name": "web",
"values": {
"href": "",
"target": "_blank"
}
},
"_meta": {
"htmlID": "u_content_image_1",
"htmlClassNames": "u_content_image"
}
}
},
{
"id": "u_content_text_1",
"type": "text",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "10px 25px 14px",
"anchor": "",
"fontWeight": 400,
"fontSize": "16px",
"color": "#374151",
"textAlign": "left",
"lineHeight": "150%",
"linkStyle": {
"inherit": true
},
"_meta": {
"htmlID": "u_content_text_1",
"htmlClassNames": "u_content_text"
},
"text": "Bonjour {{firstname}},"
}
},
{
"id": "u_content_text_2",
"type": "text",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "10px 25px 14px",
"anchor": "",
"fontWeight": 400,
"fontSize": "16px",
"color": "#374151",
"textAlign": "justify",
"lineHeight": "150%",
"linkStyle": {
"inherit": true
},
"_meta": {
"htmlID": "u_content_text_2",
"htmlClassNames": "u_content_text"
},
"text": "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."
}
},
{
"id": "u_content_text_3",
"type": "text",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "10px 25px 0px",
"anchor": "",
"fontWeight": 400,
"fontSize": "16px",
"color": "#374151",
"textAlign": "justify",
"lineHeight": "150%",
"linkStyle": {
"inherit": true
},
"_meta": {
"htmlID": "u_content_text_3",
"htmlClassNames": "u_content_text"
},
"text": "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."
}
},
{
"id": "u_content_html_2",
"type": "html",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "18px 36px 8px",
"anchor": "",
"_meta": {
"htmlID": "u_content_html_2",
"htmlClassNames": "u_content_html"
},
"html": "<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>"
}
},
{
"id": "u_content_html_3",
"type": "html",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "18px 36px 22px",
"anchor": "",
"_meta": {
"htmlID": "u_content_html_3",
"htmlClassNames": "u_content_html"
},
"html": "<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>"
}
},
{
"id": "u_content_button_1",
"type": "button",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "10px 25px",
"anchor": "",
"href": {
"name": "web",
"values": {
"href": "{{gift_url}}",
"target": "_blank"
}
},
"buttonColors": {
"color": "#ffffff",
"backgroundColor": "#00C853",
"hoverColor": "#ffffff",
"hoverBackgroundColor": "#005026"
},
"size": {
"autoWidth": false,
"width": "100%"
},
"fontSize": "32px",
"fontWeight": 700,
"textAlign": "center",
"lineHeight": "120%",
"padding": "30px 24px",
"border": {},
"borderRadius": "12px",
"_meta": {
"htmlID": "u_content_button_1",
"htmlClassNames": "u_content_button"
},
"text": "<span style=\"font-size: 32px; line-height: 120%; font-weight: 700;\">🎁&nbsp;&nbsp;{{amount}}</span>"
}
},
{
"id": "u_content_html_4",
"type": "html",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "0 36px 4px",
"anchor": "",
"_meta": {
"htmlID": "u_content_html_4",
"htmlClassNames": "u_content_html"
},
"html": "{{#expires_at_date}}\n <div style=\"background:#ffffff;background-color:#ffffff;margin:0px auto;max-width:600px;\">\n <table align=\"center\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\" style=\"background:#ffffff;background-color:#ffffff;width:100%;\">\n <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;\">\n <div style=\"font-family:Plus Jakarta Sans, Helvetica, Arial, sans-serif;font-size:13px;line-height:1.4;text-align:center;color:#64748B;\">\n ⏰ Cadeau valide jusqu'au <strong style=\"color:#1B2E24;\">{{expires_at_date}}</strong>\n </div>\n </td></tr></tbody>\n </table>\n </div>\n {{/expires_at_date}}"
}
},
{
"id": "u_content_text_4",
"type": "text",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "10px 36px 22px",
"anchor": "",
"fontWeight": 400,
"fontSize": "14px",
"color": "#6b7280",
"textAlign": "left",
"lineHeight": "150%",
"linkStyle": {
"inherit": true
},
"_meta": {
"htmlID": "u_content_text_4",
"htmlClassNames": "u_content_text"
},
"text": "🪂 Annulation avant {{commitment_months}} mois : seulement à rembourser au prorata des mois restants."
}
},
{
"id": "u_content_html_5",
"type": "html",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "18px 36px 6px",
"anchor": "",
"_meta": {
"htmlID": "u_content_html_5",
"htmlClassNames": "u_content_html"
},
"html": "<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>"
}
},
{
"id": "u_content_text_5",
"type": "text",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "6px 36px 22px",
"anchor": "",
"fontWeight": 400,
"fontSize": "15px",
"color": "#4b5563",
"textAlign": "left",
"lineHeight": "155%",
"linkStyle": {
"inherit": true
},
"_meta": {
"htmlID": "u_content_text_5",
"htmlClassNames": "u_content_text"
},
"text": "Ne rien faire. Aucun changement à ton abonnement actuel."
}
},
{
"id": "u_content_text_6",
"type": "text",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "18px 36px 28px",
"anchor": "",
"fontWeight": 400,
"fontSize": "15px",
"color": "#1B2E24",
"textAlign": "left",
"lineHeight": "150%",
"linkStyle": {
"inherit": true
},
"_meta": {
"htmlID": "u_content_text_6",
"htmlClassNames": "u_content_text"
},
"text": "🤝 Merci de faire rouler l'économie de notre région avec nous !<br><br>L'équipe TARGO"
}
}
],
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"_meta": {
"htmlID": "u_column_2",
"htmlClassNames": "u_column"
},
"padding": "0px",
"border": {},
"borderRadius": "0px",
"backgroundColor": ""
}
}
],
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"columns": false,
"backgroundColor": "#ffffff",
"columnsBackgroundColor": "",
"backgroundImage": {
"url": "",
"fullWidth": true,
"repeat": "no-repeat",
"size": "custom",
"position": "center"
},
"padding": "0px",
"anchor": "",
"borderRadius": "",
"_meta": {
"htmlID": "u_row_2",
"htmlClassNames": "u_row"
}
}
},
{
"id": "u_row_3",
"cells": [
1
],
"columns": [
{
"id": "u_column_3",
"contents": [
{
"id": "u_content_text_7",
"type": "text",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "18px 36px 8px",
"anchor": "",
"fontWeight": 400,
"fontSize": "12px",
"color": "#64748B",
"textAlign": "center",
"lineHeight": "155%",
"linkStyle": {
"inherit": true
},
"_meta": {
"htmlID": "u_content_text_7",
"htmlClassNames": "u_content_text"
},
"text": "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>."
}
}
],
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"_meta": {
"htmlID": "u_column_3",
"htmlClassNames": "u_column"
},
"padding": "0px",
"border": {},
"borderRadius": "0px",
"backgroundColor": ""
}
}
],
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"columns": false,
"backgroundColor": "#F5FAF7",
"columnsBackgroundColor": "",
"backgroundImage": {
"url": "",
"fullWidth": true,
"repeat": "no-repeat",
"size": "custom",
"position": "center"
},
"padding": "0px",
"anchor": "",
"borderRadius": "",
"_meta": {
"htmlID": "u_row_3",
"htmlClassNames": "u_row"
}
}
},
{
"id": "u_row_4",
"cells": [
1
],
"columns": [
{
"id": "u_column_4",
"contents": [
{
"id": "u_content_html_6",
"type": "html",
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"containerPadding": "26px 36px 22px",
"anchor": "",
"_meta": {
"htmlID": "u_content_html_6",
"htmlClassNames": "u_content_html"
},
"html": "<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>"
}
}
],
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"_meta": {
"htmlID": "u_column_4",
"htmlClassNames": "u_column"
},
"padding": "0px",
"border": {},
"borderRadius": "0px",
"backgroundColor": ""
}
}
],
"values": {
"selectable": true,
"draggable": true,
"duplicatable": true,
"deletable": true,
"hideable": true,
"hideDesktop": false,
"displayCondition": null,
"columns": false,
"backgroundColor": "#1C1E26",
"columnsBackgroundColor": "",
"backgroundImage": {
"url": "",
"fullWidth": true,
"repeat": "no-repeat",
"size": "custom",
"position": "center"
},
"padding": "0px",
"anchor": "",
"borderRadius": "",
"_meta": {
"htmlID": "u_row_4",
"htmlClassNames": "u_row"
}
}
}
],
"values": {
"popupPosition": "center",
"popupWidth": "600px",
"popupHeight": "auto",
"borderRadius": "10px",
"contentAlign": "center",
"contentVerticalAlign": "center",
"contentWidth": "600px",
"fontFamily": {
"label": "Plus Jakarta Sans",
"value": "'Plus Jakarta Sans', sans-serif",
"url": "https://fonts.googleapis.com/css?family=Plus+Jakarta+Sans:400,500,600,700"
},
"textColor": "#1B2E24",
"popupBackgroundColor": "#FFFFFF",
"backgroundColor": "#F5FAF7",
"preheaderText": "Comme toi, on aime les connexions stables et les relations durables.",
"linkStyle": {
"body": true,
"linkColor": "#00C853",
"linkHoverColor": "#005026",
"linkUnderline": true,
"linkHoverUnderline": true
},
"_meta": {
"htmlID": "u_body",
"htmlClassNames": "u_body"
}
}
},
"schemaVersion": 16
}