Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Fix: Add support to apply filters via URL for All Products block #6642

Merged
merged 18 commits into from Jul 11, 2022

Conversation

dinhtungdu
Copy link
Member

@dinhtungdu dinhtungdu commented Jun 29, 2022

Fixes #6441

With this PR, when filtering for the All Products block:

  • The URL is updated on filter state changes.
  • Only the URL is updated, no page reload occurs.
  • Initial filters are set from the URL like PHP templates.

This PR also:

  • simplifies the logic that set the initial filters from the URL and makes the filter blocks more stable.
  • fixes the issue with the Filter Products by Stock Status when filtering the All Products block on the homepage (see screenshot).

To reviewers:

  • Should we disable the new behavior by default and let developers enable it by a filter or setting?
  • The codebase of filter blocks are similar and I think we should refactor and extract the common logic to share between them during the cooldown periods.

Accessibility

Other Checks

  • This PR adds/removes a feature flag & I've updated this doc .
  • This PR adds/removes an experimental interfaces and I've updated this doc
  • I tagged two reviewers because this PR makes queries to the database or I think it might have some security impact.

Screenshots

Screen.Recording.2022-06-30.at.14.38.41.mov

Testing

Automated Tests

  • Changes in this PR are covered by Automated Tests.
    • Unit tests
    • E2E tests

User Facing Testing

For each filter block, ensure:

  • No regression when used with PHP templates.
  • The URL is updated when checking or unchecking filters.
  • For filter blocks using the filter button, the URL is updated after clicking the filter button.
  • With the updated URL, all selected filters are set correctly after reloading the page. Filter blocks with or without the filter button should work the same.
  • Removing the filter from the Active Filters block should update the URL and the corresponding filter block.
  • Do not include in the Testing Notes

WooCommerce Visibility

  • WooCommerce Core
  • Feature plugin
  • Experimental

Performance Impact

Changelog

Add filter URL support to filter blocks when filtering for All Products block.

@dinhtungdu dinhtungdu self-assigned this Jun 29, 2022
@github-actions
Copy link
Contributor

github-actions bot commented Jun 29, 2022

Size Change: +541 B (0%)

Total Size: 876 kB

