From e3347827ca7395828ec41eb017a031513189f4e5 Mon Sep 17 00:00:00 2001 From: Simon Backx Date: Thu, 14 Sep 2023 14:30:05 +0200 Subject: [PATCH] Added sending of events when clicking or subscribing to a recommendation fixes https://github.com/TryGhost/Product/issues/3855 --- apps/portal/src/actions.js | 20 +++++++++++++++++- .../components/pages/RecommendationsPage.js | 21 ++++++++++++++++--- apps/portal/src/utils/api.js | 12 +++++++++++ 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/apps/portal/src/actions.js b/apps/portal/src/actions.js index 6d35cd2074..df96cd95e8 100644 --- a/apps/portal/src/actions.js +++ b/apps/portal/src/actions.js @@ -501,6 +501,22 @@ async function oneClickSubscribe({data: {siteUrl}, state}) { return {}; } +function trackRecommendationClicked({data: {recommendationId}, api}) { + api.recommendations.trackClicked({ + recommendationId + }); + + return {}; +} + +async function trackRecommendationSubscribed({data: {recommendationId}, api}) { + api.recommendations.trackSubscribed({ + recommendationId + }); + + return {}; +} + const Actions = { togglePopup, openPopup, @@ -524,7 +540,9 @@ const Actions = { updateNewsletterPreference, showPopupNotification, removeEmailFromSuppressionList, - oneClickSubscribe + oneClickSubscribe, + trackRecommendationClicked, + trackRecommendationSubscribed }; /** Handle actions in the App, returns updated state */ diff --git a/apps/portal/src/components/pages/RecommendationsPage.js b/apps/portal/src/components/pages/RecommendationsPage.js index 18093ffc50..5b58c3f691 100644 --- a/apps/portal/src/components/pages/RecommendationsPage.js +++ b/apps/portal/src/components/pages/RecommendationsPage.js @@ -74,7 +74,7 @@ export const RecommendationsPageStyles = ` .gh-portal-recommendation-item .gh-portal-list-detail:hover .gh-portal-recommendation-arrow-icon { opacity: 0.8; } - + .gh-portal-recommendation-subscribed { display: flex; align-items: center; @@ -155,6 +155,7 @@ const RecommendationItem = (recommendation) => { const {title, url, reason, favicon, one_click_subscribe: oneClickSubscribe, featured_image: featuredImage} = recommendation; const allowOneClickSubscribe = member && oneClickSubscribe; const [subscribed, setSubscribed] = useState(false); + const [clicked, setClicked] = useState(false); const [loading, setLoading] = useState(false); const outboundLinkTagging = site.outbound_link_tagging ?? false; @@ -179,7 +180,12 @@ const RecommendationItem = (recommendation) => { const visitHandler = useCallback(() => { // Open url in a new tab openTab(refUrl); - }, [refUrl]); + + if (!clicked) { + onAction('trackRecommendationClicked', {recommendationId: recommendation.id}); + setClicked(true); + } + }, [refUrl, recommendation.id, clicked]); const oneClickSubscribeHandler = useCallback(async () => { try { @@ -188,6 +194,10 @@ const RecommendationItem = (recommendation) => { siteUrl: url, throwErrors: true }); + if (!clicked) { + onAction('trackRecommendationSubscribed', {recommendationId: recommendation.id}); + setClicked(true); + } setSubscribed(true); } catch (_) { // Open portal signup page @@ -195,9 +205,14 @@ const RecommendationItem = (recommendation) => { // Trigger a visit openTab(signupUrl); + + if (!clicked) { + onAction('trackRecommendationClicked', {recommendationId: recommendation.id}); + setClicked(true); + } } setLoading(false); - }, [setSubscribed, url, refUrl]); + }, [setSubscribed, url, refUrl, recommendation.id, clicked]); const clickHandler = useCallback((e) => { if (loading) { diff --git a/apps/portal/src/utils/api.js b/apps/portal/src/utils/api.js index 346d3657f8..50c9b5d49b 100644 --- a/apps/portal/src/utils/api.js +++ b/apps/portal/src/utils/api.js @@ -163,6 +163,18 @@ function setupGhostApi({siteUrl = window.location.origin, apiUrl, apiKey}) { } }; + api.recommendations = { + trackClicked({recommendationId}) { + let url = endpointFor({type: 'members', resource: 'recommendations/' + recommendationId + '/clicked'}); + navigator.sendBeacon(url); + }, + + trackSubscribed({recommendationId}) { + let url = endpointFor({type: 'members', resource: 'recommendations/' + recommendationId + '/subscribed'}); + navigator.sendBeacon(url); + } + }; + api.member = { identity() { const url = endpointFor({type: 'members', resource: 'session'});