How to use order metafields in your theme
Unfortunately, order metafields are not supported by BigCommerce GraphQL storefront API. The only way to access them is through the REST management API.
You should not make requests directly to the Management API from the storefront because this would leak sensitive information to unauthorised users. The appropriate way to access order metafields would be to create a middleware service that accepted a request for metafields along with a current customer JWT and then ferried order metafields back to the theme.
This is a hassle, so we've built it for you.
Our Order Metafields API
For Metafield Manager subscribers, our app now offers an endpoint so that you can add JavaScript to your order detail page to fetch these metafields on page load.
Endpoint
https://metafields.space48apps.com/api/storefronts/{{store_hash}}/customers/{{jwt}}/orders/{{order_id}}/metafields
Params
- store_hash
- Your store identify, visible in the URL of your BigCommerce admin are
- jwt
- The JWT is retrieved by making a request to the current customer API with JS in your theme.
- order_id
- The ID of the order that you wish to load metafields for.
Example code
As an example, this JavaScript can be added to templates/pages/account/orders/details.html
Replace me
Note that you will need to add your store hash to this code. Search for "REPLACE ME".
<script type="text/javascript"> const store_hash = '%% REPLACE ME %%'; // Replace with your store hash const app_client_id = 'c0s7a28bku7ij79qte07ibtdedu619x'; // Metafields Manager Client ID const query_params = new URLSearchParams(window.location.search); const order_id = query_params.get('order_id'); const fetchCustomerJWT = async (app_client_id) => { const response = await fetch('/customer/current.jwt?app_client_id=' + app_client_id); if (!response.ok) { if (response.status === 404) { return new Error('Customer not logged in.'); } return new Error('Unable to identify customer'); } return await response.text(); } const fetchOrderMetafields = async (store_hash, jwt, order_id) => { const response = await fetch("https://metafields.space48apps.com/api/storefronts/" + store_hash + "/customers/" + jwt + "/orders/" + order_id + "/metafields"); if (!response.ok) { if (response.status === 404) { return new Error(response?.data?.error || "Sorry, no match found."); } else if (response.status === 402) { return new Error(response?.data?.error || "A subscription to Metafields Manager is required to perform this action."); } return new Error('Unable to fetch metafields'); } return await response.json(); } const useOrderMetafields = async (store_hash, app_client_id, order_id) => { const jwt = await fetchCustomerJWT(app_client_id); if (!jwt.length) { throw new Error('Unable to fetch JWT'); } const metafields = await fetchOrderMetafields(store_hash, jwt, order_id); // Do whatever you would like to do with metafields here, e.g. add to the page. console.log("Metafields: \n"); console.table(metafields.data); // For example, add them to the order details sidebar block. const formatted_metafields = metafields.data.map(function (metafield) { const capitalisedKey = metafield.key.charAt(0).toUpperCase() + metafield.key.slice(1); const capitalisedKeyWithSpaces = capitalisedKey.replace('_', ' '); return `<dt class="definitionList-key">${capitalisedKeyWithSpaces}</dt> <dd class="definitionList-value">${metafield.value}</dd>` }); const orderDetailsBlock = document.querySelector('.account-sidebar-block .definitionList'); orderDetailsBlock.innerHTML += formatted_metafields.join("\n"); } try { useOrderMetafields(store_hash, app_client_id, order_id); } catch (e) { console.log(e); } </script>
Once this is working, it would be reasonable to want to move this code into the a JS file, e.g the assets/js/theme/account.js. It would likely need some small adjustments to achieve this. Notably, the injection of the store hash and order ID into the jsContext so these can be accessed.