Skip to content

Commit

Permalink
Add new paid stats site features: STATS_FREE, STATS_COMMERCIAL (#97041)
Browse files Browse the repository at this point in the history
* Add new stats features handling

* Paid stats shouldn't gate traffic/insight pages

* Add Basic stats

* Gate granular controls for basic stats too

* Logic error on how paidStats array now works

* Document more and make breakdown easier to follow

* Fix tests

* Handle deployment order using v3 flag

* Ensure premium plan stats aren't upselling premium plans
  • Loading branch information
lsl authored Dec 10, 2024
1 parent 1307772 commit fb35cb4
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 36 deletions.
5 changes: 3 additions & 2 deletions client/my-sites/stats/hooks/test/use-should-gate-stats.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { isEnabled } from '@automattic/calypso-config';
import { FEATURE_STATS_PAID } from '@automattic/calypso-products';
import { STAT_TYPE_CLICKS, STATS_TYPE_DEVICE_STATS } from '../../constants';
import { shouldGateStats } from '../use-should-gate-stats';

jest.mock( '@automattic/calypso-config', () => {
Expand All @@ -9,9 +10,9 @@ jest.mock( '@automattic/calypso-config', () => {
} );

const siteId = 123;
const gatedStatType = 'statsSearchTerms';
const gatedStatType = STAT_TYPE_CLICKS;
const notGatedStatType = 'notGatedStatType';
const jetpackStatsAdvancedStatType = 'stats_devices_module';
const jetpackStatsAdvancedStatType = STATS_TYPE_DEVICE_STATS;

describe( 'shouldGateStats in Calypso', () => {
beforeAll( () => {
Expand Down
107 changes: 90 additions & 17 deletions client/my-sites/stats/hooks/use-should-gate-stats.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { FEATURE_STATS_PAID } from '@automattic/calypso-products';
import { isEnabled } from '@automattic/calypso-config';
import {
FEATURE_STATS_FREE,
FEATURE_STATS_PAID,
FEATURE_STATS_COMMERCIAL,
FEATURE_STATS_BASIC,
} from '@automattic/calypso-products';
import { useSelector } from 'calypso/state';
import getSiteFeatures from 'calypso/state/selectors/get-site-features';
import isAtomicSite from 'calypso/state/selectors/is-site-wpcom-atomic';
Expand Down Expand Up @@ -79,23 +85,18 @@ const granularControlForJetpackStatsCommercialPaywall = [
STATS_FEATURE_DOWNLOAD_CSV,
];

// Gated modules for WPCOM sites without the FEATURE_STATS_PAID feature.
const paidStats = [
STAT_TYPE_REFERRERS,
STAT_TYPE_CLICKS,
// wpcom: All stats are gated for WPCOM sites without the STATS_FREE, STATS_BASIC, STATS_PAID or STATS_COMMERCIAL feature.
const gatedStats = [
// Commercial stats
STAT_TYPE_TOP_AUTHORS,
STAT_TYPE_SEARCH_TERMS,
STAT_TYPE_VIDEO_PLAYS,

// Paid stats is currently a premium plan feature.
// Legacy sites will inadvertantly get these temporarily but paywalling
// these again later is fine. (https://github.com/Automattic/wp-calypso/pull/97041)
STATS_TYPE_DEVICE_STATS,
STATS_FEATURE_UTM_STATS,
];
STATS_TYPE_DEVICE_STATS,

// Gated controls for WPCOM sites without the FEATURE_STATS_PAID feature.
const granularControlForPaidStats = [
// Paid Stats
STAT_TYPE_REFERRERS,
STAT_TYPE_CLICKS,
STATS_FEATURE_DATE_CONTROL,
STATS_FEATURE_DATE_CONTROL_LAST_30_DAYS,
STATS_FEATURE_DATE_CONTROL_LAST_90_DAYS,
Expand All @@ -108,10 +109,55 @@ const granularControlForPaidStats = [
STATS_FEATURE_SUMMARY_LINKS_QUARTER,
STATS_FEATURE_SUMMARY_LINKS_YEAR,
STATS_FEATURE_SUMMARY_LINKS_ALL,

// Traffic and insights pages (page level upsell)
STATS_FEATURE_PAGE_INSIGHTS,
STATS_FEATURE_PAGE_TRAFFIC,
];

// wpcom: Gate UTM and device stats for sites with STATS_FREE feature, this is the feature applied to legacy sites.
const freeStats = [
// New Commercial stats are the only thing we gate for legacy sites.
STATS_FEATURE_UTM_STATS,
STATS_TYPE_DEVICE_STATS,
];

// wpcom: Gate UTM and device stats for sites with STATS_BASIC feature, this is the feature applied to legacy sites.
const basicStats = [
// Commercial stats
STAT_TYPE_TOP_AUTHORS,
STAT_TYPE_SEARCH_TERMS,
STAT_TYPE_VIDEO_PLAYS,
STATS_FEATURE_UTM_STATS,
STATS_TYPE_DEVICE_STATS,

// Paid stats
STAT_TYPE_REFERRERS,
STAT_TYPE_CLICKS,
STATS_FEATURE_DATE_CONTROL,
STATS_FEATURE_DATE_CONTROL_LAST_30_DAYS,
STATS_FEATURE_DATE_CONTROL_LAST_90_DAYS,
STATS_FEATURE_DATE_CONTROL_LAST_YEAR,
STATS_FEATURE_DATE_CONTROL_CUSTOM_DATE_RANGE,
STATS_FEATURE_DOWNLOAD_CSV,
STATS_FEATURE_INTERVAL_DROPDOWN_WEEK,
STATS_FEATURE_INTERVAL_DROPDOWN_MONTH,
STATS_FEATURE_INTERVAL_DROPDOWN_YEAR,
STATS_FEATURE_SUMMARY_LINKS_QUARTER,
STATS_FEATURE_SUMMARY_LINKS_YEAR,
STATS_FEATURE_SUMMARY_LINKS_ALL,
];

// wpcom: Gated modules for WPCOM sites with the FEATURE_STATS_PAID feature.
export const paidStats = [
// Commercial stats
STAT_TYPE_TOP_AUTHORS,
STAT_TYPE_SEARCH_TERMS,
STAT_TYPE_VIDEO_PLAYS,
STATS_TYPE_DEVICE_STATS,
STATS_FEATURE_UTM_STATS,
];

/*
* Check if a site can access a specific module or card based on the WPCOM plan or Jetpack Stats product purchase.
*
Expand Down Expand Up @@ -172,15 +218,42 @@ export const shouldGateStats = ( state: object, siteId: number | null, statType:
}

const siteFeatures = getSiteFeatures( state, siteId );
const siteHasCommercialStats = siteHasFeature( state, siteId, FEATURE_STATS_COMMERCIAL );
const siteHasFreeStats = siteHasFeature( state, siteId, FEATURE_STATS_FREE );
const siteHasPaidStats = siteHasFeature( state, siteId, FEATURE_STATS_PAID );
const siteHasBasicStats = siteHasFeature( state, siteId, FEATURE_STATS_BASIC );

// Check if the site features have loaded and the site has the FEATURE_STATS_PAID feature.
if ( ! siteFeatures || siteHasPaidStats ) {
// Check if the site features have loaded.
if ( ! siteFeatures ) {
return false;
}

// Sites cannot access the feature FEATURE_STATS_PAID, gate stats accordingly
return [ ...paidStats, ...granularControlForPaidStats ].includes( statType );
// Commercial stats has no paywall.
if ( siteHasCommercialStats ) {
return false;
}

// Legacy free stats given to all sites before 2024-01-09.
if ( siteHasFreeStats ) {
return freeStats.includes( statType );
}

// Paid stats given to personal and higher plans
if ( siteHasPaidStats ) {
if ( ! isEnabled( 'stats/paid-wpcom-v3' ) ) {
// if v3 is not enabled, treat paid stats as commercial stats
return false;
}
return paidStats.includes( statType );
}

// Basic stats given to free sites before 2024-12-06.
if ( siteHasBasicStats ) {
return basicStats.includes( statType );
}

// All other sites get gated to 7 days + paywall upsell
return gatedStats.includes( statType );
};

/*
Expand Down
18 changes: 2 additions & 16 deletions client/my-sites/stats/stat-type-to-plan.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,14 @@
import config from '@automattic/calypso-config';
import { PLAN_PERSONAL, PLAN_PREMIUM } from '@automattic/calypso-products';
import {
STATS_TYPE_DEVICE_STATS,
STATS_FEATURE_UTM_STATS,
STAT_TYPE_SEARCH_TERMS,
STAT_TYPE_VIDEO_PLAYS,
STAT_TYPE_TOP_AUTHORS,
} from './constants';
import { paidStats } from './hooks/use-should-gate-stats';

export function statTypeToPlan( statType: string ) {
if ( ! config.isEnabled( 'stats/paid-wpcom-v3' ) ) {
return PLAN_PREMIUM;
}

// Commercial stats features that require the premium plan
if (
[
STAT_TYPE_TOP_AUTHORS,
STAT_TYPE_SEARCH_TERMS,
STAT_TYPE_VIDEO_PLAYS,
STATS_FEATURE_UTM_STATS,
STATS_TYPE_DEVICE_STATS,
].includes( statType )
) {
if ( paidStats.includes( statType ) ) {
return PLAN_PREMIUM;
}

Expand Down
3 changes: 2 additions & 1 deletion packages/calypso-products/src/constants/features.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ export const FEATURE_WOOP = 'woop';
export const FEATURE_PREMIUM_THEMES = 'premium-themes-v3';
export const FEATURE_STATS_PAID = 'stats-paid';
export const FEATURE_STATS_FREE = 'stats-free';

export const FEATURE_STATS_COMMERCIAL = 'stats-commercial';
export const FEATURE_STATS_BASIC = 'stats-basic';
// Jetpack features constants
export const FEATURE_BLANK = 'blank-feature';
export const FEATURE_STANDARD_SECURITY_TOOLS = 'standard-security-tools';
Expand Down

0 comments on commit fb35cb4

Please sign in to comment.