Closed westonruter closed 4 months ago
I reported this problem on the support forum. The 1.2.1 fixed the problem as it was. Then I added speculation rules using this script:
<script type="speculationrules">
{
"prerender": [{
"where": {
"and": [
{ "href_matches": "/product/*" },
{ "not": {"selector_matches": ".do-not-prerender"}}
]
},
"eagerness": "eager"
}]
}
</script>
The intention was to give product pages higher priority in prerendering while still having two available on hover "slot" provided by the "Moderate" setting. I used the template found here.
That's what happened: video.
Some products are still automatically added to cart. It looks like the culprits are the add to cart links /?add-to-cart=
in the related products boxes, like I highlighted in the video.
I can't share the URL because it's a staging I'm developing for a client, but I can privately grant admin access.
@masvil Thanks. Can you share the HTML for the related products boxes? Do the links not have rel=nofollow
like the WooCommerce's product add-to-cart template includes by default?
This is basically what 1.2.1 does now:
<script type="speculationrules">
{
"prerender": [
{
"where": {
"and": [
{"href_matches": "/*"},
{"not": {
"selector_matches": [
".do-not-prerender",
"[rel=nofollow]"
]
}},
{"not": {
"href_matches": [
"\/wp-login.php",
"\/wp-admin\/*",
"/*?*(^|&)_wpnonce=*"
]
}}
]
},
"eagerness": "moderate"
}
]
}
</script>
That is it excludes some WordPress specific stuff:
[rel=nofollow]
- this is not WordPress specific but some of the WooCommerce links are only decorated with this./wp-login.php
/wp-admin/*
/*?*(^|&)_wpnonce=*
- this is a unique nonce set as a URL param and used by WooCommerce for some cart linksIf you want to add your own rules on top, then you need to be aware of these types of specifics. Rather than copying from a generic article, it would be better to have looked at the rendered DOM in the Elements panel in DevTools to see what the plugin added and modified that.
Saying that, earlier today I added the [rel=nofollow]
to the example in the article you referenced (refresh to see it) as that seemed a sensible one to add. However the intent is not to list all WordPress or WooCommerce-specific things (or any other platform).
BTW, IMHO WooCommerce should not be performing changing requests in links (GET—HTTP requests as links are—are supposed to be "safe" by HTTP standards) but such is the varied web we live in. It's incredibly forgiving when people do things that aren't really correct, until it's not.
Also note that Chrome is limited to 10 prerenders per page. So really wouldn't recommend eagerly prerendering many links on the page. You can see in that video that only the first 10 succeeded anyway.
I've opened https://github.com/WordPress/performance/issues/1156 to extend the plugin with the ability to add additional rules to the speculationrules. So with that, you would be able to do the following to add the rule in https://github.com/WordPress/performance/issues/1140#issuecomment-2060034357 to the existing ruleset:
add_filter(
'plsr_speculation_ruleset',
static function ( array $ruleset ): array {
$ruleset['prerender'][] = array(
"where" => array(
"and" => array(
array( "href_matches" => "/product/*" ),
array( "not" => array( "selector_matches" => array(
".do-not-prerender",
"[rel=nofollow]", // 👈 added
) ) )
)
),
"eagerness" => "eager"
);
return $ruleset;
}
);
~It's important to remember that only one speculationrules
script can be on the page at a time.~ Actually, this is not true. See Multiple speculation rules. h/t @tunetheweb
@masvil Oh, and to @tunetheweb's point, it seems your rule was lacking the rel=nofollow
exclusion (presuming the template includes rel=nofollow
on the add-to-cart buttons). So that should be included as well.
Do the links not have
rel=nofollow
like the WooCommerce's product add-to-cart template includes by default?
Those links have rel=nofollow
.
and to @tunetheweb's point, it seems your rule was lacking the
rel=nofollow
exclusion (presuming the template includesrel=nofollow
on the add-to-cart buttons). So that should be included as well.
Done. Indeed, the following script works good:
<script type="speculationrules">
{
"prerender": [{
"where": {
"and": [
{ "href_matches": "/product/*" },
{ "not": {"selector_matches": ".do-not-prerender"}},
{ "not": {"selector_matches": "[rel=nofollow]"}}
]
},
"eagerness": "eager"
}]
}
</script>
it would be better to have looked at the rendered DOM in the Elements panel in DevTools to see what the plugin added and modified that.
Lesson learned, thank you.
Saying that, earlier today I added the
[rel=nofollow]
to the example in the article you referenced (refresh to see it) as that seemed a sensible one to add.
Thank you!
Bug Description
As reported on the support forum, users browsing a site with WooCommerce and the Speculative Loading plugin can end up getting products added to their shopping cart by just hovering over the Add to Cart button when in moderate eagerness (the default setting). What's worse is when the eager eagerness setting is enabled, all the products on the page can be added to the cart just by visiting the page.
Steps to reproduce
Screenshots
Screen recording 2024-04-15 11.49.08.webm
Additional Context
When not using a block theme, this is the code to create the add-to-cart button: https://github.com/woocommerce/woocommerce/blob/a8e84d8c8b20558f66ed33dcbee6c1dec300752f/plugins/woocommerce/includes/wc-template-functions.php#L1363-L1403 https://github.com/woocommerce/woocommerce/blob/a8e84d8c8b20558f66ed33dcbee6c1dec300752f/plugins/woocommerce/templates/loop/add-to-cart.php#L27-L32
Note an
a
tag is always used. Contrast with the block code: https://github.com/woocommerce/woocommerce/blob/a8e84d8c8b20558f66ed33dcbee6c1dec300752f/plugins/woocommerce/src/Blocks/BlockTypes/ProductButton.php#L74-L231Here a
button
is used when AJAX is enabled.In both cases, however,
rel=nofollow
is present (although it can be filtered out by thewoocommerce_loop_add_to_cart_args
filter). It's unfortunate that since these add-to-cart links aren't idempotent (i.e. they have an action) that they don't also have_wpnonce
query parameters.