Filename Size Change
build/active-filters-frontend.js 7.34 kB +86 B (+1%)
build/active-filters.js 8.01 kB +91 B (+1%)
build/all-products-frontend.js 18.1 kB -1 B (0%)
build/all-products.js 33.5 kB +3 B (0%)
build/all-reviews.js 7.8 kB +1 B (0%)
build/attribute-filter-frontend.js 25.1 kB +89 B (0%)
build/attribute-filter.js 14.4 kB +55 B (0%)
build/cart-blocks/cart-line-items--mini-cart-contents-block/products-table-frontend.js 5.27 kB +1 B (0%)
build/cart-blocks/cart-line-items-frontend.js 429 B -3 B (-1%)
build/cart-blocks/order-summary-coupon-form-frontend.js 2.62 kB -1 B (0%)
build/cart-blocks/order-summary-heading-frontend.js 455 B +1 B (0%)
build/cart-blocks/order-summary-shipping--checkout-blocks/order-summary-shipping-frontend.js 6.34 kB -2 B (0%)
build/cart-blocks/order-summary-shipping-frontend.js 428 B +1 B (0%)
build/cart-blocks/order-summary-taxes-frontend.js 434 B +2 B (0%)
build/cart-blocks/proceed-to-checkout-frontend.js 1.16 kB +3 B (0%)
build/cart-frontend.js 45.6 kB -5 B (0%)
build/cart.js 44.2 kB +7 B (0%)
build/checkout-blocks/actions-frontend.js 1.41 kB -1 B (0%)
build/checkout-blocks/billing-address--checkout-blocks/shipping-address-frontend.js 4.12 kB +2 B (0%)
build/checkout-blocks/billing-address-frontend.js 889 B +1 B (0%)
build/checkout-blocks/contact-information-frontend.js 2.83 kB +2 B (0%)
build/checkout-blocks/express-payment-frontend.js 5.36 kB -1 B (0%)
build/checkout-blocks/order-summary-cart-items-frontend.js 3.67 kB +3 B (0%)
build/checkout-blocks/order-summary-coupon-form-frontend.js 2.77 kB -1 B (0%)
build/checkout-blocks/order-summary-discount-frontend.js 2.25 kB -1 B (0%)
build/checkout-blocks/order-summary-taxes-frontend.js 434 B +2 B (0%)
build/checkout-blocks/shipping-address-frontend.js 993 B +2 B (0%)
build/checkout-blocks/shipping-methods-frontend.js 4.72 kB -1 B (0%)
build/checkout-frontend.js 47.9 kB -12 B (0%)
build/checkout.js 45.5 kB +11 B (0%)
build/featured-category.js 13.2 kB +5 B (0%)
build/featured-product.js 13.5 kB +7 B (0%)
build/handpicked-products.js 7.4 kB +2 B (0%)
build/mini-cart-component-frontend.js 16.6 kB -8 B (0%)
build/mini-cart-contents-block/footer--mini-cart-contents-block/products-table-frontend.js 4.68 kB -1 B (0%)
build/mini-cart-contents-block/footer-frontend.js 5.75 kB +1 B (0%)
build/mini-cart-contents.js 22.9 kB -11 B (0%)
build/price-filter-frontend.js 13.1 kB +38 B (0%)
build/price-filter.js 9.04 kB +47 B (+1%)
build/product-add-to-cart--product-button--product-category-list--product-image--product-price--product-r--a0326d00.js 223 B +1 B (0%)
build/product-add-to-cart--product-button--product-image--product-title.js 2.65 kB -1 B (0%)
build/product-add-to-cart-frontend.js 6.96 kB +2 B (0%)
build/product-add-to-cart.js 6.63 kB +1 B (0%)
build/product-best-sellers.js 7.49 kB +1 B (0%)
build/product-button-frontend.js 1.85 kB +2 B (0%)
build/product-category-list-frontend.js 921 B +1 B (0%)
build/product-category.js 8.6 kB +1 B (0%)
build/product-new.js 7.78 kB +3 B (0%)
build/product-on-sale.js 8.09 kB +1 B (0%)
build/product-price-frontend.js 1.94 kB +1 B (0%)
build/product-price.js 1.51 kB +3 B (0%)
build/product-sale-badge-frontend.js 1.09 kB +1 B (0%)
build/product-stock-indicator-frontend.js 1.03 kB +1 B (0%)
build/product-tag-list-frontend.js 916 B +1 B (0%)
build/product-tag.js 8.13 kB +1 B (0%)
build/product-title-frontend.js 1.29 kB +3 B (0%)
build/product-title.js 910 B +1 B (0%)
build/products-by-attribute.js 8.7 kB -3 B (0%)
build/reviews-by-category.js 11.3 kB +3 B (0%)
build/reviews-by-product.js 12.4 kB +1 B (0%)
build/single-product-frontend.js 21.4 kB -4 B (0%)
build/single-product.js 10.1 kB +3 B (0%)
build/stock-filter-frontend.js 7.39 kB +43 B (+1%)
build/stock-filter.js 7.31 kB +58 B (+1%)
build/vendors--mini-cart-contents-block/footer-frontend.js 6.86 kB -1 B (0%)
build/wc-blocks-vendors.js 59 kB +3 B (0%)
ℹ️ View Unchanged
Filename Size
build/blocks-checkout.js 17.4 kB
build/cart-blocks/cart-accepted-payment-methods-frontend.js 1.16 kB
build/cart-blocks/cart-express-payment-frontend.js 5.06 kB
build/cart-blocks/cart-items-frontend.js 299 B
build/cart-blocks/cart-order-summary-frontend.js 1.11 kB
build/cart-blocks/cart-totals-frontend.js 321 B
build/cart-blocks/empty-cart-frontend.js 345 B
build/cart-blocks/filled-cart-frontend.js 782 B
build/cart-blocks/order-summary-discount-frontend.js 2.12 kB
build/cart-blocks/order-summary-fee-frontend.js 274 B
build/cart-blocks/order-summary-subtotal-frontend.js 274 B
build/checkout-blocks/fields-frontend.js 345 B
build/checkout-blocks/order-note-frontend.js 1.08 kB
build/checkout-blocks/order-summary-fee-frontend.js 275 B
build/checkout-blocks/order-summary-frontend.js 1.11 kB
build/checkout-blocks/order-summary-shipping-frontend.js 603 B
build/checkout-blocks/order-summary-subtotal-frontend.js 274 B
build/checkout-blocks/payment-frontend.js 7.67 kB
build/checkout-blocks/terms-frontend.js 1.22 kB
build/checkout-blocks/totals-frontend.js 326 B
build/legacy-template.js 2.8 kB
build/mini-cart-contents-block/empty-cart-frontend.js 364 B
build/mini-cart-contents-block/filled-cart-frontend.js 229 B
build/mini-cart-contents-block/items-frontend.js 226 B
build/mini-cart-contents-block/products-table-frontend.js 290 B
build/mini-cart-contents-block/shopping-button-frontend.js 288 B
build/mini-cart-contents-block/title-frontend.js 367 B
build/mini-cart-frontend.js 1.72 kB
build/mini-cart.js 6.62 kB
build/price-format.js 1.19 kB
build/product-add-to-cart--product-button.js 564 B
build/product-button--product-category-list--product-image--product-price--product-rating--product-sale-b--e17c7c01.js 500 B
build/product-button.js 1.09 kB
build/product-categories.js 2.78 kB
build/product-category-list.js 502 B
build/product-image-frontend.js 1.84 kB
build/product-image.js 1.07 kB
build/product-rating-frontend.js 1.15 kB
build/product-rating.js 731 B
build/product-sale-badge.js 679 B
build/product-search.js 2.18 kB
build/product-sku-frontend.js 381 B
build/product-sku.js 381 B
build/product-stock-indicator.js 621 B
build/product-summary-frontend.js 1.33 kB
build/product-summary.js 916 B
build/product-tag-list.js 497 B
build/product-top-rated.js 8.01 kB
build/reviews-frontend.js 7.02 kB
build/vendors--cart-blocks/cart-line-items--cart-blocks/cart-order-summary--cart-blocks/order-summary-shi--c02aad66-frontend.js 5.26 kB
build/vendors--cart-blocks/cart-line-items--checkout-blocks/order-summary-cart-items--mini-cart-contents---233ab542-frontend.js 3.14 kB
build/vendors--cart-blocks/order-summary-shipping--checkout-blocks/billing-address--checkout-blocks/order--5b8feb0b-frontend.js 4.74 kB
build/vendors--cart-blocks/order-summary-shipping--checkout-blocks/billing-address--checkout-blocks/order--decc3dc6-frontend.js 20.5 kB
build/vendors--product-add-to-cart-frontend.js 7.53 kB
build/wc-blocks-data.js 9.87 kB
build/wc-blocks-editor-style-rtl.css 5.08 kB
build/wc-blocks-editor-style.css 5.08 kB
build/wc-blocks-google-analytics.js 1.56 kB
build/wc-blocks-middleware.js 930 B
build/wc-blocks-registry.js 2.7 kB
build/wc-blocks-shared-context.js 1.52 kB
build/wc-blocks-shared-hocs.js 1.14 kB
build/wc-blocks-style-rtl.css 22.2 kB
build/wc-blocks-style.css 22.2 kB
build/wc-blocks-vendors-style-rtl.css 1.28 kB
build/wc-blocks-vendors-style.css 1.28 kB
build/wc-blocks.js 2.63 kB
build/wc-payment-method-bacs.js 816 B
build/wc-payment-method-cheque.js 811 B
build/wc-payment-method-cod.js 909 B
build/wc-payment-method-paypal.js 837 B
build/wc-settings.js 2.61 kB

