diff --git a/ghost/core/core/server/services/staff/index.js b/ghost/core/core/server/services/staff/index.js
index 8ad4632d63..2b57d20de6 100644
--- a/ghost/core/core/server/services/staff/index.js
+++ b/ghost/core/core/server/services/staff/index.js
@@ -12,6 +12,7 @@ class StaffServiceWrapper {
const logging = require('@tryghost/logging');
const models = require('../../models');
+ const memberAttribution = require('../member-attribution');
const {GhostMailer} = require('../mail');
const mailer = new GhostMailer();
const settingsCache = require('../../../shared/settings-cache');
@@ -26,6 +27,7 @@ class StaffServiceWrapper {
settingsCache,
urlUtils,
DomainEvents,
+ memberAttributionService: memberAttribution.service,
labs
});
diff --git a/ghost/staff-service/lib/email-templates/new-free-signup.hbs b/ghost/staff-service/lib/email-templates/new-free-signup.hbs
index 26eba02ddd..c2a1007267 100644
--- a/ghost/staff-service/lib/email-templates/new-free-signup.hbs
+++ b/ghost/staff-service/lib/email-templates/new-free-signup.hbs
@@ -37,21 +37,18 @@
-
+ |
{{memberData.initials}}
|
-
+ |
{{memberData.name}}
{{#if memberData.showEmail}}
{{memberData.email}}
{{/if}}
Created on {{memberData.createdAt}}{{#if memberData.location}} • {{memberData.location}} {{/if}}
- {{#if referrerSource}}
- Source: {{referrerSource}}
- {{/if}}
|
@@ -60,6 +57,25 @@
+
+
+
+ {{#if referrerSource}}
+ Signup info
+
+ Source
+ - {{referrerSource}}
+
+ {{#if attributionTitle}}
+ Page
+ - {{attributionTitle}}
+
+ {{/if}}
+ {{/if}}
+ |
+
+
+
diff --git a/ghost/staff-service/lib/email-templates/new-paid-started.hbs b/ghost/staff-service/lib/email-templates/new-paid-started.hbs
index 10b2aec16a..d3b7674207 100644
--- a/ghost/staff-service/lib/email-templates/new-paid-started.hbs
+++ b/ghost/staff-service/lib/email-templates/new-paid-started.hbs
@@ -37,45 +37,58 @@
-
+ |
{{memberData.initials}}
|
-
+ |
{{memberData.name}}
{{#if memberData.showEmail}}
{{memberData.email}}
{{/if}}
Subscription started on {{subscriptionData.startedOn}}
- {{#if referrerSource}}
- Source: {{referrerSource}}
- {{/if}}
|
|
-
-
-
- Tier
- {{tierData.name}}
- {{#if tierData.details}} - {{tierData.details}}{{/if}}
-
- |
-
- {{#if offerData}}
-
-
- Offer
- {{offerData.name}} - {{offerData.details}}
- |
-
- {{/if}}
+
+
+
+
+ Tier
+
+ {{tierData.name}}
+ {{#if tierData.details}} - {{tierData.details}}{{/if}}
+
+
+ {{#if offerData}}
+ Offer
+
+ {{offerData.name}} - {{offerData.details}}
+ {{/if}}
+
+ {{#if referrerSource}}
+ Signup info
+
+ Source
+ - {{referrerSource}}
+
+ {{#if attributionTitle}}
+ Page
+ - {{attributionTitle}}
+
+ {{/if}}
+ {{/if}}
+
+ |
+
+
+
diff --git a/ghost/staff-service/lib/emails.js b/ghost/staff-service/lib/emails.js
index 089b965a01..4fe62a44a4 100644
--- a/ghost/staff-service/lib/emails.js
+++ b/ghost/staff-service/lib/emails.js
@@ -27,8 +27,16 @@ class StaffServiceEmails {
const subject = `🥳 Free member signup: ${memberData.name}`;
+ let attributionTitle = attribution?.title || '';
+ // In case of a homepage attribution, we want to show the title as "Homepage" on email
+ if (attributionTitle === 'homepage') {
+ attributionTitle = 'Homepage';
+ }
+
const templateData = {
memberData,
+ attributionTitle,
+ attributionUrl: attribution?.url || '',
referrerSource: attribution?.referrerSource,
siteTitle: this.settingsCache.get('title'),
siteUrl: this.urlUtils.getSiteUrl(),
@@ -73,8 +81,16 @@ class StaffServiceEmails {
let offerData = this.getOfferData(offer);
+ let attributionTitle = attribution?.title || '';
+ // In case of a homepage attribution, we want to show the title as "Homepage" on email
+ if (attributionTitle === 'homepage') {
+ attributionTitle = 'Homepage';
+ }
+
const templateData = {
memberData,
+ attributionTitle,
+ attributionUrl: attribution?.url || '',
referrerSource: attribution?.referrerSource,
tierData,
offerData,
diff --git a/ghost/staff-service/lib/staff-service.js b/ghost/staff-service/lib/staff-service.js
index 47fc642e71..8502a24d61 100644
--- a/ghost/staff-service/lib/staff-service.js
+++ b/ghost/staff-service/lib/staff-service.js
@@ -5,13 +5,14 @@ const {MilestoneCreatedEvent} = require('@tryghost/milestones');
// @NOTE: 'StaffService' is a vague name that does not describe what it's actually doing.
// Possibly, "StaffNotificationService" or "StaffEventNotificationService" would be a more accurate name
class StaffService {
- constructor({logging, models, mailer, settingsCache, settingsHelpers, urlUtils, DomainEvents, labs}) {
+ constructor({logging, models, mailer, settingsCache, settingsHelpers, urlUtils, DomainEvents, labs, memberAttributionService}) {
this.logging = logging;
this.labs = labs;
/** @private */
this.settingsCache = settingsCache;
this.models = models;
this.DomainEvents = DomainEvents;
+ this.memberAttributionService = memberAttributionService;
const Emails = require('./emails');
@@ -98,17 +99,29 @@ class StaffService {
});
if (type === MemberCreatedEvent && member.status === 'free') {
+ let attribution;
+ try {
+ attribution = await this.memberAttributionService.getMemberCreatedAttribution(event.data.memberId);
+ } catch (e) {
+ this.logging.warn(`Failed to get attribution for member - ${event?.data?.memberId}`);
+ }
await this.emails.notifyFreeMemberSignup({
member,
- attribution: event?.data?.attribution
+ attribution
});
} else if (type === SubscriptionActivatedEvent) {
+ let attribution;
+ try {
+ attribution = await this.memberAttributionService.getSubscriptionCreatedAttribution(event.data.subscriptionId);
+ } catch (e) {
+ this.logging.warn(`Failed to get attribution for member - ${event?.data?.memberId}`);
+ }
await this.emails.notifyPaidSubscriptionStarted({
member,
offer,
tier,
subscription,
- attribution: event?.data?.attribution
+ attribution
});
} else if (type === SubscriptionCancelledEvent) {
subscription.canceledAt = event.timestamp;
diff --git a/ghost/staff-service/test/staff-service.test.js b/ghost/staff-service/test/staff-service.test.js
index cc339ed3c9..4a312a9e4e 100644
--- a/ghost/staff-service/test/staff-service.test.js
+++ b/ghost/staff-service/test/staff-service.test.js
@@ -429,7 +429,9 @@ describe('StaffService', function () {
};
const attribution = {
- referrerSource: 'Twitter'
+ referrerSource: 'Twitter',
+ title: 'Welcome Post',
+ url: 'https://example.com/welcome'
};
await service.emails.notifyFreeMemberSignup({member, attribution}, options);
@@ -447,8 +449,23 @@ describe('StaffService', function () {
mailStub.calledWith(
sinon.match.has('html', sinon.match('Created on 1 Aug 2022 • France'))
).should.be.true();
+
mailStub.calledWith(
- sinon.match.has('html', sinon.match('Source: Twitter'))
+ sinon.match.has('html', sinon.match('Source'))
+ ).should.be.true();
+
+ mailStub.calledWith(
+ sinon.match.has('html', sinon.match('Twitter'))
+ ).should.be.true();
+
+ // check attribution page
+ mailStub.calledWith(
+ sinon.match.has('html', sinon.match('Welcome Post'))
+ ).should.be.true();
+
+ // check attribution url
+ mailStub.calledWith(
+ sinon.match.has('html', sinon.match('https://example.com/welcome'))
).should.be.true();
});
});
@@ -486,7 +503,9 @@ describe('StaffService', function () {
it('sends paid subscription start alert with attribution', async function () {
const attribution = {
- referrerSource: 'Twitter'
+ referrerSource: 'Twitter',
+ title: 'Welcome Post',
+ url: 'https://example.com/welcome'
};
await service.emails.notifyPaidSubscriptionStarted({member, offer: null, tier, subscription, attribution}, options);
@@ -495,7 +514,22 @@ describe('StaffService', function () {
// check attribution text
mailStub.calledWith(
- sinon.match.has('html', sinon.match('Source: Twitter'))
+ sinon.match.has('html', sinon.match('Twitter'))
+ ).should.be.true();
+
+ // check attribution text
+ mailStub.calledWith(
+ sinon.match.has('html', sinon.match('Source'))
+ ).should.be.true();
+
+ // check attribution page
+ mailStub.calledWith(
+ sinon.match.has('html', sinon.match('Welcome Post'))
+ ).should.be.true();
+
+ // check attribution url
+ mailStub.calledWith(
+ sinon.match.has('html', sinon.match('https://example.com/welcome'))
).should.be.true();
});
|