Add support for variant id product URLs via redirect - #3952
Conversation
Assisted-By: devx/e521c41d-1f69-4cf4-a15b-500550b56ab0
Assisted-By: devx/55056b40-7bff-48b1-b3d3-f70d0c9b35c5
frandiox
left a comment
There was a problem hiding this comment.
I think it makes sense to handle it as a redirect, but perhaps we should consider this as a core feature instead of as an optional handler? Left a comment below with more thoughts 👍
Move Liquid-style variant URL redirects into handleShopifyRoutes so routeTemplates and i18n pathPrefix are configured once. Keep registered route handlers as exact-path groups, restrict redirect statuses, and update docs/templates for the new wiring. Assisted-By: devx/ae222d2c-c26f-4eeb-8dde-5cfd0ca36c0d
Assisted-By: devx/ae222d2c-c26f-4eeb-8dde-5cfd0ca36c0d
it's now a core feature! not much had to be moved, it works pretty smoothly now |
|
Having now second thoughts on this: the PR is good and is a good feature. However, it seems Liquid doesn't support the options pattern for URLs (I thought it did), only Certain features like Storefront Agent currently depend on reading the variant ID from the URL to know in which product/variant we showing in the page. If we implement this via redirects, we'll be removing the id from the URL, thus removing that context. We don't necessarily need to solve this by adding the variant id to the URL, there are also other alternatives (making SA resolve options the Hydrogen-style, or giving this variant id context in another way e.g. via I wonder if there's a way to somehow keep both variant and options in the URL:
@andguy95 @fredericoo Is this worth considering? Or perhaps not very interesting for headless? |
looks very hacky and goes even more against the customisability aspect of hydrogen "you own your URLs" i would push towards making the SF Agent be able to understand variant id from option values in the URL (but this requires a query), or straight off the DOM (we do have the variantId there in the add to cart button, we just dont surface it in the URL – it can be read) |
|
Yeah not a huge fan of having the variant be a required param to be in the URL. We should let that decision fall back to how the users want to display it. It maybe worth having a strategy config in the API help users easily set up canonical params vs variant params. But either case, I agree we should find a better location to expose the selected variantid for external consumers to use. |
TL;DR: Let Hydrogen product pages accept Liquid-style
?variant=<numeric id>links while keeping option params as the canonical product selection URL.Before
Product loaders only understood option params:
?variant=123was treated like an option namedvariant, and template URL helpers could preserve stalevariantparams while switching options.After
handleShopifyRoutesnow accepts the app route templates once:That lets Hydrogen recognize Liquid-style product links before framework routing:
and redirect them to the canonical option-param URL for the resolved variant.
What this changes
handleShopifyRoutespre-route check for product?variant=<numeric id>URLs.routeTemplatestohandleShopifyRoutesoptions so product URLs are recognized from the app's routing manifest.pathPrefixfromrequestContext.i18n.pathPrefixinstead of asking callers to pass it separately.buildProductSelectionSearchParams()so templates and examples can build option-param or explicit variant links without preserving stale selection params.variantingetSelectedProductOptionsso loaders never treat it as a product option.301 | 302 | 303 | 307 | 308and validates that at runtime for JS callers.Developer impact
Includes a minor changeset for
@shopify/hydrogen.This adds
routeTemplatestohandleShopifyRoutes, addsbuildProductSelectionSearchParams(), and exposesShopifyRedirectStatus. The earlier optionalacceptProductVariantIdhandler and generic match-handler shape are no longer part of the public API for this PR.UX impact
Buyers landing on Liquid-style product links like
/products/foo?variant=123now land on the matching Hydrogen variant instead of the default variant. In-app option navigation still uses option params as the canonical URL.Out of scope
Risk
?variant=product links now do one Storefront API lookup before redirecting.allowedOptionNamesignore them.How to Test
pnpm install && pnpm --filter hydrogen dev./products/{handle}?variant={numericVariantId}./products/{handle}?OptionName=valueand the matching variant renders./products/{handle}?variant=not-a-number.