From ebbde4a66b8f72552ba45af333bd132ac09b614e Mon Sep 17 00:00:00 2001 From: Drew Blaisdell Date: Fri, 29 Jan 2016 14:59:01 -0800 Subject: [PATCH] Plans: A/B test displaying a feature list vs. description in `Plan` Fixes #2752. --- .../components/plans/plan-actions/index.jsx | 5 +- client/components/plans/plan/index.jsx | 29 +++++- client/components/plans/plan/style.scss | 22 +++-- client/lib/abtest/active-tests.js | 8 ++ client/lib/features-list/test-features.js | 95 +++++++++++++++++++ 5 files changed, 149 insertions(+), 10 deletions(-) create mode 100644 client/lib/features-list/test-features.js diff --git a/client/components/plans/plan-actions/index.jsx b/client/components/plans/plan-actions/index.jsx index 2150da89de630..3e7b04df55bd9 100644 --- a/client/components/plans/plan-actions/index.jsx +++ b/client/components/plans/plan-actions/index.jsx @@ -7,7 +7,8 @@ var React = require( 'react' ), /** * Internal dependencies */ -var analytics = require( 'analytics' ), +var abtest = require( 'lib/abtest' ).abtest, + analytics = require( 'analytics' ), config = require( 'config' ), productsValues = require( 'lib/products-values' ), isFreePlan = productsValues.isFreePlan, @@ -253,7 +254,7 @@ module.exports = React.createClass( { }, freePlanExpiration: function() { - if ( ! this.planHasCost() ) { + if ( ! this.planHasCost() && abtest( 'plansFeatureList' ) !== 'list' ) { return ( { this.translate( 'Never expires', { context: 'Expiration info for free plan in /plans/' } ) } ); diff --git a/client/components/plans/plan/index.jsx b/client/components/plans/plan/index.jsx index 0c664f8ea4511..d74d6f47aa281 100644 --- a/client/components/plans/plan/index.jsx +++ b/client/components/plans/plan/index.jsx @@ -8,7 +8,9 @@ var React = require( 'react' ), /** * Internal dependencies */ -var analytics = require( 'analytics' ), +var abtest = require( 'lib/abtest' ).abtest, + analytics = require( 'analytics' ), + testFeatures = require( 'lib/features-list/test-features' ), Gridicon = require( 'components/gridicon' ), PlanActions = require( 'components/plans/plan-actions' ), PlanHeader = require( 'components/plans/plan-header' ), @@ -60,6 +62,29 @@ module.exports = React.createClass( { ); }, + getFeatureList: function() { + var features; + + if ( this.isPlaceholder() ) { + return; + } + + features = testFeatures[ this.props.plan.product_slug ].map( function( feature, i ) { + var classes = classNames( 'plan__feature', { + 'is-plan-specific': feature.planSpecific + } ); + + return ( +
  • + + { feature.text } +
  • + ); + } ); + + return ; + }, + showDetails: function() { if ( 'function' === typeof ( this.props.onOpen ) ) { this.props.onOpen( this.props.plan.product_id ); @@ -205,7 +230,7 @@ module.exports = React.createClass( {
    - { this.getDescription() } + { abtest( 'plansFeatureList' ) === 'list' ? this.getFeatureList() : this.getDescription() }
    { this.getPlanActions() }
    diff --git a/client/components/plans/plan/style.scss b/client/components/plans/plan/style.scss index 0e760cbec6fc7..fdebe86808001 100644 --- a/client/components/plans/plan/style.scss +++ b/client/components/plans/plan/style.scss @@ -59,13 +59,8 @@ li { font-size: 13px; - padding: 3px 0; + padding: 5px 0 5px 14px; opacity: .8; - - &:before { - @include noticon( '\f418', 16px ); - vertical-align: middle; - } } } @@ -154,3 +149,18 @@ @include plans-in-three-columns(); } } + +.plan__feature { + padding-left: 10px; + + &.is-plan-specific { + font-weight: bold; + } +} + +.plan__features .gridicon { + margin-left: -12px; + position: relative; + left: -5px; + top: 2px; +} diff --git a/client/lib/abtest/active-tests.js b/client/lib/abtest/active-tests.js index 069323b092186..4fcd25e6e6819 100644 --- a/client/lib/abtest/active-tests.js +++ b/client/lib/abtest/active-tests.js @@ -77,4 +77,12 @@ module.exports = { }, defaultVariation: 'add' }, + plansFeatureList: { + datestamp: '20040202', + variations: { + list: 50, + description: 50 + }, + defaultVariation: 'description' + } }; diff --git a/client/lib/features-list/test-features.js b/client/lib/features-list/test-features.js new file mode 100644 index 0000000000000..71401377d83b3 --- /dev/null +++ b/client/lib/features-list/test-features.js @@ -0,0 +1,95 @@ +/** + * A list of features to a/b test on the `Plans` component. + * NOTE: If this test variation becomes the default, these will need to + * be translated and returned by the API. + */ +const features = { + free_plan: [ + { + text: 'A WordPress.com Site loaded with powerful features', + planSpecific: false + }, + { + text: '3GB Storage Space', + planSpecific: false + }, + { + text: 'Support from the WordPress.com community', + planSpecific: false + }, + ], + value_bundle: [ + { + text: 'A WordPress.com Site', + planSpecific: false + }, + { + text: '13GB Storage Space', + planSpecific: true + }, + { + text: 'Custom Site Address', + planSpecific: true + }, + { + text: 'No Ads', + planSpecific: true + }, + { + text: 'Custom Design', + planSpecific: true + }, + { + text: 'Video Hosting & Storage', + planSpecific: true + }, + { + text: 'Direct Email Support', + planSpecific: true + }, + ], + 'business-bundle': [ + { + text: 'A WordPress.com Site', + planSpecific: false + }, + { + text: 'Unlimited Storage Space', + planSpecific: true + }, + { + text: 'Custom Site Address', + planSpecific: false + }, + { + text: 'No Ads', + planSpecific: false + }, + { + text: 'Custom Design', + planSpecific: false + }, + { + text: 'Video Hosting & Storage', + planSpecific: false + }, + { + text: 'eCommerce', + planSpecific: true + }, + { + text: 'Unlimited Premium Themes', + planSpecific: true + }, + { + text: 'Google Analytics', + planSpecific: true + }, + { + text: 'Live Chat Support', + planSpecific: true + }, + ] +}; + +export default features;