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

My Jetpack: Add "Expired" & "Expires soon" statuses to product cards #39816

Merged
merged 19 commits into from
Nov 27, 2024

Conversation

elliottprogrammer
Copy link
Contributor

@elliottprogrammer elliottprogrammer commented Oct 18, 2024

This PR adds an "Expired" or "Expiring soon" status to the product cards of products with an expired or expiring paid plan subscription. We also make the product CTA say "Renew my plan" (or "Resume my plan" if expired) and link to the specific subscription in purchase management section of their wordpress.com account so that they can renew or resume their subscription.

Screenshots:

Screen Shot 2024-11-26 at 08 12 58

Screen Shot 2024-10-22 at 18 57 57

.

Proposed changes:

Other information:

  • Have you written new tests for your changes, if applicable?
  • Have you checked the E2E test CI results, and verified that your changes do not break them?
  • Have you tested your changes on WordPress.com, if applicable (if so, you'll see a generated comment below with a script to run)?

Jetpack product discussion

Project Thread: pbNhbs-bJN-p2

Design Thread: p1HpG7-umC-p2

Does this pull request change what data or activity we track or use?

No

Testing instructions:

To test this PR, skip down to "Testing this PR":
Otherwise, if testing issue: Backup Card: My Jetpack shows "Needs Plan" for backup even when there is a Jetpack plan from a hosting partner, follow the instructions below:

Testing issue #39762 :
(Backup Card: My Jetpack shows "Needs Plan" for backup even when there is a Jetpack plan from a hosting partner.)

  • Create a Pressable hosting partner site (if you don't already have one) by following instructions here: PCYsg-9TF-p2
    • (sign up using the direct link to the a8c employee plan that requires no coupon)
  • Install the Jetpack Beta Tester plugin: https://github.com/Automattic/jetpack-beta
  • Activate this PR branch for Jetpack in Jetpack Beta plugin.
  • Purchase a Backup plan.
  • Open My Jetpack and confirm that Backup product card status is Active and not "Needs plan".

Testing this PR:

  • Test this PR with a Jurassic Ninja Site running the Beta plugin on the add/mj-expired-products-cards branch. In the JN interface, you can automatically assign paid product licenses for all the products shown on the My Jetpack page, See screenshot:

Screen Shot on 2024-10-22 at 22-08-12

  • Connect Jetpack, both site and user. (Once user connected, you will see all the paid plans in My Jetpack.)
  • Confirm that all paid products are showing the correct status (For example confirm Backup and Search are not showing "Needs plan" when the paid plan has actually been purchased) - See issue: Backup Card: My Jetpack shows "Needs Plan" for backup even when there is a Jetpack plan from a hosting partner. #39762
  • Now look up your site in Store Admin.
  • One by one, for each of the subscriptions, change the expiration date to either expiring (nearing expiration), or expired . You may need to disable 'auto-renew' for the plan to show as expiring/expired. The go to My Jetpack, reload the page and look at the product card for that plan.
  • Verify the status is either "Expired" or "Expiring soon", depending on the date you set.
  • Verify there is a red border around expired products, and a yellow border around products expiring soon.
  • Verify that for products that are Expired, the CTA says "Resume my plan" and points to the wordpress.com purchase management page. For products that are Expiring soon, verify the CTA says "Renew my plan", and points directly to checkout with the product renewal in the cart.
  • Continue this (set the expiration date, then view in My Jetpack) for each of the products.
  • Once done testing all products, in Store Admin you can remove all the product subscriptions.
  • Now Purchase a bundle for the site, such as Complete, or Security.
  • In Store Admin, set the bundle subscription date to expired/expiring. (you may need to disable auto-renew).
  • Now view the products included with the bundle on My Jetpack. The products included with the bundle should be showing as expired/expiring soon, in My Jetpack.
  • Verify that the expired/expiring CTA points to the bundle subscription in the purchase management page on wordpress.com (for expired), or points directly to checkout (for expiring-soon).
  • Establish a site-only connection (no user-connection) and verify everything works properly with no errors. Some product cars may now show the status "Requires user connection", which takes precedence over expired/expiring products.

Copy link
Contributor

github-actions bot commented Oct 18, 2024

Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.

  • To test on WoA, go to the Plugins menu on a WordPress.com Simple site. Click on the "Upload" button and follow the upgrade flow to be able to upload, install, and activate the Jetpack Beta plugin. Once the plugin is active, go to Jetpack > Jetpack Beta, select your plugin, and enable the add/mj-expired-products-cards branch.

  • To test on Simple, run the following command on your sandbox:

    bin/jetpack-downloader test jetpack add/mj-expired-products-cards
    

Interested in more tips and information?

  • In your local development environment, use the jetpack rsync command to sync your changes to a WoA dev blog.
  • Read more about our development workflow here: PCYsg-eg0-p2
  • Figure out when your changes will be shipped to customers here: PCYsg-eg5-p2

Copy link
Contributor

Thank you for your PR!

When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:

  • ✅ Include a description of your PR changes.
  • ✅ Add a "[Status]" label (In Progress, Needs Team Review, ...).
  • ✅ Add testing instructions.
  • ✅ Specify whether this PR includes any changes to data or privacy.
  • ✅ Add changelog entries to affected projects

This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖


The e2e test report can be found here. Please note that it can take a few minutes after the e2e tests checks are complete for the report to be available.


Follow this PR Review Process:

  1. Ensure all required checks appearing at the bottom of this PR are passing.
  2. Choose a review path based on your changes:
    • A. Team Review: add the "[Status] Needs Team Review" label
      • For most changes, including minor cross-team impacts.
      • Example: Updating a team-specific component or a small change to a shared library.
    • B. Crew Review: add the "[Status] Needs Review" label
      • For significant changes to core functionality.
      • Example: Major updates to a shared library or complex features.
    • C. Both: Start with Team, then request Crew
      • For complex changes or when you need extra confidence.
      • Example: Refactor affecting multiple systems.
  3. Get at least one approval before merging.

Still unsure? Reach out in #jetpack-developers for guidance!

IanRamosC
IanRamosC previously approved these changes Oct 24, 2024
Copy link
Contributor

@IanRamosC IanRamosC left a comment

Choose a reason for hiding this comment

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

This looks pretty good. The changes are easy to follow and the code tested well. 👍🏾

@IanRamosC
Copy link
Contributor

It seems like you need to update the PR before merging

Copy link
Contributor

@CodeyGuyDylan CodeyGuyDylan left a comment

Choose a reason for hiding this comment

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

I mentioned this is the other PR but wanted to make sure it didn't get lost. I don't think we should be showing the "expired" status if it's been expired for a very long time. My gut reaction is we probably shouldn't show it if it's been expired for longer than a month

I noticed the "needs connection" error shows as a red error. I'm wondering if it should be yellow since the status is also yellow? Also, if the "Needs connection" error has a red or maybe yellow border, should the "Needs plan" status also have one?

image

Other than those thoughts, the plan recognition upgrade seems to work great! Thank you for your hard work on this

*
* @return boolean
*/
public static function has_paid_plan_for_product() {
// First check site features (if there's a feature that identifies the paid plan)
if ( static::$feature_identifying_paid_plan ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Seems like having this check fulfills most of what this issue needs to be fixed 😄 Once this is done, it should be a quick patch to get this one done finally 🥳

Copy link
Contributor

Choose a reason for hiding this comment

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

@grzegorz-cp would you be able to follow up on this, and get the issue done?

@elliottprogrammer
Copy link
Contributor Author

First, thanks very much for the reviews @CodeyGuyDylan! 😃
Oh, my apologies Dylan, I meant to address/answer these points/feedback from your first review.

I mentioned this is the other PR but wanted to make sure it didn't get lost. I don't think we should be showing the "expired" status if it's been expired for a very long time. My gut reaction is we probably shouldn't show it if it's been expired for longer than a month

For not showing a product as "expired" after it's been expired for a certain amount of time, here's my thoughts:
If we don't show when the product is expired (after a certain time), then what status do we show it as then? Just "Active"?, or "Needs plan"? For products that require a paid plan to use them, if we show them as Active, it won't actually be active because it's expired. But we show the product as "Needs plan" instead, I don't think the user can re-purchase the same plan until they "Remove" the expired one first. Something about showing a particular product card (like Backup, or whatever) like nothing is wrong with it, but then when the user clicks on the card to use it, it's not working properly because the plan subscription has been expired. It just seems like it might be opening a big can of worms..
When a product subscription expires, the user really should either 1.- Renew the subscription, Or 2.- Remove it (in the purchase management section). If they Remove the subscription, the expiration status and notice goes away. If they Renew the subscription, the status and notice goes away. Thats why when a product is expired, the Notice CTA, I pointed to the purchase/subscription management section on wordpress.com where the user can either "Remove" the subscription or "Renew" it. However if the product is expiring soon, the Notice CTA points straight to checkout with the product renewal in the cart.
I noticed that Atomic sites also don't hide the plan expiration notice (after any amount of time) either. In fact Atomic sites have the expiration notice displaying all over the place, on many different pages all throughout wp-admin (Every one of the settings pages (14 pages), the WP Dashboard page, the Hosting -> home page, the Jetpack - Akismet page, and others I think.), where I believe the thinking is that the user is expected to either renew the subscription, or remove it, if they want the notice to go away. (see screenshots: Here's only a few, out of many, many:)

Screen Shot 2024-11-25 at 20 16 56
Screen Shot 2024-11-25 at 20 18 29
Screen Shot 2024-11-25 at 20 19 50

Anyway, so let me know your thoughts. Let me know if maybe I'm missing something, or maybe over-thinking it?

I did however make a change in the code where I added in the ability to hide/don't show the expiration status after 2 months after the expiration date. I didn't turn it on by default. But it would only be a matter of passing in a true value into a function call, if we should decide to go that route. 😉🤷‍♂️

I noticed the "needs connection" error shows as a red error. I'm wondering if it should be yellow since the status is also yellow? Also, if the "Needs connection" error has a red or maybe yellow border, should the "Needs plan" status also have one?

Hmm, I changed/fixed this prior to your review.. I wonder if your branch (or Jetpack Beta branch) was not up to the latest?
I changed the product card border back to how it was originally, where connection warnings and other warnings/errors do not show a red or yellow border around the product cards. Only the expired/expiring products show the red/yellow borders around them. 🙂

@CodeyGuyDylan
Copy link
Contributor

Thats why when a product is expired, the Notice CTA, I pointed to the purchase/subscription management section on wordpress.com where the user can either "Remove" the subscription or "Renew" it.

This is a good point and maybe fixes the issue I had with it 🤔 I don't know that, as a user, I would find it clear that the way to make the notification go away is to remove the subscription altogether, though I guess I would probably try it eventually. (I hate notifications 😆). I think we are probably okay to keep it how it is then if that's the case. Could we add to tracks the ability to see how long a subscription has been expired when viewing a card with an expired plan? That way we could check in tracks later to see if users are leaving that notification there for long periods of time or not later on.

In fact Atomic sites have the expiration notice displaying all over the place

Personally I don't think that's very good UX either 😅. I am not every user but personally that would bug the heck out of me

@elliottprogrammer
Copy link
Contributor Author

@CodeyGuyDylan ,

I don't know that, as a user, I would find it clear that the way to make the notification go away is to remove the subscription altogether, though I guess I would probably try it eventually. (I hate notifications 😆)

Yeah, so true, I think we all hate notifications! 😆

Looking into it and thinking about this further, I'm noticing there's a way to show a close(X) icon on the notice! I'll look now to see how much it would take to close the expired/expiring notices with some persistence! This would be ideal, I think. Do you agree? 😃

Could we add to tracks the ability to see how long a subscription has been expired when viewing a card with an expired plan? That way we could check in tracks later to see if users are leaving that notification there for long periods of time or not later on.

This is a great idea! Yes, I'll do this! 🙌

In fact Atomic sites have the expiration notice displaying all over the place

Personally I don't think that's very good UX either 😅. I am not every user but personally that would bug the heck out of me

Yeah, I agree.

CodeyGuyDylan
CodeyGuyDylan previously approved these changes Nov 27, 2024
Copy link
Contributor

@CodeyGuyDylan CodeyGuyDylan left a comment

Choose a reason for hiding this comment

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

More of a question instead of a requested change. In the scenario below, Boost, Social, and Protect all have expired plans. I see that some statuses override the expired plan status such as these. I think that is fine, as it wouldn't work anyway without the plugin being installed or active, so the statuses shown are still integral to getting the plugin to work. I just wanted to make sure it was expected behavior 😄
image

One note, and this probably isn't feasible, but I think it would be great if we could redirect them back to My Jetpack after renewing or removing a product after getting to /me/purchases from My Jetpack. Maybe we could do that sometime in the future

Other than that I think all of my issues have been addressed. Thank you for all the changes! I'll put my conversation with payments about the renewal stuff here since that answers the question as to why we don't need to cut off renewals older than a month old 😄

Slack: p1732730061873749-slack-C02BEP610

@elliottprogrammer
Copy link
Contributor Author

More of a question instead of a requested change. In the scenario below, Boost, Social, and Protect all have expired plans. I see that some statuses override the expired plan status such as these. I think that is fine, as it wouldn't work anyway without the plugin being installed or active, so the statuses shown are still integral to getting the plugin to work. I just wanted to make sure it was expected behavior

@CodeyGuyDylan, Yes, that is expected behavior.
There are some statuses that have a higher priority and they override the expiring plans notices. Yeah all the statuses have a particular, sensible order in the Product::get_status() function. 👍

@elliottprogrammer elliottprogrammer merged commit 8b04c77 into trunk Nov 27, 2024
72 checks passed
@elliottprogrammer elliottprogrammer deleted the add/mj-expired-products-cards branch November 27, 2024 19:48
Comment on lines +177 to +188
return array(
'jetpack_social_v1_yearly',
'jetpack_social_v1_monthly',
'jetpack_social_v1_bi_yearly',
'jetpack_social_basic_yearly',
'jetpack_social_monthly',
'jetpack_social_basic_monthly',
'jetpack_social_basic_bi_yearly',
'jetpack_social_advanced_yearly',
'jetpack_social_advanced_monthly',
'jetpack_social_advanced_bi_yearly',
);
Copy link
Member

Choose a reason for hiding this comment

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

Should this contain all the legacy products that are no longer used anymore?

Social currently has only those *_v1_* products.

Copy link
Contributor Author

@elliottprogrammer elliottprogrammer Dec 2, 2024

Choose a reason for hiding this comment

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

Hey @manzoorwanijk! 👋 Thanks for the question! 😃

Should this contain all the legacy products that are no longer used anymore?
Social currently has only those v1 products.

To answer your question: Yes, it should contain ALL possible Social product slugs (including legacy products, but not including Bundle plans)
Yes, ultimately has_paid_plan_for_product() uses this function in question (get_paid_plan_product_slugs()) as well as get_paid_bundles_that_include_product() to get All the paid plan product_slugs and bundle plan product_slugs that include Social, to ultimately determine if the site has a paid plan for the product (in this case Social).
Some sites/users might still be renewing a legacy Social product that they bought previously, so we need to know if the site/user has ANY Social paid plan (including legacy plans, or even bundled plans that include Social within it). Basically, if the site/user has Any paid plan that includes Social, we want to know about it. 😉

Copy link
Member

Choose a reason for hiding this comment

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

Hey

Oh yeah. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants