Skip to content

Commit

Permalink
fix(click-open-tracking): Allow to configure clicks and opens trackin…
Browse files Browse the repository at this point in the history
…g separately with trackOpens and trackClicks options
  • Loading branch information
andris9 committed Sep 2, 2024
1 parent 7e2e94f commit 1cc55bc
Show file tree
Hide file tree
Showing 7 changed files with 166 additions and 59 deletions.
10 changes: 7 additions & 3 deletions lib/add-trackers.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,15 +98,19 @@ async function addClickTrackers(html, account, messageId, baseUrl) {
return html;
}

async function addTrackers(raw, account, messageId, baseUrl) {
async function addTrackers(raw, account, messageId, baseUrl, opts) {
let { trackClicks, trackOpens } = opts || {};
let openTrackerAdded = false;
return await rewriteTextNodes(raw, {
async htmlRewriter(html) {
if (!openTrackerAdded) {
if (trackOpens && !openTrackerAdded) {
html = await addOpenTracker(html, account, messageId, baseUrl);
openTrackerAdded = true;
}
html = await addClickTrackers(html, account, messageId, baseUrl);

if (trackClicks) {
html = await addClickTrackers(html, account, messageId, baseUrl);
}
return html;
}
});
Expand Down
26 changes: 23 additions & 3 deletions lib/api-client/base-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -1230,7 +1230,10 @@ class BaseClient {
}
}

let { raw, hasBcc, envelope, subject, messageId, sendAt, deliveryAttempts, trackingEnabled, gateway } = await getRawEmail(data, licenseInfo);
let { raw, hasBcc, envelope, subject, messageId, sendAt, deliveryAttempts, trackClicks, trackOpens, trackingEnabled, gateway } = await getRawEmail(
data,
licenseInfo
);

if (data.dryRun) {
let response = {
Expand Down Expand Up @@ -1277,9 +1280,26 @@ class BaseClient {
trackingEnabled = (await settings.get('trackSentMessages')) || false;
}

if (raw && trackingEnabled && baseUrl) {
if (typeof trackClicks !== 'boolean') {
trackClicks = await settings.get('trackClicks');
if (typeof trackClicks !== 'boolean') {
trackClicks = trackingEnabled;
}
}

if (typeof trackOpens !== 'boolean') {
trackOpens = await settings.get('trackOpens');
if (typeof trackOpens !== 'boolean') {
trackOpens = trackingEnabled;
}
}

if (raw && (trackClicks || trackOpens) && baseUrl) {
// add open and click tracking
raw = await addTrackers(raw, accountData.account, messageId, baseUrl);
raw = await addTrackers(raw, accountData.account, messageId, baseUrl, {
trackClicks,
trackOpens
});
}

let now = new Date();
Expand Down
25 changes: 24 additions & 1 deletion lib/get-raw-email.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ async function processMessage(data, licenseInfo) {
let deliveryAttempts = data.deliveryAttempts;
let subject = data.subject;
let trackingEnabled = data.trackingEnabled;

let gateway = data.gateway;

const splitter = new Splitter();
Expand Down Expand Up @@ -263,7 +264,22 @@ async function processMessage(data, licenseInfo) {
splitter.end(raw);
});

return { raw: message, hasBcc, messageId, envelope, subject, sendAt, deliveryAttempts, trackingEnabled, gateway };
let trackClicks = typeof data.trackClicks === 'boolean' ? data.trackClicks : trackingEnabled;
let trackOpens = typeof data.trackOpens === 'boolean' ? data.trackClicks : trackingEnabled;

return {
raw: message,
hasBcc,
messageId,
envelope,
subject,
sendAt,
deliveryAttempts,
trackClicks,
trackOpens,
trackingEnabled,
gateway
};
}

async function removeBcc(raw) {
Expand Down Expand Up @@ -349,6 +365,9 @@ async function getRawEmail(data, licenseInfo) {
let gateway = data.gateway;
let trackingEnabled = data.trackingEnabled;

let trackClicks = typeof data.trackClicks === 'boolean' ? data.trackClicks : trackingEnabled;
let trackOpens = typeof data.trackOpens === 'boolean' ? data.trackOpens : trackingEnabled;

let html = data.html || null;
if (data.previewText && html) {
let previewText = data.previewText;
Expand Down Expand Up @@ -385,6 +404,8 @@ async function getRawEmail(data, licenseInfo) {
deliveryAttempts: null,
gateway: null,
trackingEnabled: null,
trackClicks: null,
trackOpens: null,
previewText: null
}
)
Expand All @@ -408,6 +429,8 @@ async function getRawEmail(data, licenseInfo) {
sendAt,
deliveryAttempts,
trackingEnabled,
trackClicks,
trackOpens,
gateway
};
}
Expand Down
21 changes: 18 additions & 3 deletions lib/routes-ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -1223,6 +1223,8 @@ function applyRoutes(server, call) {
method: 'GET',
path: '/admin/config/service',
async handler(request, h) {
let trackSentMessages = (await settings.get('trackSentMessages')) || false;

const values = {
serviceUrl: (await settings.get('serviceUrl')) || null,
serviceSecret: (await settings.get('serviceSecret')) || null,
Expand All @@ -1232,7 +1234,10 @@ function applyRoutes(server, call) {
scriptEnv: (await settings.get('scriptEnv')) || '',
enableTokens: !(await settings.get('disableTokens')),
enableApiProxy: (await settings.get('enableApiProxy')) || false,
trackSentMessages: (await settings.get('trackSentMessages')) || false,

trackClicks: await settings.get('trackClicks'),
trackOpens: await settings.get('trackOpens'),

resolveGmailCategories: (await settings.get('resolveGmailCategories')) || false,
enableOAuthTokensApi: (await settings.get('enableOAuthTokensApi')) || false,

Expand All @@ -1242,6 +1247,14 @@ function applyRoutes(server, call) {
timezone: (await settings.get('timezone')) || false
};

if (typeof values.trackClicks !== 'boolean') {
values.trackClicks = trackSentMessages;
}

if (typeof values.trackOpens !== 'boolean') {
values.trackOpens = trackSentMessages;
}

if (typeof values.deliveryAttempts !== 'number') {
values.deliveryAttempts = DEFAULT_DELIVERY_ATTEMPTS;
}
Expand Down Expand Up @@ -1281,7 +1294,8 @@ function applyRoutes(server, call) {
scriptEnv: request.payload.scriptEnv,
disableTokens: !request.payload.enableTokens,
enableApiProxy: request.payload.enableApiProxy,
trackSentMessages: request.payload.trackSentMessages,
trackOpens: request.payload.trackOpens,
trackClicks: request.payload.trackClicks,
resolveGmailCategories: request.payload.resolveGmailCategories,
enableOAuthTokensApi: request.payload.enableOAuthTokensApi,
ignoreMailCertErrors: request.payload.ignoreMailCertErrors,
Expand Down Expand Up @@ -1380,7 +1394,8 @@ function applyRoutes(server, call) {
templateHeader: settingsSchema.templateHeader.default(''),
scriptEnv: settingsSchema.scriptEnv.default(''),
enableApiProxy: settingsSchema.enableApiProxy.default(false),
trackSentMessages: settingsSchema.trackSentMessages.default(false),
trackOpens: settingsSchema.trackOpens.default(false),
trackClicks: settingsSchema.trackClicks.default(false),
resolveGmailCategories: settingsSchema.resolveGmailCategories.default(false),
ignoreMailCertErrors: settingsSchema.ignoreMailCertErrors.default(false),

Expand Down
13 changes: 12 additions & 1 deletion lib/schemas.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,18 @@ const settingsSchema = {
trackSentMessages: Joi.boolean()
.truthy('Y', 'true', '1', 'on')
.falsy('N', 'false', 0, '')
.description('If true, then rewrite html links in sent emails to track opens and clicks'),
.description('If true, then rewrite html links in sent emails to track opens and clicks')
.meta({ swaggerHidden: true }),

trackClicks: Joi.boolean()
.truthy('Y', 'true', '1', 'on')
.falsy('N', 'false', 0, '')
.description('If true, then rewrite html links in sent emails to track clicks'),

trackOpens: Joi.boolean()
.truthy('Y', 'true', '1', 'on')
.falsy('N', 'false', 0, '')
.description('If true, then add an open tracking beacon image to email html'),

resolveGmailCategories: Joi.boolean()
.truthy('Y', 'true', '1', 'on')
Expand Down
Loading

0 comments on commit 1cc55bc

Please sign in to comment.