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

Show Ads value prop in Paid Campaign performance card #2650

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
d544759
remove free credits
kt-12 Oct 22, 2024
62d124c
add paid-features.js
kt-12 Oct 22, 2024
19ef7b1
remove translations
kt-12 Oct 22, 2024
90ea27a
e2e
kt-12 Oct 22, 2024
2a7af58
style fixes and e2e
kt-12 Oct 22, 2024
1ed56b8
fix e2e button clicking
kt-12 Oct 22, 2024
cd2521c
fix old e2e
kt-12 Oct 22, 2024
d8cb4cc
address review feedback.
kt-12 Oct 28, 2024
cd58bca
doc updated.
kt-12 Oct 28, 2024
cfa279c
Update js/src/dashboard/summary-section/paid-features/free-ad-credit.js
kt-12 Nov 1, 2024
96e4162
Update js/src/dashboard/summary-section/paid-features/free-ad-credit.js
kt-12 Nov 1, 2024
d5d1d2f
remove usage of sections, fix styling
kt-12 Nov 1, 2024
e4fa585
Merge branch 'feature/2538-performance-card-sep' of https://github.co…
kt-12 Nov 1, 2024
d043e81
remove margin
kt-12 Nov 1, 2024
b77f18e
seperate file for paid-features test
kt-12 Nov 1, 2024
cd7ec9f
fix button name
kt-12 Nov 1, 2024
6fe5003
update variable names and cleanup
kt-12 Nov 1, 2024
51d5187
cleanup
kt-12 Nov 1, 2024
ccc7edc
Merge branch 'feature/2460-google-ads-value-prop' into feature/2538-p…
kt-12 Nov 1, 2024
2d77db8
check when ads complete is set
kt-12 Nov 1, 2024
0fcba0f
change variable name
kt-12 Nov 1, 2024
38318b2
avoide flakyness
kt-12 Nov 1, 2024
2297982
change variable name
kt-12 Nov 4, 2024
f8f9c4a
remove additional assignement
kt-12 Nov 4, 2024
d7d17ad
style changes
kt-12 Nov 4, 2024
311a850
update E2E
kt-12 Nov 4, 2024
f899c31
jest update
kt-12 Nov 5, 2024
ff4376e
fix review changes.
kt-12 Nov 5, 2024
f46e880
fix jest
kt-12 Nov 5, 2024
f0ab0f6
fix unused variable
kt-12 Nov 5, 2024
9caf01d
remove only
kt-12 Nov 5, 2024
5a27b75
fix jest
kt-12 Nov 6, 2024
f8c3339
remove unnecessary typecasting.
kt-12 Nov 6, 2024
0e80569
css changes
kt-12 Nov 6, 2024
64eaab6
div -> component
kt-12 Nov 6, 2024
b0c712e
Style fixes
joemcgill Nov 7, 2024
64eb3b4
More style adjustments
joemcgill Nov 7, 2024
d1fe9eb
add new Fulfill for ad report.
kt-12 Nov 7, 2024
c7bbc72
check for text content in Summary+ mock add empty campaign.
kt-12 Nov 7, 2024
0f809f3
update variable name.
kt-12 Nov 7, 2024
c724767
remove margin
kt-12 Nov 7, 2024
1a516c7
remove size attribute.
kt-12 Nov 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion js/src/components/free-ad-credit/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

svg {
flex: 0 0 auto;
fill: #007017;
fill: $gla-color-green;
}

