🎨 Added source attribution info to email alerts (#16360)
refs https://github.com/TryGhost/Team/issues/2489 - adds attribution info for new free and paid members in email alerts
This commit is contained in:
parent
74067f23bd
commit
d6a1d98aca
@ -1086,6 +1086,7 @@ module.exports = class MemberRepository {
|
||||
memberId: member.id,
|
||||
subscriptionId: subscriptionModel.get('id'),
|
||||
offerId: offerId,
|
||||
attribution: data.attribution,
|
||||
batchId: options.batch_id
|
||||
});
|
||||
this.dispatchEvent(activatedEvent, options);
|
||||
|
@ -48,6 +48,9 @@
|
||||
<p class="text-link" style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 13px; padding-right: 8px; padding: 0; margin: 0; color: #394047; font-weight: 400;">{{memberData.email}}</p>
|
||||
{{/if}}
|
||||
<p style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 13px; padding-right: 8px; padding: 0; margin: 0; color: #95A1AD;">Created on {{memberData.createdAt}}{{#if memberData.location}} • {{memberData.location}} {{/if}}
|
||||
{{#if referrerSource}}
|
||||
<p class="text-link" style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 13px; padding-right: 8px; padding: 0; margin: 0; color: #95A1AD;">Source: {{referrerSource}}</p>
|
||||
{{/if}}
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -48,6 +48,9 @@
|
||||
<p class="text-link" style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 13px; padding-right: 8px; padding: 0; margin: 0; color: #394047; font-weight: 400;">{{memberData.email}}</p>
|
||||
{{/if}}
|
||||
<p style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 13px; padding-right: 8px; padding: 0; margin: 0; color: #95A1AD;">Subscription started on {{subscriptionData.startedOn}} </p>
|
||||
{{#if referrerSource}}
|
||||
<p class="text-link" style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 13px; padding-right: 8px; padding: 0; margin: 0; color: #95A1AD;">Source: {{referrerSource}}</p>
|
||||
{{/if}}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
@ -16,7 +16,9 @@ class StaffServiceEmails {
|
||||
this.registerPartials();
|
||||
}
|
||||
|
||||
async notifyFreeMemberSignup(member, options) {
|
||||
async notifyFreeMemberSignup({
|
||||
member, attribution
|
||||
}, options) {
|
||||
const users = await this.models.User.getEmailAlertUsers('free-signup', options);
|
||||
|
||||
for (const user of users) {
|
||||
@ -27,6 +29,7 @@ class StaffServiceEmails {
|
||||
|
||||
const templateData = {
|
||||
memberData,
|
||||
referrerSource: attribution?.referrerSource,
|
||||
siteTitle: this.settingsCache.get('title'),
|
||||
siteUrl: this.urlUtils.getSiteUrl(),
|
||||
siteDomain: this.siteDomain,
|
||||
@ -47,7 +50,7 @@ class StaffServiceEmails {
|
||||
}
|
||||
}
|
||||
|
||||
async notifyPaidSubscriptionStarted({member, subscription, offer, tier}, options = {}) {
|
||||
async notifyPaidSubscriptionStarted({member, subscription, offer, tier, attribution}, options = {}) {
|
||||
const users = await this.models.User.getEmailAlertUsers('paid-started', options);
|
||||
|
||||
for (const user of users) {
|
||||
@ -72,6 +75,7 @@ class StaffServiceEmails {
|
||||
|
||||
const templateData = {
|
||||
memberData,
|
||||
referrerSource: attribution?.referrerSource,
|
||||
tierData,
|
||||
offerData,
|
||||
subscriptionData,
|
||||
|
@ -98,13 +98,17 @@ class StaffService {
|
||||
});
|
||||
|
||||
if (type === MemberCreatedEvent && member.status === 'free') {
|
||||
await this.emails.notifyFreeMemberSignup(member);
|
||||
await this.emails.notifyFreeMemberSignup({
|
||||
member,
|
||||
attribution: event?.data?.attribution
|
||||
});
|
||||
} else if (type === SubscriptionActivatedEvent) {
|
||||
await this.emails.notifyPaidSubscriptionStarted({
|
||||
member,
|
||||
offer,
|
||||
tier,
|
||||
subscription
|
||||
subscription,
|
||||
attribution: event?.data?.attribution
|
||||
});
|
||||
} else if (type === SubscriptionCancelledEvent) {
|
||||
subscription.canceledAt = event.timestamp;
|
||||
|
@ -377,7 +377,7 @@ describe('StaffService', function () {
|
||||
created_at: '2022-08-01T07:30:39.882Z'
|
||||
};
|
||||
|
||||
await service.emails.notifyFreeMemberSignup(member, options);
|
||||
await service.emails.notifyFreeMemberSignup({member}, options);
|
||||
|
||||
mailStub.calledOnce.should.be.true();
|
||||
testCommonMailData(stubs);
|
||||
@ -402,7 +402,7 @@ describe('StaffService', function () {
|
||||
created_at: '2022-08-01T07:30:39.882Z'
|
||||
};
|
||||
|
||||
await service.emails.notifyFreeMemberSignup(member, options);
|
||||
await service.emails.notifyFreeMemberSignup({member}, options);
|
||||
|
||||
mailStub.calledOnce.should.be.true();
|
||||
testCommonMailData(stubs);
|
||||
@ -418,6 +418,39 @@ describe('StaffService', function () {
|
||||
sinon.match.has('html', sinon.match('Created on 1 Aug 2022 • France'))
|
||||
).should.be.true();
|
||||
});
|
||||
|
||||
it('sends free member signup alert with attribution', async function () {
|
||||
const member = {
|
||||
name: 'Ghost',
|
||||
email: 'member@example.com',
|
||||
id: 'abc',
|
||||
geolocation: '{"country": "France"}',
|
||||
created_at: '2022-08-01T07:30:39.882Z'
|
||||
};
|
||||
|
||||
const attribution = {
|
||||
referrerSource: 'Twitter'
|
||||
};
|
||||
|
||||
await service.emails.notifyFreeMemberSignup({member, attribution}, options);
|
||||
|
||||
mailStub.calledOnce.should.be.true();
|
||||
testCommonMailData(stubs);
|
||||
getEmailAlertUsersStub.calledWith('free-signup').should.be.true();
|
||||
|
||||
mailStub.calledWith(
|
||||
sinon.match({subject: '🥳 Free member signup: Ghost'})
|
||||
).should.be.true();
|
||||
mailStub.calledWith(
|
||||
sinon.match.has('html', sinon.match('🥳 Free member signup: Ghost'))
|
||||
).should.be.true();
|
||||
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'))
|
||||
).should.be.true();
|
||||
});
|
||||
});
|
||||
|
||||
describe('notifyPaidSubscriptionStart', function () {
|
||||
@ -451,6 +484,21 @@ describe('StaffService', function () {
|
||||
};
|
||||
});
|
||||
|
||||
it('sends paid subscription start alert with attribution', async function () {
|
||||
const attribution = {
|
||||
referrerSource: 'Twitter'
|
||||
};
|
||||
await service.emails.notifyPaidSubscriptionStarted({member, offer: null, tier, subscription, attribution}, options);
|
||||
|
||||
mailStub.calledOnce.should.be.true();
|
||||
testCommonPaidSubMailData({...stubs, member});
|
||||
|
||||
// check attribution text
|
||||
mailStub.calledWith(
|
||||
sinon.match.has('html', sinon.match('Source: Twitter'))
|
||||
).should.be.true();
|
||||
});
|
||||
|
||||
it('sends paid subscription start alert without offer', async function () {
|
||||
await service.emails.notifyPaidSubscriptionStarted({member, offer: null, tier, subscription}, options);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user