Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TW-755: AB-Testing for ads acceptance banner #930

Merged
merged 8 commits into from
Jul 12, 2023
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"test": "jest",
"test:coverage": "jest --coverage",
"ts": "tsc --pretty",
"lint": "eslint src",
"lint": "eslint --quiet src",
"lint:fix": "prettier \"./**/*\" --write --ignore-unknown",
"clear:lint": "rimraf node_modules/.cache/.eslintcache",
"find-deadcode": "ts-prune --error"
Expand Down
6 changes: 3 additions & 3 deletions public/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -991,9 +991,9 @@
"enable": {
"message": "enable"
},
"enableAds": {
"message": "Enable Ads"
},
"enableAds": { "message": "Enable Ads" },
"payMeForEveryAdISee": { "message": "Pay me for every ad I see" },
"noThanksIhateFreeMoney": { "message": "No thanks, I hate free money" },
"dAppsCheckmarkPrompt": {
"message": "Click on the checkmark to $action$ DApps interaction feature",
"description": "DApps = Decentralized Applications",
Expand Down
56 changes: 35 additions & 21 deletions src/app/atoms/Banner.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,52 @@
import React, { FC } from 'react';

import { TID, t } from '../../lib/i18n';
import { TestIDProps } from 'lib/analytics';
import { TID, T } from 'lib/i18n';

import { FormSecondaryButton } from './FormSecondaryButton';
import { FormSubmitButton } from './FormSubmitButton';

interface Props {
text: string;
title: string;
description: string;
onEnable?: EmptyFn;
onDisable?: EmptyFn;
enableButtonText?: TID;
disableButtonText?: TID;
enableButton: BannerButtonProps;
disableButton: BannerButtonProps;
}

export interface BannerButtonProps extends TestIDProps {
title?: TID;
onClick: EmptyFn;
}

export const Banner: FC<Props> = ({
text,
description,
onEnable,
onDisable,
enableButtonText = 'enable',
disableButtonText = 'disable'
}) => (
export const Banner: FC<Props> = ({ title, description, enableButton, disableButton }) => (
<div className="p-3 border border-gray-300 rounded-md bg-white mx-4 sm:mx-0 mb-3">
<p className="text-sm font-medium text-gray-900 mb-1">{text}</p>
<h5 className="text-sm font-medium text-gray-900 mb-1 whitespace-pre-line">{title}</h5>

<p className="text-xs font-normal text-gray-700 mb-4">{description}</p>
<p className="text-xs font-normal text-gray-700 mb-4 whitespace-pre-line">{description}</p>

<div className="flex justify-between">
<FormSecondaryButton small className="flex-1 mr-4 h-2.25 rounded-md" type="button" onClick={onDisable}>
<span className="capitalize text-base text-center w-full">{t(disableButtonText)}</span>
<div className="flex flex-wrap gap-x-4 gap-y-2">
<FormSecondaryButton
small
className="flex-1 h-2.25 rounded-md"
onClick={disableButton.onClick}
testID={disableButton.testID}
testIDProperties={disableButton.testIDProperties}
>
<span className="capitalize text-base text-center w-full whitespace-pre">
<T id={disableButton.title ?? 'disable'} />
</span>
</FormSecondaryButton>

<FormSubmitButton small className="flex-1 h-2.25 rounded-md" onClick={onEnable}>
<span className="capitalize text-base text-center w-full whitespace-nowrap">{t(enableButtonText)}</span>
<FormSubmitButton
small
className="flex-1 h-2.25 rounded-md"
onClick={enableButton.onClick}
testID={enableButton.testID}
testIDProperties={enableButton.testIDProperties}
>
<span className="capitalize text-base text-center w-full whitespace-pre">
<T id={enableButton.title ?? 'enable'} />
</span>
</FormSubmitButton>
</div>
</div>
Expand Down
97 changes: 97 additions & 0 deletions src/app/pages/Home/OtherComponents/Tokens/AcceptAdsBanner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import React, { FC, useCallback, useMemo } from 'react';

import { useDispatch } from 'react-redux';

import ABContainer from 'app/atoms/ABContainer';
import { Banner, BannerButtonProps } from 'app/atoms/Banner';
import { togglePartnersPromotionAction } from 'app/store/partners-promotion/actions';
import { setAdsBannerVisibilityAction } from 'app/store/settings/actions';

export const AcceptAdsBanner: FC = () => {
const dispatch = useDispatch();

const onEnableButtonClick = useCallback(() => {
dispatch(togglePartnersPromotionAction(true));
dispatch(setAdsBannerVisibilityAction(false));
}, [dispatch]);

const onDisableButtonClick = useCallback(() => {
dispatch(togglePartnersPromotionAction(false));
dispatch(setAdsBannerVisibilityAction(false));
}, [dispatch]);

return (
<ABContainer
groupAComponent={
<AcceptAdsBannerForTestGroupA
onEnableButtonClick={onEnableButtonClick}
onDisableButtonClick={onDisableButtonClick}
/>
}
groupBComponent={
<AcceptAdsBannerForTestGroupB
onEnableButtonClick={onEnableButtonClick}
onDisableButtonClick={onDisableButtonClick}
/>
}
/>
);
};

interface Props {
onEnableButtonClick: EmptyFn;
onDisableButtonClick: EmptyFn;
}

const AcceptAdsBannerForTestGroupA: FC<Props> = ({ onEnableButtonClick, onDisableButtonClick }) => {
const enableButton: BannerButtonProps = useMemo(
() => ({
title: 'payMeForEveryAdISee',
onClick: onEnableButtonClick
}),
[onEnableButtonClick]
);

const disableButton: BannerButtonProps = useMemo(
() => ({
title: 'noThanksIhateFreeMoney',
onClick: onDisableButtonClick
}),
[onDisableButtonClick]
);

return (
<Banner
title={`Get paid to discover exciting services and dApps!\n👀💰`}
description={`Here's the deal: share some data with us (wallet address, IP) to see the most relevant ads and we'll *pay you* a fair share monthly. By doing so, you support the developers of Temple Wallet. Change your mind? Easily disable sharing in settings.\n\nStart earning now!`}
alex-tsx marked this conversation as resolved.
Show resolved Hide resolved
enableButton={enableButton}
disableButton={disableButton}
/>
);
};

const AcceptAdsBannerForTestGroupB: FC<Props> = ({ onEnableButtonClick, onDisableButtonClick }) => {
const enableButton: BannerButtonProps = useMemo(
() => ({
title: 'enableAds',
onClick: onEnableButtonClick
}),
[onEnableButtonClick]
);

const disableButton: BannerButtonProps = useMemo(
() => ({
onClick: onDisableButtonClick
}),
[onDisableButtonClick]
);

return (
<Banner
title="Earn by viewing ads in Temple Wallet"
description="Support the development team and earn tokens by viewing ads inside the wallet. To enable this feature, we request your permission to trace your Wallet Address and IP address. You can always disable ads in the settings."
enableButton={enableButton}
disableButton={disableButton}
/>
);
};
39 changes: 8 additions & 31 deletions src/app/pages/Home/OtherComponents/Tokens/Tokens.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import { useAppEnv } from 'app/env';
import { useBalancesWithDecimals } from 'app/hooks/use-balances-with-decimals.hook';
import { ReactComponent as AddToListIcon } from 'app/icons/add-to-list.svg';
import { ReactComponent as SearchIcon } from 'app/icons/search.svg';
import { loadPartnersPromoAction, togglePartnersPromotionAction } from 'app/store/partners-promotion/actions';
import { loadPartnersPromoAction } from 'app/store/partners-promotion/actions';
import { useShouldShowPartnersPromoSelector } from 'app/store/partners-promotion/selectors';
import { useIsEnabledAdsBannerSelector } from 'app/store/settings/selectors';
import SearchAssetField from 'app/templates/SearchAssetField';
import { OptimalPromoVariantEnum } from 'lib/apis/optimal';
import { TEMPLE_TOKEN_SLUG } from 'lib/assets';
Expand All @@ -20,11 +22,8 @@ import { useSyncTokens } from 'lib/temple/front/sync-tokens';
import { filterUnique } from 'lib/utils';
import { Link, navigate } from 'lib/woozie';

import { Banner } from '../../../../atoms/Banner';
import { useShouldShowPartnersPromoSelector } from '../../../../store/partners-promotion/selectors';
import { setAdsBannerVisibilityAction } from '../../../../store/settings/actions';
import { useIsEnabledAdsBannerSelector } from '../../../../store/settings/selectors';
import { AssetsSelectors } from '../Assets.selectors';
import { AcceptAdsBanner } from './AcceptAdsBanner';
import { ListItem } from './components/ListItem';
import { toExploreAssetLink } from './utils';

Expand Down Expand Up @@ -124,16 +123,6 @@ export const TokensTab: FC = () => {
return () => window.removeEventListener('keyup', handleKeyup);
}, [activeAssetSlug, setActiveIndex]);

const handleEnableBannerButton = async () => {
dispatch(togglePartnersPromotionAction(true));
dispatch(setAdsBannerVisibilityAction(false));
};

const handleDisableBannerButton = () => {
dispatch(togglePartnersPromotionAction(false));
dispatch(setAdsBannerVisibilityAction(false));
};

return (
<div className="w-full max-w-sm mx-auto">
<div className={classNames('mt-3', popup && 'mx-4')}>
Expand All @@ -149,14 +138,10 @@ export const TokensTab: FC = () => {
<Link
to="/manage-assets"
className={classNames(
'ml-2 flex-shrink-0',
'px-3 py-1',
'rounded overflow-hidden',
'flex items-center',
'text-gray-600 text-sm',
'flex-shrink-0 flex items-center px-3 py-1 ml-2',
'text-gray-600 text-sm rounded overflow-hidden',
'transition ease-in-out duration-200',
'hover:bg-gray-100',
'opacity-75 hover:opacity-100 focus:opacity-100'
'hover:bg-gray-100 opacity-75 hover:opacity-100 focus:opacity-100'
)}
testID={AssetsSelectors.manageButton}
>
Expand All @@ -166,15 +151,7 @@ export const TokensTab: FC = () => {
</div>
</div>

{isEnabledAdsBanner && (
<Banner
text="Earn by viewing ads in Temple Wallet"
description="Support the development team and earn tokens by viewing ads inside the wallet. To enable this feature, we request your permission to trace your Wallet Address and IP address. You can always disable ads in the settings."
enableButtonText="enableAds"
onDisable={handleDisableBannerButton}
onEnable={handleEnableBannerButton}
/>
)}
{isEnabledAdsBanner && <AcceptAdsBanner />}

{filteredAssets.length === 0 ? (
<div className="my-8 flex flex-col items-center justify-center text-gray-500">
Expand Down
Loading