Recipes

Some useful recipes for your newsletters.

Create a manual newsletter

A manual newsletter is a newsletter edited by humans. Some editions are generated.

  • When you click on "Créer une newsletter", you can choose your newsletter broadcast service depending on integrations you configured



  • In newsletter settings interface, fill the field with your provider campaign and provider informations. Keep the mode to "Manuel".



  • Some fields accept javascript and can be filled with data fetched from GraphQL.



GraphQL

{
preHeader: textArea(name: "pre-header")
@placeholder(value: "Des nouvelles de l’Obs")
@label(value: "Pre-header")
@textAreaOptions(multiline: true)
main: articlesArea(name: "zone_1", limit: 1)
@label(value: "Leads")
@seed(ids: [28893]) {
id
url
title
authors {
id
longName
origin
}
nodes(where: { type: { eq: text }, textNode: { type: { neq: heading } } }) {
__typename
... on TextArticleNode {
textNode {
type
text
}
}
}
}
leads: articlesArea(name: "zone_2", limit: 6)
@label(value: "Leads")
@seed(ids: [23134, 23507, 22803, 23654, 22411, 23634]) {
id
title
url
image(width: 250, height: 120, aspectRatio: ratio_3x2) {
url
alt
width
height
}
}
metadata {
environment
date(format: "YYYYMMDDHHmmss")
url
trackingDate: date(format: "YYYYMMDD")
provider {
__typename
... on SelligentMetadata {
segment {
api_name
}
}
}
}
}

This query will define one text area to manage newsletter pre-header and two articles area controllable in publication.

Template

