From f79f5471b4d3f635f1800b790128335dcb6e9282 Mon Sep 17 00:00:00 2001 From: Hannah Wolfe Date: Thu, 29 Aug 2024 21:40:41 +0100 Subject: [PATCH] Added stats tracker script to ghost head (#20881) closes https://linear.app/tryghost/issue/ANAL-9/initial-tracker-in-ghost-head - Given that all of the correct config is in place, output a tracking script - This allows us to send pageview events into tinybird - All of the details (location of the script, destination etc) are kept in config so that it's easy to change for different environments --- .../core/core/frontend/helpers/ghost_head.js | 19 ++ .../__snapshots__/ghost_head.test.js.snap | 256 +++++++++++++++++- .../unit/frontend/helpers/ghost_head.test.js | 89 ++++++ 3 files changed, 357 insertions(+), 7 deletions(-) diff --git a/ghost/core/core/frontend/helpers/ghost_head.js b/ghost/core/core/frontend/helpers/ghost_head.js index 09904905ce..9661145e09 100644 --- a/ghost/core/core/frontend/helpers/ghost_head.js +++ b/ghost/core/core/frontend/helpers/ghost_head.js @@ -141,6 +141,21 @@ function getWebmentionDiscoveryLink() { } } +function getTinybirdTrackerScript(dataRoot) { + const scriptUrl = config.get('tinybird:tracker:scriptUrl'); + const endpoint = config.get('tinybird:tracker:endpoint'); + const token = config.get('tinybird:tracker:token'); + + const tbParams = _.map({ + site_uuid: config.get('tinybird:tracker:id'), + post_uuid: dataRoot.post?.uuid, + member_uuid: dataRoot.member?.uuid, + member_status: dataRoot.member?.status + }, (value, key) => `tb_${key}="${value}"`).join(' '); + + return ``; +} + /** * **NOTE** * Express adds `_locals`, see https://github.com/expressjs/express/blob/4.15.4/lib/response.js#L962. @@ -319,6 +334,10 @@ module.exports = async function ghost_head(options) { // eslint-disable-line cam if (!_.isEmpty(tagCodeInjection)) { head.push(tagCodeInjection); } + + if (config.get('tinybird') && config.get('tinybird:tracker') && config.get('tinybird:tracker:scriptUrl')) { + head.push(getTinybirdTrackerScript(dataRoot)); + } } debug('end'); diff --git a/ghost/core/test/unit/frontend/helpers/__snapshots__/ghost_head.test.js.snap b/ghost/core/test/unit/frontend/helpers/__snapshots__/ghost_head.test.js.snap index d38ac6af6e..b9bd03697e 100644 --- a/ghost/core/test/unit/frontend/helpers/__snapshots__/ghost_head.test.js.snap +++ b/ghost/core/test/unit/frontend/helpers/__snapshots__/ghost_head.test.js.snap @@ -457,7 +457,7 @@ Object { "string": " - + @@ -469,7 +469,7 @@ Object { - + ", } `; @@ -959,6 +959,248 @@ Object { } `; +exports[`{{ghost_head}} helper includes tinybird tracker script when config is set Sets tb_post_uuid on post page 1 1`] = ` +Object { + "rendered": " + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ", +} +`; + +exports[`{{ghost_head}} helper includes tinybird tracker script when config is set sets both tb_member_x variables and tb_post_uuid on logged in post page 1 1`] = ` +Object { + "rendered": " + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ", +} +`; + +exports[`{{ghost_head}} helper includes tinybird tracker script when config is set sets tb_member_x variables on logged in home page 1 1`] = ` +Object { + "rendered": " + + + + + + + + + + + + + + + + + + + + + + + + ", +} +`; + +exports[`{{ghost_head}} helper includes tinybird tracker script when config is set with all tb_variables set to undefined on logged out home page 1 1`] = ` +Object { + "rendered": " + + + + + + + + + + + + + + + + + + + + + + + + ", +} +`; + exports[`{{ghost_head}} helper members scripts includes portal when members enabled 1 1`] = ` Object { "rendered": " diff --git a/ghost/core/test/unit/frontend/helpers/ghost_head.test.js b/ghost/core/test/unit/frontend/helpers/ghost_head.test.js index 2d07430fd7..2241abb0a9 100644 --- a/ghost/core/test/unit/frontend/helpers/ghost_head.test.js +++ b/ghost/core/test/unit/frontend/helpers/ghost_head.test.js @@ -340,6 +340,19 @@ describe('{{ghost_head}} helper', function () { published_at: new Date(0), updated_at: new Date(0) })); + + posts.push(createPost({ // Post 10 + title: 'Testing stats', + uuid: 'post_uuid', + excerpt: 'Creating stats for the site', + mobiledoc: testUtils.DataGenerator.markdownToMobiledoc('Creating stats for the site'), + authors: [ + authors[3] + ], + primary_author: authors[3], + published_at: new Date(0), + updated_at: new Date(0) + })); }; before(function () { @@ -1185,4 +1198,80 @@ describe('{{ghost_head}} helper', function () { })); }); }); + + describe('includes tinybird tracker script when config is set', function () { + beforeEach(function () { + configUtils.set({ + tinybird: { + tracker: { + scriptUrl: 'https://unpkg.com/@tinybirdco/flock.js', + endpoint: 'https://api.tinybird.co', + token: 'tinybird_token', + id: 'tb_test_site_uuid' + } + } + }); + }); + it('with all tb_variables set to undefined on logged out home page', async function () { + await testGhostHead(testUtils.createHbsResponse({ + locals: { + relativeUrl: '/', + context: ['home', 'index'], + safeVersion: '4.3' + } + })); + }); + + it('Sets tb_post_uuid on post page', async function () { + const renderObject = { + post: posts[10] + }; + + await testGhostHead(testUtils.createHbsResponse({ + renderObject: renderObject, + locals: { + relativeUrl: '/post/', + context: ['post'], + safeVersion: '0.3' + } + })); + }); + + it('sets tb_member_x variables on logged in home page', async function () { + const renderObject = { + member: { + uuid: 'member_uuid', + status: 'paid' + } + }; + + await testGhostHead(testUtils.createHbsResponse({ + renderObject: renderObject, + locals: { + relativeUrl: '/', + context: ['home', 'index'], + safeVersion: '4.3' + } + })); + }); + + it('sets both tb_member_x variables and tb_post_uuid on logged in post page', async function () { + const renderObject = { + member: { + uuid: 'member_uuid', + status: 'free' + }, + post: posts[10] + }; + + await testGhostHead(testUtils.createHbsResponse({ + renderObject: renderObject, + locals: { + relativeUrl: '/post/', + context: ['post'], + safeVersion: '4.3' + } + })); + }); + }); });