diff --git a/apps/admin-x-settings/src/api/referrers.ts b/apps/admin-x-settings/src/api/referrers.ts new file mode 100644 index 0000000000..486c572d15 --- /dev/null +++ b/apps/admin-x-settings/src/api/referrers.ts @@ -0,0 +1,19 @@ +import {createQuery} from '../utils/apiRequests'; + +export type ReferrerHistoryItem = { + date: string, + signups: number, + source: string|null, + paid_conversions: number +}; + +export interface ReferrerHistoryResponseType { + stats: ReferrerHistoryItem[]; +} + +const dataType = 'ReferrerHistoryResponseType'; + +export const useReferrerHistory = createQuery({ + dataType, + path: '/stats/referrers/' +}); diff --git a/apps/admin-x-settings/src/components/settings/site/recommendations/IncomingRecommendationList.tsx b/apps/admin-x-settings/src/components/settings/site/recommendations/IncomingRecommendationList.tsx index 666bc0a876..8a0f3b8bc5 100644 --- a/apps/admin-x-settings/src/components/settings/site/recommendations/IncomingRecommendationList.tsx +++ b/apps/admin-x-settings/src/components/settings/site/recommendations/IncomingRecommendationList.tsx @@ -1,21 +1,47 @@ import NoValueLabel from '../../../../admin-x-ds/global/NoValueLabel'; -import React from 'react'; +import React, {useMemo} from 'react'; import RecommendationIcon from './RecommendationIcon'; import Table from '../../../../admin-x-ds/global/Table'; import TableCell from '../../../../admin-x-ds/global/TableCell'; import TableRow from '../../../../admin-x-ds/global/TableRow'; import {Mention} from '../../../../api/mentions'; import {PaginationData} from '../../../../hooks/usePagination'; +import {ReferrerHistoryItem} from '../../../../api/referrers'; interface IncomingRecommendationListProps { mentions: Mention[], + stats: ReferrerHistoryItem[], pagination: PaginationData, isLoading: boolean } -const IncomingRecommendationItem: React.FC<{mention: Mention}> = ({mention}) => { +const IncomingRecommendationItem: React.FC<{mention: Mention, stats: ReferrerHistoryItem[]}> = ({mention, stats}) => { const cleanedSource = mention.source.replace('/.well-known/recommendations.json', ''); + const {signups, paidConversions, hasPaidColumn} = useMemo(() => { + // Note: this should match the `getDomainFromUrl` method from OutboundLinkTagger + let cleanedDomain = cleanedSource; + try { + cleanedDomain = new URL(cleanedSource).hostname.replace(/^www\./, ''); + } catch (_) { + // Ignore invalid urls + } + + return stats.reduce((acc, stat) => { + acc.hasPaidColumn = acc.hasPaidColumn || stat.paid_conversions > 0; + if (stat.source === cleanedDomain) { + acc.signups += stat.signups; + acc.paidConversions += stat.paid_conversions; + return acc; + } + return acc; + }, { + signups: 0, + paidConversions: 0, + hasPaidColumn: false + }); + }, [stats, cleanedSource]); + const showDetails = () => { // Open url window.open(cleanedSource, '_blank'); @@ -34,23 +60,28 @@ const IncomingRecommendationItem: React.FC<{mention: Mention}> = ({mention}) => - {/* +
- If it's 0 - - - If it's more than 0 - 12 - Subscribers gained + {(signups - paidConversions) === 0 && -} + {(signups - paidConversions) > 0 && <>{signups - paidConversions}free members}
-
*/} +
+ {hasPaidColumn && + +
+ {paidConversions === 0 && -} + {paidConversions > 0 && <>{paidConversions}paid members} +
+
+ } ); }; -const IncomingRecommendationList: React.FC = ({mentions, pagination, isLoading}) => { +const IncomingRecommendationList: React.FC = ({mentions, stats, pagination, isLoading}) => { if (isLoading || mentions.length) { return - {mentions.map(mention => )} + {mentions.map(mention => )}
; } else { return diff --git a/apps/admin-x-settings/src/components/settings/site/recommendations/IncomingRecommendations.tsx b/apps/admin-x-settings/src/components/settings/site/recommendations/IncomingRecommendations.tsx index bd7b4811c6..3a47ee36cb 100644 --- a/apps/admin-x-settings/src/components/settings/site/recommendations/IncomingRecommendations.tsx +++ b/apps/admin-x-settings/src/components/settings/site/recommendations/IncomingRecommendations.tsx @@ -1,5 +1,6 @@ import IncomingRecommendationList from './IncomingRecommendationList'; import {useBrowseMentions} from '../../../../api/mentions'; +import {useReferrerHistory} from '../../../../api/referrers'; const IncomingRecommendations: React.FC = () => { const {data: {mentions} = {}, pagination, isLoading} = useBrowseMentions({ @@ -10,7 +11,10 @@ const IncomingRecommendations: React.FC = () => { } }); - return (); + // Also fetch sources + const {data: {stats} = {}, isLoading: areSourcesLoading} = useReferrerHistory({}); + + return (); }; export default IncomingRecommendations;