<!DOCTYPE html>
<html
lang="fr"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:v="urn:schemas-microsoft-com:vml"
>
<head>
<title>Lettre aux abonnés</title>
<style type="text/css">
/* YOUR CSS HERE */
</style>
</head>
<body>
<!-- Visually Hidden Preheader Text : BEGIN -->
<div
style="
display: none;
font-size: 1px;
line-height: 1px;
max-height: 0px;
max-width: 0px;
opacity: 0;
overflow: hidden;
mso-hide: all;
font-family: sans-serif;
"
>
{{preHeader}}
</div>
<!-- Visually Hidden Preheader Text : END -->
<p>
Pour visualiser correctement ce message, accédez à la
<a
href="{{{metadata.url}}}"
target="_blank"
>version en ligne</a
>
</p>
{{!-- Section "Main" : begin --}}
<div>
{{#each main}}
<div>{{{title}}}</div>
{{#each nodes}} {{#if @first}}
<div class="article__content" style="margin-top: 20px">
{{else}}
<div class="article__content" style="margin-top: 0">
{{/if}} {{{addDataLinks textNode.text 'zone-1'}}}
</div>
{{/each}} {{#if authors.0.longName}}
<div>
<strong>{{authors.0.longName}}</strong><br />{{authors.0.origin}}
</div>
{{/if}}
</div>
{{/each}}
</div>
{{!-- Section "Main" : ends --}}
{{!-- Section "Leads" : begin --}}
{{#if leads}}
<div>
<div>Voici une sélection de nos articles</div>
<div>
{{#each leads}}
<div class="stack-column">
{{#if image}}
<div>
<a href="{{trackingNlArticle url ../metadata.trackingDate 'zone_2' @index}}" target="_blank">
<img alt="{{image.alt}}" class="fluid" src="{{image.url}}" />
</a>
</div>
{{/if}}
<div>
<a href="{{trackingNlArticle url ../metadata.trackingDate 'zone_2' @index}}"
>{{{title}}}</a
>
</div>
</div>
{{/each}}
</div>
</div>
{{/if}}
{{!-- Section "Leads" : end --}}
</body>
</html>

Helpers

const dataLinksCounters = {};
Handlebars.registerHelper("addDataLinks", function (text, tag = "") {
if (typeof dataLinksCounters[tag] === "undefined") {
dataLinksCounters[tag] = 0;
}
const linkRegex = /<a href="([^"]+)">([^<]+)<\/a>/gi;
return text.replace(linkRegex, (found, link, text) => {
dataLinksCounters[sectionTag] += 1;
return `<a href="${link}" data-link="${tag}_${dataLinksCounters[tag]}">${text}</a>`;
});
});
Handlebars.registerHelper(
"trackingNlArticle",
function (url, trackingDate, tag, articleIndex) {
if (!url) {
return "";
}
const xtor = `EPR-1XXXXX1-${trackingDate}-${articleIndex}-${tag}`;
const urlObj = new URL(url);
urlObj.searchParams.append("xtor", xtor);
return decodeURIComponent(urlObj.href);
},
);

Create an automatic newsletter

For automatic newsletter you will have to configure sending frequency (except for alert). This can be done using the crontab syntax.

newsletter cron “At 12:30 on every day-of-week from Monday through Friday.”

You can fetch articles for a particular rubric. This query will fetch the last 10 articles with "sport" as header section:

sportArticles: section(slug: "sport") {
articles(limit: 10, header: true) {
id
title
url
chapo
pricingTier {
value
}
}
}

For section manually managed you can also fetch articles from a specific area:

sportArticles: section(slug: "sport") {
articles(area: "zone_1", limit: 3) {
id
title
url
chapo
image(width: 480, height: 328, aspectRatio: ratio_3x2) {
url
alt
width
height
}
}
}

Alert newsletter

It is possible to trigger email campaign on alert publication. To achieve this, you must select "Automatique" mode, left cron field empty and check the alert checkbox.


Therefore, you can retrieve alert data in GraphQL as follow:

query AlertQuery($alertId: Int! = 51) {
alert(id: $alertId) {
id
title
text
article {
url
}
}
}

Use alias article to create custom editable contents

Alias articles can help you achieve some use cases.

  • For example, for now article don't have teaser for newsletter context, but you could create an alias with url field targeting your article and defined a different title
  • It may be helpful when needing to add an image with a link in your template and manage it via Sirius you can do it with an alias.
article(id: 23) {
id
title
url
}

You can access your alias url field directly with article url.

Helpers recipes

Some example of helpers commonly used in newsletters.

Definition

const dataLinksCounters = {};
Handlebars.registerHelper("addDataLinks", function (text, tag = "") {
if (typeof dataLinksCounters[tag] === "undefined") {
dataLinksCounters[tag] = 0;
}
const linkRegex = /<a href="([^"]+)">([^<]+)<\/a>/gi;
return text.replace(linkRegex, (found, link, text) => {
dataLinksCounters[sectionTag] += 1;
return `<a href="${link}" data-link="${tag}_${dataLinksCounters[tag]}">${text}</a>`;
});
});

Usage

<p>{{{addDataLinks textNode.text "zone-1"}}}</p>

Add xtor tracking param to specific URL

Definition

Handlebars.registerHelper(
"trackingNlArticle",
function (url, trackingDate, tag, articleIndex) {
if (!url) {
return "";
}
const xtor = `EPR-1XXXXX1-${trackingDate}-${articleIndex}-${tag}`;
const urlObj = new URL(url);
urlObj.searchParams.append("xtor", xtor);
return decodeURIComponent(urlObj.href);
},
);

Usage

{{#each zone2Articles}}
<a href="{{{trackingNlArticle url ../metadata.trackingDate '' @index}}}">{{{title}}}</a>
{{/each}}

Remove duplicate articles

Definition

const articlesIds = [];
Handlebars.registerHelper("dedup", function (articles, limit, options) {
if (typeof limit === "object") {
options = limit;
limit = undefined;
}
let data;
if (options.data) {
data = Handlebars.createFrame(options.data);
}
const dedupArticles = articles
.filter((article) => !articlesIds.includes(article.id))
.slice(0, limit);
articlesIds.push(...dedupArticles.map(({ id }) => id));
data.dedupArticles = dedupArticles;
return options.fn(this, { data });
});

Usage

{{! Section "Most read" : begin }}
{{#dedup zone3Articles 3}}
{{#if @dedupArticles}}
<h2>Most Read</h2>
{{#each @dedupArticles}}
<p>{{{title}}}</p>
{{/each}}
{{/if}}
{{/dedup}}
{{! Section "Most read" : end }}
Edit this page on GitHub