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

2535: Consolidate Ad Creation #2623

Open
wants to merge 60 commits into
base: feature/2459-campaign-creation-flow
Choose a base branch
from

Conversation

asvinb
Copy link
Collaborator

@asvinb asvinb commented Sep 24, 2024

Changes proposed in this Pull Request:

Closes #2535 .

Replace this with a good description of your changes & reasoning.

Detailed test instructions:

  1. Go through the onboarding process and ensure a paid campaign can be created.
    • When billing is not set up, the "Launch Paid Campaign" button should be disabled.
  2. Ensure the skip paid ads modal is displayed when the user clicks the skip button during the onboarding flow.
  3. Go through the setup ads flow (/wp-admin/admin.php?page=wc-admin&path=%2Fgoogle%2Fsetup-ads) and ensure a paid campaign can be created if billing is setup.
  4. Ensure a paid campaign can be added via the "Add a paid campaign" button on the dashboard.
  5. Ensure a paid campaign can be edited via the "Edit" links on the dashboard.
    • The budget recommendation should be for the selected countries for the paid campaign.
  6. Test when billing is not setup flow, ie. the user is prompted to setup billing.
  7. Users should not be able to submit/continue any flow if billing is not set up and approved.
  8. Users are no longer able to view the targeted countries.

Extra issues to test:

Additional details:

Changelog entry

Update - Consolidate the campaign setup UI in the onboarding flow with the one in the ads setup flow.

@github-actions github-actions bot added the changelog: update Big changes to something that wasn't broken. label Sep 24, 2024
Copy link

codecov bot commented Sep 24, 2024

Codecov Report

Attention: Patch coverage is 10.00000% with 27 lines in your changes missing coverage. Please review.

Project coverage is 61.8%. Comparing base (aa4329c) to head (25ed467).
Report is 47 commits behind head on feature/2459-campaign-creation-flow.

Files with missing lines Patch % Lines
...c/components/paid-ads/ads-campaign/ads-campaign.js 0.0% 14 Missing and 3 partials ⚠️
js/src/pages/create-paid-ads-campaign/index.js 0.0% 3 Missing and 1 partial ⚠️
...tup-ads/ads-stepper/launch-paid-campaign-button.js 40.0% 3 Missing ⚠️
...c/components/paid-ads/billing-card/billing-card.js 0.0% 1 Missing and 1 partial ⚠️
js/src/setup-ads/ads-stepper/index.js 50.0% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@                          Coverage Diff                          @@
##           feature/2459-campaign-creation-flow   #2623     +/-   ##
=====================================================================
- Coverage                                 62.6%   61.8%   -0.8%     
=====================================================================
  Files                                      319     327      +8     
  Lines                                     5063    5106     +43     
  Branches                                  1232    1242     +10     