compressed-size-action

@dinhtungdu dinhtungdu marked this pull request as ready for review June 30, 2022 08:37
@rubikuserbot rubikuserbot requested review from a team and albarin and removed request for a team June 30, 2022 08:37
@dinhtungdu dinhtungdu added status: needs review type: enhancement The issue is a request for an enhancement. block: all products Issues related to the all products block. block-type: filter blocks Issues related to all of the filter blocks. labels Jun 30, 2022
@dinhtungdu
Copy link
Member Author

Requesting additional reviews because this is a quite big PR.

Copy link
Contributor

@albarin albarin left a comment

Choose a reason for hiding this comment

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

Nice work! Works 👌

@dinhtungdu
Copy link
Member Author

Nice work! Works 👌

@albarin Thanks for your review and testing! Do you think we should let stores enable/disable the URL updating function when filtering the All Products Block?

@dinhtungdu dinhtungdu changed the title Fix: Add support to apply filters via URL when it is used the All Products block and a Product Filter block Fix: Add support to apply filters via URL for All Products block Jul 4, 2022
@albarin
Copy link
Contributor

albarin commented Jul 4, 2022

@albarin Thanks for your review and testing! Do you think we should let stores enable/disable the URL updating function when filtering the All Products Block?
Not sure if doing that would provide much value, I might be missing something, do you think by enabling this by default we could bother some users? maybe break something? 🤔

@nielslange nielslange modified the milestones: 8.0.0, 8.1.0 Jul 4, 2022
@dinhtungdu
Copy link
Member Author

Not sure if doing that would provide much value, I might be missing something, do you think by enabling this by default we could bother some users? maybe break something?

@albarin You're right! I also don't think it will bother users. Because if users add filter blocks to pages, they already want to filter products.

Copy link
Contributor

@Aljullu Aljullu left a comment

Choose a reason for hiding this comment

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

