0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-01-20 22:42:53 -05:00

Added signup & conversion counts to Posts API

refs https://github.com/TryGhost/Team/issues/1822

Exposing the values through the API is restricted behind the alpha flag.
We're exposing the values by default when the flag is enabled for now,
but can reconsider that later.
This commit is contained in:
Fabien "egg" O'Carroll 2022-08-18 12:23:20 -04:00 committed by Fabien 'egg' O'Carroll
parent 0169487745
commit 20726c8fc2
7 changed files with 49 additions and 2 deletions

View file

@ -2,7 +2,16 @@ const models = require('../../models');
const tpl = require('@tryghost/tpl');
const errors = require('@tryghost/errors');
const getPostServiceInstance = require('../../services/posts/posts-service');
const allowedIncludes = ['tags', 'authors', 'authors.roles', 'email', 'tiers', 'newsletter'];
const allowedIncludes = [
'tags',
'authors',
'authors.roles',
'email',
'tiers',
'newsletter',
'count.signups',
'count.conversions'
];
const unsafeAttrs = ['status', 'authors', 'visibility'];
const messages = {

View file

@ -23,7 +23,7 @@ function defaultRelations(frame) {
return false;
}
frame.options.withRelated = ['tags', 'authors', 'authors.roles', 'email', 'tiers', 'newsletter'];
frame.options.withRelated = ['tags', 'authors', 'authors.roles', 'email', 'tiers', 'newsletter', 'count.signups', 'count.conversions'];
}
function setDefaultOrder(frame) {

View file

@ -10,6 +10,7 @@ const extraAttrs = require('../utils/extra-attrs');
const gating = require('../utils/post-gating');
const url = require('../utils/url');
const labs = require('../../../../../../../shared/labs');
const utils = require('../../../index');
const postsMetaSchema = require('../../../../../../data/schema').tables.posts_meta;
@ -109,5 +110,9 @@ module.exports = async (model, frame, options = {}) => {
});
}
if (!labs.isSet('memberAttribution')) {
delete jsonModel.count;
}
return jsonModel;
};

View file

@ -1249,6 +1249,27 @@ Post = ghostBookshelf.Model.extend({
return Promise.reject(new errors.NoPermissionError({
message: tpl(messages.notEnoughPermission)
}));
},
countRelations() {
return {
signups(modelOrCollection) {
modelOrCollection.query('columns', 'posts.*', (qb) => {
qb.count('member_created_events.id')
.from('member_created_events')
.whereRaw('posts.id = member_created_events.source_id')
.as('count__signups');
});
},
conversions(modelOrCollection) {
modelOrCollection.query('columns', 'posts.*', (qb) => {
qb.count('subscription_created_events.id')
.from('subscription_created_events')
.whereRaw('posts.id = subscription_created_events.source_id')
.as('count__conversions');
});
}
};
}
});

View file

@ -10,6 +10,7 @@ const config = require('../../../core/shared/config');
const models = require('../../../core/server/models');
const localUtils = require('./utils');
const configUtils = require('../../utils/configUtils');
const mockManager = require('../../utils/e2e-framework-mock-manager');
describe('Posts API', function () {
let request;
@ -27,6 +28,7 @@ describe('Posts API', function () {
const newsletterId = testUtils.DataGenerator.Content.newsletters[0].id;
const postId = testUtils.DataGenerator.Content.posts[0].id;
await models.Post.edit({newsletter_id: newsletterId}, {id: postId});
mockManager.mockLabsDisabled('memberAttribution');
});
afterEach(function () {

View file

@ -63,6 +63,7 @@ describe('post.* events', function () {
beforeEach(function () {
webhookMockReceiver = mockManager.mockWebhookRequests();
mockManager.mockLabsDisabled('memberAttribution');
});
afterEach(function () {

View file

@ -7,6 +7,7 @@ const testUtils = require('../../../utils');
const config = require('../../../../core/shared/config');
const models = require('../../../../core/server/models');
const localUtils = require('./utils');
const mockManager = require('../../../utils/e2e-framework-mock-manager');
const defaultNewsletterSlug = testUtils.DataGenerator.Content.newsletters[0].slug;
const secondNewsletterSlug = testUtils.DataGenerator.Content.newsletters[1].slug;
@ -25,6 +26,14 @@ describe('Posts API', function () {
await localUtils.doAuth(request, 'users:extra', 'posts', 'emails', 'newsletters', 'members:newsletters');
});
beforeEach(function () {
mockManager.mockLabsDisabled('memberAttribution');
});
afterEach(function () {
mockManager.mockLabsDisabled('memberAttribution');
});
describe('Browse', function () {
it('fields & formats combined', function (done) {
request.get(localUtils.API.getApiQuery('posts/?formats=mobiledoc,html&fields=id,title'))