Use Case: A Shopify Multi-Currency enabled store using Markets has a lightweight 'Membership' program where a secondary price is provided to logged-in customers with an active membership state.
Approach: A Cart Transform Function is handling an adjustment to the cart & checkout price of a product based on a metafield value. The Function's logic applies a currency adjustment to the metafield value to account for multi-currency scenarios. I also want to show that metafield value as a secondary price on the PDP, also accounting for the currency conversion of that value to match the cart & checkout price as calculated by the Function.
Problem: Liquid cannot easily access the same 'presentmentCurrencyRate' field that's accessible via the Functions API.
I ran into this problem recently, and it had me stuck at a strange dead-end I didn't expect. My Cart Transform function was working perfectly, returning a fixedPricePerUnit
that properly accounts for multi-currency scenarios by modifying a Metafield value by the cart's current presentmentCurrencyRate
.
function optionallyBuildUpdateOperation(
{ id: cartLineId, merchandise },
presentmentCurrencyRate
) {
if (
merchandise.__typename === "ProductVariant" &&
merchandise.product &&
merchandise.product.metafield &&
merchandise.product.metafield.value
) {
return {
cartLineId,
price: {
adjustment: {
fixedPricePerUnit: {
amount: Number(merchandise.product.metafield.value) * Number(presentmentCurrencyRate)
}
}
}
};
}
return null;
}
And I had a really simple Liquid snippet in the PDP template that pulled in the same member_price
metafield to show the customer what they can expect when compared to the non-member regular price:
{% if product.metafields.custom.member_price %} <p><b>Member Price:</b></br>{{ product.metafields.custom.member_price }}</p> {% endif %}
But when that's in place, we obviously get a strange mismatch for other regions where the member_price
is a value set in the shops' base currency and isn't adjusted for the active market.
One solution could presumably be to store multiple member_price
metafields that are all individually adjusted per region, like member_price_uk
+ member_price_us
, etc.
But if we consider that larger businesses are most likely feeding their price maps to Shopify via the Product API from a PIM or other source of truth, that's getting pretty complex very quickly and waters down data quality over time. I like the relative security of letting the Store's configured currency rates in Markets settings determine the conversion as opposed to multiple hard-coded prices.
So another possible solution is to use Shopify's provided .js file with live currency conversion rates to return a value to my liquid snippet based on the active country code.
/services/javascripts/currencies.js
This seemed like overkill to me. Also, I didn't love the idea of modifying the price.liquid base snippet and pulling in a bunch of live rates the store might not even use. Larger businesses are much more likely to set static conversion rates that suit their needs, which mirrors what I have set up in my Demo store.
eg. USD = x1.3, EUR = x1.5, CAD = x1.8
Okay, so now that we know the rates are fine as static conversion, we can do some simpler things just within my liquid snippet. Shopify gives us the active market through Liquid with the localization object:
localization.market.handle
That should mirror what the Cart Transform is accessing as the presentmentCurrencyRate -- as long as the Market has a static currency rate across all the regions it serves (which is luckily a lot more common than showing prices in the customer's local currency).
So now I can assign the market to a specific converted price that I define in the liquid snippet:
{% assign market_handle = localization.market.handle %}
{% if product.metafields.custom.member_price %}
{% assign member_price = product.metafields.custom.member_price %}
{% if market_handle == 'north-america' %}
{% assign converted_price = member_price | times: 1.3 %}
{% elsif market_handle == 'europe' %}
{% assign converted_price = member_price | times: 1.5 %}
{% elsif market_handle == 'canada' %}
{% assign converted_price = member_price | times: 1.8 %}
{% else %}
{% assign converted_price = member_price %}
{% endif %}
<p><b>Member Price:</b></br>{{ converted_price | money_with_currency }}</p>
{% endif %}
Sweet. That's better.
Now if the shop ever wants to adjust their hard-coded currency conversion rates, they can do that much more easily just within a Liquid snippet in the Theme Editor, as opposed to within the theme code itself.
If you want to see the full Cart Transform Function code for this app that's essentially a lightweight membership program, I have it public here:
Github - Mackiec Extensions Prod - Update Line Item
âď¸