Nice to see this improvement! Everything seems to be working fine except the back/forward button in the All Products block with filters:

Kooha-07-06-2022-13-27-08.mp4

In the screencast above, you will notice that I have to press twice for the query URL to be cleared, and even when doing so, the filter is not cleared. Is that something that would be easy to fix?

The codebase of filter blocks are similar and I think we should refactor and extract the common logic to share between them during the cooldown periods.

Good idea! Could you create an issue for this?

@dinhtungdu
Copy link
Member Author

@Aljullu In 0c2e198, I use replaceState instead of pushState to avoid creating new history entries.

Clearing/updating the filter on history changes is possible but we need to create a router for that purpose. By the way, using pushState will create a new entry on every change to the query state. So I think the optima direction here is using the replaceState method. What do you think?

@dinhtungdu
Copy link
Member Author

Good idea! Could you create an issue for this?

Looking closer at filter blocks, the logic of common actions is quite different for each filter block. In 2a94b77, I extract the logic that updates the URL or reloads the page. At the moment, it's the only logic that is worth extracting IMO. So I don't think we need to create an issue anymore.

Copy link
Contributor

@Aljullu Aljullu left a comment

Choose a reason for hiding this comment

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

Clearing/updating the filter on history changes is possible but we need to create a router for that purpose. By the way, using pushState will create a new entry on every change to the query state. So I think the optima direction here is using the replaceState method. What do you think?

Makes sense and it's testing alright. 👍

Looking closer at filter blocks, the logic of common actions is quite different for each filter block. In 2a94b77, I extract the logic that updates the URL or reloads the page. At the moment, it's the only logic that is worth extracting IMO. So I don't think we need to create an issue anymore.

Sounds good.

@dinhtungdu dinhtungdu merged commit 3bc4499 into trunk Jul 11, 2022
@dinhtungdu dinhtungdu deleted the fix/6441 branch July 11, 2022 07:04
@Marc-pi
Copy link

Marc-pi commented Jul 11, 2022

@Aljullu / @dinhtungdu

we should let stores enable/disable the URL updating function when filtering the All Products Block?
please don't, changing url per query is a very very bad practice in term of SEO. You generate duplicate content.
Please use hashbang instead (#!), but the better is to not use query strings in url at all

Should we disable the new behavior by default and let developers enable it by a filter or setting?
yes, but again please please avoid pushing query string vars in url (get)

@dinhtungdu dinhtungdu restored the fix/6441 branch July 11, 2022 07:24
@dinhtungdu
Copy link
Member Author

@Marc-pi Thanks for your comments! I agree that we should ensure the plugin optimized for SEO. I have some questions related to your comments and love to hear your options:

please don't, changing url per query is a very very bad practice in term of SEO. You generate duplicate content.
Please use hashbang instead (#!), but the better is to not use query strings in url at all

WC has been applying filters through URL for a long time with filter widgets. I'm wondering how stores are dealing with the filter URL.

From my research, we can use the canonical tag to avoid duplicated content issue according to this page. What do you think?

A better solution is to allow search engines to crawl these URLs, but mark them as duplicates by using the rel="canonical" link element or 301 redirects.

(Thanks @Aljullu for the reference!)

The URL doesn't exist in DOM, the URL is changed by JS when users interact with the filter blocks. So we don't provide them to search engines. Do search engines still be able to index those URLs?

@Marc-pi
Copy link

Marc-pi commented Jul 12, 2022

@dinhtungdu / @Aljullu

"WC has been applying filters through URL for a long time with filter widgets."
yep, that's why SEO are looking for some dedicated plugins that manage this better.

Level 1 - There dirty method is to add noindex on the page each time an attribute / filter is checked
Level 2 - The right method is indeed the canonical tag as explained in Google Dev Doc.
Level 3 - The expert method is to open facets when needed (to decide to index some long tail queries) but it harder to manager because we need for that to also personalize meta description & title tag, and add noindex to others.

Please note also that we need to take care about the filter anchors. Please do not use a pure a:ref value but encapsulate it in a button with onclick event / location href value, for instance, so crawlers do not follow the url.

From my knowledge Filtereverything can manage the level 3, but there should exists for sure some other plugins
Step 3 could be left to dedicated plugins i think, or later PR. Please avoid also nofollow value.

see https://filtereverything.pro/resources/seo-rules/
and https://yithemes.com/themes/plugins/yith-woocommerce-ajax-product-filter

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
block: all products Issues related to the all products block. block-type: filter blocks Issues related to all of the filter blocks. type: enhancement The issue is a request for an enhancement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support to apply filters via URL when it is used the All Products block and a Product Filter block
5 participants