mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-10 23:36:14 -05:00
a06064b115
refs https://github.com/TryGhost/Ghost/pull/12541 refs https://github.com/TryGhost/Ghost/pull/12689 - the analytics job had been switched to create it's own instance of EmailAnalyticsService to avoid requiring logging but the analytics extraction branch was created before this change and wasn't picked up when merging - pulled `queries` option object into a separate file for re-use - updated `fetchLatest` job to conform to extracted library interface
59 lines
2.9 KiB
JavaScript
59 lines
2.9 KiB
JavaScript
const _ = require('lodash');
|
|
const debug = require('ghost-ignition').debug('services:email-analytics');
|
|
const db = require('../../../data/db');
|
|
|
|
const MIN_EMAIL_COUNT_FOR_OPEN_RATE = 5;
|
|
|
|
module.exports = {
|
|
async shouldFetchStats() {
|
|
// don't fetch stats from Mailgun if we haven't sent any emails
|
|
const [emailCount] = await db.knex('emails').count('id as count');
|
|
return emailCount && emailCount.count > 0;
|
|
},
|
|
|
|
async getLastSeenEventTimestamp() {
|
|
const startDate = new Date();
|
|
|
|
// three separate queries is much faster than using max/greatest (with coalesce to handle nulls) across columns
|
|
const {maxDeliveredAt} = await db.knex('email_recipients').select(db.knex.raw('MAX(delivered_at) as maxDeliveredAt')).first() || {};
|
|
const {maxOpenedAt} = await db.knex('email_recipients').select(db.knex.raw('MAX(opened_at) as maxOpenedAt')).first() || {};
|
|
const {maxFailedAt} = await db.knex('email_recipients').select(db.knex.raw('MAX(failed_at) as maxFailedAt')).first() || {};
|
|
|
|
const lastSeenEventTimestamp = _.max([maxDeliveredAt, maxOpenedAt, maxFailedAt]);
|
|
debug(`getLastSeenEventTimestamp: finished in ${Date.now() - startDate}ms`);
|
|
|
|
return lastSeenEventTimestamp;
|
|
},
|
|
|
|
async aggregateEmailStats(emailId) {
|
|
await db.knex('emails').update({
|
|
delivered_count: db.knex.raw(`(SELECT COUNT(id) FROM email_recipients WHERE email_id = ? AND delivered_at IS NOT NULL)`, [emailId]),
|
|
opened_count: db.knex.raw(`(SELECT COUNT(id) FROM email_recipients WHERE email_id = ? AND opened_at IS NOT NULL)`, [emailId]),
|
|
failed_count: db.knex.raw(`(SELECT COUNT(id) FROM email_recipients WHERE email_id = ? AND failed_at IS NOT NULL)`, [emailId])
|
|
}).where('id', emailId);
|
|
},
|
|
|
|
async aggregateMemberStats(memberId) {
|
|
const {trackedEmailCount} = await db.knex('email_recipients')
|
|
.select(db.knex.raw('COUNT(email_recipients.id) as trackedEmailCount'))
|
|
.leftJoin('emails', 'email_recipients.email_id', 'emails.id')
|
|
.where('email_recipients.member_id', memberId)
|
|
.where('emails.track_opens', true)
|
|
.first() || {};
|
|
|
|
const updateQuery = {
|
|
email_count: db.knex.raw('(SELECT COUNT(id) FROM email_recipients WHERE member_id = ?)', [memberId]),
|
|
email_opened_count: db.knex.raw('(SELECT COUNT(id) FROM email_recipients WHERE member_id = ? AND opened_at IS NOT NULL)', [memberId])
|
|
};
|
|
|
|
if (trackedEmailCount >= MIN_EMAIL_COUNT_FOR_OPEN_RATE) {
|
|
updateQuery.email_open_rate = db.knex.raw(`
|
|
ROUND(((SELECT COUNT(id) FROM email_recipients WHERE member_id = ? AND opened_at IS NOT NULL) * 1.0 / ? * 100), 0)
|
|
`, [memberId, trackedEmailCount]);
|
|
}
|
|
|
|
await db.knex('members')
|
|
.update(updateQuery)
|
|
.where('id', memberId);
|
|
}
|
|
};
|