&__title {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import AppDocumentationLink from '.~/components/app-documentation-link';
import CampaignPreview from '.~/components/paid-ads/campaign-preview';
import FreeAdCredit from '.~/components/free-ad-credit';
import VerticalGapLayout from '.~/components/vertical-gap-layout';
import useFreeAdCredit from '.~/hooks/useFreeAdCredit';
kt-12 marked this conversation as resolved.
Show resolved Hide resolved
import './paid-ads-features-section.scss';

function FeatureList() {
Expand Down Expand Up @@ -49,8 +48,6 @@ function FeatureList() {
* for the next actions: skip or continue the paid ads setup.
*/
export default function PaidAdsFeaturesSection() {
const hasFreeAdCredit = useFreeAdCredit();

return (
<Section
className="gla-paid-ads-features-section"
Expand Down Expand Up @@ -111,8 +108,7 @@ export default function PaidAdsFeaturesSection() {
<CampaignPreview />
</FlexItem>
</Flex>

{ hasFreeAdCredit && <FreeAdCredit /> }
kt-12 marked this conversation as resolved.
Show resolved Hide resolved
<FreeAdCredit />
</VerticalGapLayout>
</Section.Card.Body>
</Section.Card>
Expand Down
1 change: 1 addition & 0 deletions js/src/dashboard/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
margin-bottom: var(--main-gap);

@include break-medium {
align-items: flex-start;
flex-direction: row;
}

Expand Down
15 changes: 10 additions & 5 deletions js/src/dashboard/summary-section/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
/**
* Internal dependencies
*/
import { glaData, REPORT_SOURCE_PAID, REPORT_SOURCE_FREE } from '.~/constants';
import { REPORT_SOURCE_PAID, REPORT_SOURCE_FREE } from '.~/constants';
import useAdsCampaigns from '.~/hooks/useAdsCampaigns';
import useAdsCurrency from '.~/hooks/useAdsCurrency';
import useCurrencyFormat from '.~/hooks/useCurrencyFormat';
import usePerformance from './usePerformance';
Expand Down Expand Up @@ -106,17 +107,21 @@
};

export default function SummarySection() {
const { adsSetupComplete } = glaData;
const { loaded, data: adsCampaignsData } = useAdsCampaigns();
if ( ! loaded ) {
return null;

Check warning on line 112 in js/src/dashboard/summary-section/index.js

View check run for this annotation

Codecov / codecov/patch

js/src/dashboard/summary-section/index.js#L112

Added line #L112 was not covered by tests
}
const showCampaignPromotionCard = ! adsCampaignsData?.length;

return (
<>
<SummaryCard
title={ __( 'Google Ads', 'google-listings-and-ads' ) }
>
{ adsSetupComplete ? (
<PaidPerformanceCard />
) : (
{ showCampaignPromotionCard ? (
<PaidCampaignPromotionCard />
) : (
<PaidPerformanceCard />
) }
</SummaryCard>
<SummaryCard
Expand Down
35 changes: 2 additions & 33 deletions js/src/dashboard/summary-section/paid-campaign-promotion-card.js
Original file line number Diff line number Diff line change
@@ -1,51 +1,20 @@
/**
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import { Spinner } from '@woocommerce/components';

/**
* Internal dependencies
*/
import useGoogleAdsAccount from '.~/hooks/useGoogleAdsAccount';
import AddPaidCampaignButton from '.~/components/paid-ads/add-paid-campaign-button';
import { GOOGLE_ADS_ACCOUNT_STATUS } from '.~/constants';

const PromotionContent = ( { adsAccount } ) => {
const showFreeCredit =
adsAccount.sub_account ||
adsAccount.status === GOOGLE_ADS_ACCOUNT_STATUS.DISCONNECTED;

return (
<>
<p>
{ showFreeCredit
? __(
'Create your first campaign and get $500 in ad credit*',
'google-listings-and-ads'
)
: __(
'Create your first campaign',
'google-listings-and-ads'
) }
</p>
<AddPaidCampaignButton
eventProps={ { context: 'add-paid-campaign-promotion' } }
/>
</>
);
};
import PaidFeatures from './paid-features';

function PaidCampaignPromotionCard() {
const { googleAdsAccount } = useGoogleAdsAccount();

return (
<div className="gla-summary-card__body">
{ googleAdsAccount ? (
<PromotionContent adsAccount={ googleAdsAccount } />
) : (
<Spinner />
) }
{ googleAdsAccount ? <PaidFeatures /> : <Spinner /> }

Check warning on line 17 in js/src/dashboard/summary-section/paid-campaign-promotion-card.js

View check run for this annotation

Codecov / codecov/patch

js/src/dashboard/summary-section/paid-campaign-promotion-card.js#L17

Added line #L17 was not covered by tests
</div>
);
}
Expand Down
44 changes: 44 additions & 0 deletions js/src/dashboard/summary-section/paid-features/free-ad-credit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import GridiconGift from 'gridicons/dist/gift';
import { createInterpolateElement } from '@wordpress/element';

/**
* Internal dependencies
*/
import AppDocumentationLink from '.~/components/app-documentation-link';

/**
* Render the Free Ads Credit inside the Paid Features component.
*
kt-12 marked this conversation as resolved.
Show resolved Hide resolved
* @fires gla_documentation_link_click with `{ context: 'dashboard', link_id: 'free-ad-credit-terms', href: 'https://www.google.com/ads/coupons/terms/' }`
* @return {JSX.Element} Free Ads Credit component.
*/
const FreeAdCredit = () => {
return (

Check warning on line 20 in js/src/dashboard/summary-section/paid-features/free-ad-credit.js

View check run for this annotation

Codecov / codecov/patch

js/src/dashboard/summary-section/paid-features/free-ad-credit.js#L20

Added line #L20 was not covered by tests
<div className="gla-free-ad-credit-claim">
<GridiconGift />
<div>
{ createInterpolateElement(
__(
'Claim $500 in ads credit when you spend your first $500 with Google Ads. <termLink>Terms and conditions apply</termLink>.',
'google-listings-and-ads'
),
{
termLink: (
<AppDocumentationLink
context="dashboard"
linkId="free-ad-credit-terms"
href="https://www.google.com/ads/coupons/terms/"
/>
),
}
) }
</div>
</div>
);
};

export default FreeAdCredit;
101 changes: 101 additions & 0 deletions js/src/dashboard/summary-section/paid-features/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/**
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import { createInterpolateElement } from '@wordpress/element';
import { Flex, FlexBlock, FlexItem } from '@wordpress/components';
import GridiconCheckmark from 'gridicons/dist/checkmark';

/**
* Internal dependencies
*/
import { ContentLink } from '.~/components/guide-page-content';
import CampaignPreview from '.~/components/paid-ads/campaign-preview';
import AddPaidCampaignButton from '.~/components/paid-ads/add-paid-campaign-button';
import FreeAdCredit from './free-ad-credit';
import VerticalGapLayout from '.~/components/vertical-gap-layout';
import './index.scss';

function FeatureList() {
const featuresItems = [

Check warning on line 20 in js/src/dashboard/summary-section/paid-features/index.js

View check run for this annotation

Codecov / codecov/patch

js/src/dashboard/summary-section/paid-features/index.js#L19-L20

Added lines #L19 - L20 were not covered by tests
{
Icon: GridiconCheckmark,
content: __(
'Reach more customer by advertising your products across Google Ads channels like Search, YouTube and Discover.',
'google-listings-and-ads'
),
},
{
Icon: GridiconCheckmark,
content: __(
'Set a daily budget and only pay when people click on your ads.',
'google-listings-and-ads'
),
},
{
Icon: GridiconCheckmark,
content: createInterpolateElement(
__(
"Performance Max uses the best of Google's AI to show the most impactful ads for your products at the right time and place. <link>Learn more about Performance Max technology.</link>",
'google-listings-and-ads'
),
{
link: (
<ContentLink
href="https://support.google.com/google-ads/answer/10724817"
context="campaign-creation-performance-max"
/>
),
}
),
},
];

return (

Check warning on line 54 in js/src/dashboard/summary-section/paid-features/index.js

View check run for this annotation

Codecov / codecov/patch

js/src/dashboard/summary-section/paid-features/index.js#L54

Added line #L54 was not covered by tests
<div className="gla-paid-features__feature-list">
{ featuresItems.map( ( { Icon, content }, idx ) => (
<Flex key={ idx } align="flex-start">

Check warning on line 57 in js/src/dashboard/summary-section/paid-features/index.js

View check run for this annotation

Codecov / codecov/patch

js/src/dashboard/summary-section/paid-features/index.js#L57

Added line #L57 was not covered by tests
<Icon size="18" />
<FlexBlock>{ content }</FlexBlock>
</Flex>
) ) }
</div>
);
}

/**
* Returns a component with paid features content.
*
* @return {JSX.Element} Paid Features component.
*/
const PaidFeatures = () => {
return (

Check warning on line 72 in js/src/dashboard/summary-section/paid-features/index.js

View check run for this annotation

Codecov / codecov/patch

js/src/dashboard/summary-section/paid-features/index.js#L72

Added line #L72 was not covered by tests
<VerticalGapLayout size="medium" className="gla-paid-features">
<Flex
align="center"
gap={ 9 }
className="gla-paid-features__content"
>
<FlexItem>
<CampaignPreview />
</FlexItem>
<FlexBlock>
<FeatureList />
</FlexBlock>
</Flex>
<FreeAdCredit />
joemcgill marked this conversation as resolved.
Show resolved Hide resolved
<AddPaidCampaignButton
isPrimary
isSecondary={ false }
isSmall={ false }
eventProps={ {
context: 'add-paid-campaign-promotion',
} }
>
{ __( 'Create Campaign', 'google-listings-and-ads' ) }
</AddPaidCampaignButton>
</VerticalGapLayout>
);
};

export default PaidFeatures;
44 changes: 44 additions & 0 deletions js/src/dashboard/summary-section/paid-features/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
.gla-paid-features {

&__content {
flex-direction: column;

@media (min-width: $break-small) {
align-items: flex-start;
flex-direction: row;
gap: $grid-unit-20;
}
}

&__feature-list {
display: flex;
flex-direction: column;
gap: $grid-unit-20;
line-height: $gla-line-height-smaller;
color: $gray-800;
text-align: left;

.gridicon {
fill: $alert-green;
}
}

.gla-free-ad-credit-claim {
text-align: left;
background-color: $white;
display: flex;
align-items: flex-start;
gap: $grid-unit;
padding: $grid-unit-20 $grid-unit-15;
color: $gray-900;

.gridicon {
fill: $gla-color-green;
flex: 0 0 auto;
}
}

.components-button {
align-self: flex-end;
}
}
37 changes: 30 additions & 7 deletions js/src/dashboard/summary-section/summary-section.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { render } from '@testing-library/react';
* Internal dependencies
*/
import SummarySection from '.~/dashboard/summary-section';
import useAdsCampaigns from '.~/hooks/useAdsCampaigns';

// Mimic no data loaded.
jest.mock( './usePerformance', () =>
Expand All @@ -22,34 +23,56 @@ jest.mock( '.~/hooks/useAdsCurrency', () =>
} )
);
jest.mock( '.~/hooks/useCurrencyFormat', () => jest.fn() );
jest.mock( '.~/hooks/useAdsCampaigns', () =>
jest.fn().mockName( 'useAdsCampaigns' )
);

describe( 'SummarySection when no data is loaded', () => {
beforeAll( () => {
useAdsCampaigns.mockImplementation( () => {
return {
loading: false,
loaded: true,
data: [
{
id: 10,
name: 'PMax Campaign',
status: 'enabled',
type: 'performance_max',
amount: 20,
displayCountries: [ 'US' ],
},
],
};
} );
} );

it( 'Shows no data message for Free Campaigns', async () => {
const { queryByText } = render( <SummarySection /> );
const { findByText } = render( <SummarySection /> );

expect(
queryByText(
await findByText(
"We're having trouble loading this data. Try again later, or track your performance in Google Merchant Center."
)
).toBeTruthy();

const link = queryByText( 'Open Google Merchant Center' );
const link = await findByText( 'Open Google Merchant Center' );

expect( link ).toBeTruthy();
expect( link.href ).toBe(
'https://merchants.google.com/mc/reporting/dashboard'
);
} );
it( 'Shows no data message for Paid Campaigns', () => {
const { queryByText } = render( <SummarySection /> );
it( 'Shows no data message for Paid Campaigns', async () => {
const { findByText } = render( <SummarySection /> );

expect(
queryByText(
await findByText(
"We're having trouble loading this data. Try again later, or track your performance in Google Ads."
)
).toBeTruthy();

const link = queryByText( 'Open Google Ads' );
const link = await findByText( 'Open Google Ads' );

expect( link ).toBeTruthy();
expect( link.href ).toBe( 'https://ads.google.com/' );
Expand Down
Loading