Search code examples
spartacus-storefront

How to create Pretty URL without ProductCode for PDP page in Spartacus?


Requirement:

The business provides a URL in the format as (":category/:name") and against this format, system will have an SKU defined for which PDP needs to be opened without changing the URL. e.g. for a defined URL -- https://example.com/categoryName/baseProductName and SKU (SKU123) will be configured in backend. When a customer opens the above URL, the PDP of SKU123 should load where the URL remains the same.

Spartacus code has a constraint that PDP cannot be opened without providing a product code (SKU number) to it. We have tried to override the routing configurations but internally spartacus is redirecting to a 404 page. In Spartacus Docs(https://sap.github.io/spartacus-docs/route-configuration/) it is mentioned that it is not allowed otherwise functionality will break.

I am looking for a workaround on the same to allow routing config as (":category/:name") and (":category/:name/:productCode") both which seems to be a constraint from Spartacus end. We can feed in the productCode but the URL needs to be as is.

The current PDP functionality should not break.

Spartacus: 1.4.4 SAP Commerce: 1905


Solution

  • that's an interesting question, and not straightforward to solve actually. I'll give you a few pointers to workaround.

    First off, Spartacus uses the product code as a unique key in all layers of the application. The code is used in the routing logic, in the store and to load the product from the backend.

    Moreover, the code is passed to the CMS, as the CMS is capable to resolve custom page structure per product; you can configure a specific CMS page structure for a specific product code or product category; therefor the product code is passed as an id to the CMS when loading.

    To workaround these features you need to configure and override a number of things:

    1. Bring product name into the routing configuration You can easily do this with the routing configuration, or just by provide a paramsMapping from product.code to product.name. More on this can be found at the docs. Additionally, you could prettify the product name (avoid spaces and other characters to avoid ugly encoding)

    2. Bring the category name into the routing configuration Before you can configure the router (see 1) for the category name, you need to get the category from the backend. You can do this by normalising the (first) category from the product model. However, by default the product doesn't contain the categories, which is why you'd need to configure the OCC field configuration. It's all described at https://sap.github.io/spartacus-docs/connecting-to-other-systems/. Special attention is required for the SOLR results, as they also need to expose the categories. Additionally, you could prettify the product name (avoid spaces and other characters to avoid ugly encoding)

    3. Change the product key internally To ensure that the category name and product name are used instead of the product code to store (ngrx) and load (OCC) the product, you need to trick the system. You can provide a custom implementation of the CurrentProductService, where you'd evaluate if the Router state contains the category name and product name parameters. If those parameters are available, you would concatenate them so that they can later on be reconstructed.

    4. Load product data by category and product name You could introduce a custom adapter to resolve the product code by it's category and product name, but i'd not recommend this. It would involve an additional API call, and that's expensive. Instead, I would implement a custom backend endpoint, that takes the the category and product name. You could still provide a custom adapter in Spartacus, for deconstructing the concatenated category and product name from step 3, as this would result in a cleaner code base.

    5. Load CMS product page by category and product name The CMS uses the product code (id) as well to load the right cms structure. You could do 2 things here: a. use the same pattern from step 4; create custom OCC endpoint to resolve the product code and then load the right CMS product page structure b. use a static (but existing) product code in a customer OccCmsPageAdapter, to load the same CMS structure for all product pages. This will obviously block existing CMS functionality, but it might be ok. Or at least for your first implementation you can get it to work with this workaround.

    Hope that gives you an idea or 2.

    All of this being said, I believe this is quite an uncommon requirement. Not that you need pretty URLs and want to use the product name as a unique "code". But using both the category name and product name as a unique key. If possible, I'd try to move into this pattern:

    • use the product category and product name in the title for SEO purposes (exactly as you require)
    • only depend on the product code as being the unique property
    • change the product code structure in the backend; the product.code there are various ways to do this, the idea is that the actual product code could be stored in an alternative field, and the generated (based on name) product.code in the native code field.
    • all application logic (UIs, APIs, SOLR, Spartacus) will transparently use the product name as the unique key.