I have a javascript that handles the product listing on the collection page. Is there a way to ensure that the product is available and not out of stock. I need something similar to {% if product.available %}. But I don't want to change the .liquid file. I need it in Javascript.
You can get the JSON representation of an arbitrary product in your store by fetching data from /products/<some-product-handle>.js. When using the .js endpoint, the product object will include a number of aggregate parameters, including product.available which will be true if at least 1 variant in the product is available.
Note that Shopify has 2* different product representations, one at the /products/<some-product-handle>.js endpoint and one at the /products/<some-product-handle.json endpoint. These two objects are surprisingly different, and one of those differences is that the .json endpoint does not have the aggregate product.available value - you would have to determine that yourself by checking the availability of all the variants within if using this endpoint. This is one of the reasons why I generally recommend using the .js endpoint for all your Javascript needs.
* Strictly speaking, there's actually 3 different product representations: the output from a {{ product | json }} drop from Liquid is slightly different from both endpoints but largely the same as the .js endpoint, with the exception being how the product.options array is structured
You have four options for getting data into javascript in Shopify:
If the javascript is included as an inline script tag / a snippet in the liquid file then you’d be writing javascript liquid and you can interpolate directly e.g. var product = "{{ product | json}}".
You can update the liquid document to include e.g. attributes with the required data, e.g ‘data-‘ attributes, and then read those with javascript from the document. You’ve said this is not an option.
Re-fetch some data about entities on the current page using a Shopify API: e.g Ajax / Storefront / Shopify Buy SDK.
Add an alternative liquid page for an existing theme page that formats the data you need to json (e.g. {{ product | json }}) but name it e.g. product.ajax.liquid - this will make it into a custom view. Then you can fetch this pages url with the query parameter ?view=ajax and returned document will include the rendered json. This effectively creates a custom API for you.
Those are the options.
Related
I'm trying to display the item data from the metafield on the checkout page using this code-
{{ pages.package-urls.metafields.custom.checkout_message }} on checkout.liquid file.
We are using Shopify Plus and the metafields are displaying on other templates fine.
As usual, you are falling victim to the documentation. Since you want to display a metafield, if you truly know it has a value, you have to express you want the value. I think your attempt at using the pages object is mis-guided, as checkout is not a page, but, you may be right there, and it may in fact be available in checkout. Anyway, tack on a value.
{{ pages.package-urls.metafields.custom.checkout_message.value }}
As you read your metafield out backwards though, you will see that you are breaking all kinds of rules. Specifically. A metafield resource has a value. It has a key (checkout_message), it has a namespace (custom) and it has a parent resource (metafields in Shop, or Product, or Page).
So what are you doing with package-urls and pages? Strange stuff. I think you might want to anchor this to the Shop. That will likely work a lot better.
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
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:
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)
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)
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.
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.
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.
Stencil provides access the Custom Fields of a Product in a template file as documented in Product Other Details
{{product.custom_fields}}
{{#each custom_fields}}
<li>{{name}}: {{{value}}}</li>
{{/each}}
How do I access the MetaFields that are created in the Product API
POST /catalog/products/{product_id}/metafields?
Product metafields aren't currently surfaced as a Stencil property. Their original purpose was to store metadata against the product object for backend apps (data like shipping origin for ShipperHQ), so they're available via the REST API but not exposed on the front end. If you wanted to access metafields on the frontend, you could build out middleware (using a serverless function, for example) to call the API and pipe that data to the storefront.
It would be good for us to understand your use case better though. Do you want to display metafield values in the template, or base some kind of frontend logic around their values?
While one cannot natively display product metafields in Stencil, there is an app in the Bigcommerce marketplace that allows one do to so. The app also lets one view, create, update, and delete metafields for products, categories, variants, and brands. You can export metafields and import them with a csv file. The app is not free, however, there is a 7 day free trial. This answer is to give an alternative solution to the problem mentioned.
On this page https://stencil.bigcommerce.com/docs/product-resources BigCommerce has mentioned that Product Object has "Options" but in the theme, I am not able to retrieve anything from options property. I am trying to access this in Category Page.
I want to do above because I have to add product attributes on product listing page "templates\components\products\card.html". I need this here because I have to remove quick view option and directly put the product option under product title on this page. Over here I am able to get product's id, name, sku etc but not getting any properties from product options.
I have already asked to BigCommerce Support team and they don't have any solutions and referred me to check here.
The category page calls the common product card model, which does not include the product options property:
https://stencil.bigcommerce.com/docs/common-product-card-model
To get product option data on the category page, you'll need to call the API. One lightweight solution for handling this is to use AWS Lambda with Amazon API Gateway. API Gateway defines an endpoint URL that you can use to trigger a Lambda function that runs a request to the BigCommerce API for product data.
https://docs.aws.amazon.com/lambda/latest/dg/with-on-demand-https.html
I'm toying with developing a Shopify App that uses the DaisyAPI dynamic image service for Shopify. In order to make the correct call to the Daisy API, I need to know what Product the customer is looking at. It seems like, to reliably do that, I will need to manipulate their product.liquid theme to insert a hidden value containing the Product ID so that Jquery can pick up that value and insert it into the API call.
What's the best way to ensure every product page contains the product ID in such a way jQuery can reliably find it? Am I overlooking something obvious?
Many thanks!
Another option would be to use the Ajax API to request the product. Of you know you're on a product page simple make a request to the same URL and append .json. You will then have a json representation of the product that you can do whatever yo want with.
To get you js into the theme you can use a script tag which will load js from you server onto the shop.
You are missing a very obvious and cool Liquid filter.
In Liquid, pump the Object for it's JSON.
var p = {{ product | json }};
And then go to town... you cannot go far on the client without this concept. Get the JSON man.. get the JSON...