=====================================================================
- Hits                                      3171    3156     -15     
- Misses                                    1718    1768     +50     
- Partials                                   174     182      +8     
Flag Coverage Δ
js-unit-tests 61.8% <10.0%> (-0.8%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...src/components/paid-ads/ads-campaign/faqs-panel.js 66.7% <ø> (ø)
...paid-ads/ads-campaign/paid-ads-features-section.js 0.0% <ø> (ø)
js/src/pages/edit-paid-ads-campaign/index.js 9.3% <ø> (-0.2%) ⬇️
js/src/setup-ads/ads-stepper/index.js 93.3% <50.0%> (-6.7%) ⬇️
...c/components/paid-ads/billing-card/billing-card.js 11.1% <0.0%> (ø)
...tup-ads/ads-stepper/launch-paid-campaign-button.js 40.0% <40.0%> (ø)
js/src/pages/create-paid-ads-campaign/index.js 10.3% <0.0%> (-0.6%) ⬇️
...c/components/paid-ads/ads-campaign/ads-campaign.js 0.0% <0.0%> (ø)

... and 7 files with indirect coverage changes

joemcgill and others added 2 commits September 30, 2024 14:08
…creation-ccf-onboarding-merged

Merge onboarding improvements branch into consolidated ad
Copy link
Collaborator

@joemcgill joemcgill left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these updates are looking pretty good and are testing well for me locally. Left one suggestion, but marking as approved and ready for another QA pass.

One note for QA that should be kept in mind is that when this PR is tested with billing not approved, you'll see the billing setup card on this form as well as a duplicate billing step when creating your first campaigns from the dashboard, until #2536 is completed.

@ankitguptaindia
Copy link
Member

QA/Test Report-

Testing Environment -

  • WordPress: 6.6.2
  • Theme active on store: Twenty Twenty-Four Version: 1.2
  • WooCommerce - Version 9.3.3
  • PHP: 8.3
  • Web Server: Nginx
  • Browser: Chrome - Version 128
  • OS: macOS Sonoma 14.6.1

Test Results - Followed the testing instructions, acceptance criteria, and tested all possible ways to create, edit, and manage paid ad campaigns. All tests were passed when billing was not set, with billing set, and other use cases.

Next Step- Ready to Code Review(Woo)

js/src/components/paid-ads/ads-campaign/ads-campaign.js Outdated Show resolved Hide resolved
js/src/components/paid-ads/ads-campaign/ads-campaign.js Outdated Show resolved Hide resolved
js/src/components/paid-ads/ads-campaign/ads-campaign.js Outdated Show resolved Hide resolved
Comment on lines 149 to 159
{ isOnboardingFlow && <PaidAdsFeaturesSection /> }

<PaidAdsSetupSections
onStatesReceived={ handleOnStatesReceived }
campaign={ campaign }
countryCodes={ countryCodes }
loadCampaignFromClientSession={ isOnboardingFlow }
showCampaignPreviewCard={
trackingContext === 'setup-ads' ||
trackingContext === 'create-ads'
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per the first acceptance criteria:

When a user is on the "Create your paid campaign" step of the "Set up paid ads" flow, they will see the same form used on the "Create a campaign" step of the "Get started..." onboarding flow.

I would like to confirm what the scope of the “same form” is, after all, they are currently presented differently in the campaign preview.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "same form" means that we will use the same component for both forms so that the requirements of each input section are consistent. The main difference is that the PaidAdsFeaturesSection should only be shown during onboarding.

Copy link
Member

@eason9487 eason9487 Oct 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the explanation.

I would suggest rephrasing it a little bit to avoid having “When a user …, they will see …” wording that confuses its goal of just having to share components in development. Or, clarify the goal is to have the same UI as before the change.

js/src/components/paid-ads/billing-card/billing-card.js Outdated Show resolved Hide resolved
js/src/components/paid-ads/billing-card/billing-card.js Outdated Show resolved Hide resolved
Copy link
Member

@ankitguptaindia ankitguptaindia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Verified the changes from a user perspective and confirmed that creating, editing, and managing paid ad campaigns from all desired screens is working without any errors.

✅ When billing is not set up, the merchant is unable to complete the setup process, as expected.

✅ All cases defined in Acceptance Criteria works as expected.

*/

/**
* @typedef {import('.~/components/paid-ads/ads-campaign/paid-ads-setup-sections').PaidAdsData} PaidAdsData
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file doesn't have the PaidAdsData type definition.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Comment on lines 40 to 41
* @param {JSX|(PaidAdsData) =>JSX} [props.skipButton] A React element or function to render the "Skip" button. If a function is passed, it receives the paid ads data and returns the button element.
* @param {JSX|(AdaptiveFormContext, PaidAdsData) =>JSX} [props.continueButton] A React element or function to render the "Continue" button. If a function is passed, it receives the form context and paid ads data and returns the button element. It handles submission logic in the form.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some issues in these JSDoc:

  1. JSX is a type namespace rather than a type.
  2. Due to the limitation of the npm run doc:tracking script, the function type needs to be placed ahead of another one. For example, swap string | () => boolean to () => boolean | string. Otherwise, the script can't parse it.
    ERROR: Unable to parse a tag's type expression for source file js/src/components/paid-ads/ads-campaign/ads-campaign.js in line 29 with tag title "param" and text "{JSX|(module:components/paid-ads/ads-campaign/ads-campaign~PaidAdsData) =>JSX} [props .skipButton] A React element or function to render the "Skip" button. If a function is passed, it receives the paid ads data and returns the button element.": Invalid type expression "JSX|(module:components/paid-ads/ads-campaign/ads-campaign~PaidAdsData) =>JSX": Expected "!", "$", "'", "*", ".", "...", "0", "?", "@", "Function", "\"", "\\", "_", "break", "case", "catch", "class", "const", "continue", "debugger", "default", "delete", "do", "else", "enum", "export", "extends", "false", "finally", "for", "function", "if", "implements", "import", "in", "instanceof", "interface", "let", "new", "null", "package", "private", "protected", "public", "return", "static", "super", "switch", "this", "throw", "true", "try", "typeof", "undefined", "var", "void", "while", "with", "yield", "{", Unicode letter number, Unicode lowercase letter, Unicode modifier letter, Unicode other letter, Unicode titlecase letter, Unicode uppercase letter, or [1-9] but "(" found.
    
  3. Their implementation doesn't pass a PaidAdsData as a function parameter.
  4. The props.continueButton doesn't actually handle submission logic in the form in this component, and it's not always expected that the consumer side will use it to submit a form.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JSDoc updated @eason9487 . Thanks for catching that.

continueButton,
} ) {
const formContext = useAdaptiveFormContext();
const { data: countryCodes } = useTargetAudienceFinalCountryCodes();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This countryCodes may lead to incorrect budget recommendation text and amount when editing an existing campaign having different target audience countries than the current ones in the free listings setup.

For example, given a campaign was created with one country code but is being edited after the free listings setup has been updated to have two country codes, the recommendation text will be incorrect:

  • Expected: Most merchants targeting Taiwan set a daily budget of 12 USD
  • Received: Most merchants targeting similar countries set a daily budget of 17 USD
Kapture.2024-10-10.at.15.46.15.mp4

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines 87 to 90
showCampaignPreviewCard={
trackingContext === 'setup-ads' ||
trackingContext === 'create-ads'
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before this PR, the preview card is shown as well when editing campaign.

Copy link
Collaborator Author

@asvinb asvinb Oct 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that the AdsCampaign component has become more flexible and simple to use, however, there are still a few factors that can be polished.

  • Render logic depending on a prop named trackingContext seems inappropriate.
  • isOnboardingFlow and trackingContext could be consolidated and lifted to a higher abstraction level.
  • PaidAdsSetupSections is now purer and contains only one section.
  • Even if there is no need to render a BillingCard when creating or editing campaign, a redundant API request will still be sent to get the billing status.

Suggestions to further simplify the logic and divide component responsibilities:

  • Remove isOnboardingFlow prop and rename trackingContext to context.
    • context accepts one more possible string value, such as 'setup-mc'. to indicate it's being used in onboarding
    • Declare render condition variables within the components, for example:
      const isOnboardingFlow = context === 'setup-mc';
      const showBillingCard = context === 'setup-mc' || context === 'setup-ads';
  • Remove PaidAdsSetupSections to reduce the complexity of a layer of components.
    • Move the API request of getting billing status and SpinnerCard back to the BillingCard component
    • Moe the rest to the AdsCampaign component and use the above render condition variables, for example:
      <BudgetSection
      	formProps={ formContext }
      	countryCodes={ /* value for this prop needs to consider another comment */ }
      >
      	{ showBillingCard && <BillingCard /> }
      	{ ! isOnboardingFlow && <CampaignPreviewCard /> }
      </BudgetSection>

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestions @eason9487 . Makes sense. Updated!

initialCampaign={ paidAds }
validate={ validateCampaign }
onChange={ ( _, values, isValid ) => {
setPaidAds( { ...paidAds, ...values, isValid } );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously, the form component was under several layers of this component, so it required a more cumbersome way to retrieve the form data and validation state.

Now this component is wrapped by CampaignAssetsForm, so all handling related to using paidAds and calling setPaidAds should be able to be removed.

  • The paidAds.amount value can be replaced with formContext.values.amount
  • The paidAds.isValid state can be replaced with formContext.isValidForm

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good. Updated.

@@ -133,6 +135,7 @@ const CreatePaidAdsCampaign = () => {
countryCodes: initialCountryCodes,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The audience section has been completely removed from campaign creation, so it would be better to decouple the countryCodes from the form component.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Member

@eason9487 eason9487 Oct 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to #2623 (comment).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Member

@eason9487 eason9487 Oct 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to #2623 (comment).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Comment on lines 416 to 420
await expect(
page.getByRole( 'link', {
name: 'click here instead',
} )
).toBeVisible();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it necessary to remove this assertion?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why it was removed in first place. I restored it 👍

@asvinb
Copy link
Collaborator Author

asvinb commented Oct 11, 2024

@ankitguptaindia Can you kindly test the changes please? I also added items to double check in the QAB.

Extra issues to test:

#2623 (comment)
#2623 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
changelog: update Big changes to something that wasn't broken.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Consolidate the ad creation step in the Ads Setup flow with the one used in Onboarding
4 participants