Added stats to 'Recommending you' table (#18292)

fixes https://github.com/TryGhost/Product/issues/3891
This commit is contained in:
Simon Backx 2023-09-22 12:31:31 +02:00 committed by GitHub
parent a04c691fa0
commit d68070db9d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 66 additions and 12 deletions

View File

@ -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<ReferrerHistoryResponseType>({
dataType,
path: '/stats/referrers/'
});

View File

@ -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}) =>
</div>
</div>
</TableCell>
{/* <TableCell className='hidden md:!visible md:!table-cell' onClick={showDetails}>
<TableCell className='hidden md:!visible md:!table-cell' onClick={showDetails}>
<div className={`flex grow flex-col`}>
If it's 0
<span className="text-grey-500">-</span>
If it's more than 0
<span>12</span>
<span className='whitespace-nowrap text-xs text-grey-700'>Subscribers gained</span>
{(signups - paidConversions) === 0 && <span className="text-grey-500">-</span>}
{(signups - paidConversions) > 0 && <><span>{signups - paidConversions}</span><span className='whitespace-nowrap text-xs text-grey-700'>free members</span></>}
</div>
</TableCell> */}
</TableCell>
{hasPaidColumn &&
<TableCell className='hidden md:!visible md:!table-cell' onClick={showDetails}>
<div className={`flex grow flex-col`}>
{paidConversions === 0 && <span className="text-grey-500">-</span>}
{paidConversions > 0 && <><span>{paidConversions}</span><span className='whitespace-nowrap text-xs text-grey-700'>paid members</span></>}
</div>
</TableCell>
}
</TableRow>
);
};
const IncomingRecommendationList: React.FC<IncomingRecommendationListProps> = ({mentions, pagination, isLoading}) => {
const IncomingRecommendationList: React.FC<IncomingRecommendationListProps> = ({mentions, stats, pagination, isLoading}) => {
if (isLoading || mentions.length) {
return <Table isLoading={isLoading} pagination={pagination}>
{mentions.map(mention => <IncomingRecommendationItem key={mention.id} mention={mention} />)}
{mentions.map(mention => <IncomingRecommendationItem key={mention.id} mention={mention} stats={stats} />)}
</Table>;
} else {
return <NoValueLabel icon='thumbs-up'>

View File

@ -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 (<IncomingRecommendationList isLoading={isLoading} mentions={mentions ?? []} pagination={pagination}/>);
// Also fetch sources
const {data: {stats} = {}, isLoading: areSourcesLoading} = useReferrerHistory({});
return (<IncomingRecommendationList isLoading={isLoading || areSourcesLoading} mentions={mentions ?? []} pagination={pagination} stats={stats ?? []}/>);
};
export default IncomingRecommendations;