Shopify Messaging allows brands to create personalised marketing emails using Liquid variables.
This makes it possible to build email experiences where every customer receives a different link or image, including:
- Unique QR codes
- Membership links
- Loyalty account links
- Apple Wallet links
- Google Wallet links
- Personalised offers
- Customer-specific landing pages
The important part is understanding what customer data Shopify makes available inside an email.
Shopify Messaging supports Custom Liquid and HTML, including custom buttons, images and layouts. It also exposes customer variables such as customer.id, customer.email, customer.first_name and customer.tags.
However, Shopify currently limits Custom Liquid emails to its documented supported-variable list. Customer metafields aren’t included in that list.
That creates a common problem:
How do you use customer-specific information stored in Shopify metafields inside a Shopify email?
The cleanest solution is to use the Shopify customer ID as the bridge between the email and an external service.
The basic architecture
Instead of trying to put this directly into Shopify Messaging:
{{ customer.metafields.custom.apple_link.value }}
you pass the customer’s Shopify ID:
{{ customer.id }}
For example:
<a href=”https://example.com/wallet/apple?customer_id={{ customer.id }}”>
Add to Apple Wallet
</a>
When Shopify sends the email, the Liquid variable is resolved separately for each recipient.
One customer might receive:
https://example.com/wallet/apple?customer_id=123456789
while another receives:
https://example.com/wallet/apple?customer_id=987654321
Shopify specifically documents customer.id as a supported variable for Shopify Messaging emails.
The external application can then use that ID to retrieve whatever customer-specific information it needs.
Step 1: Create your Shopify customer metafields
Start by deciding what personalised data you want to store.
For a digital membership or wallet implementation, you might create:
Namespace: custom
apple_link
google_link
qr_code_url
A customer’s Shopify profile could therefore contain:
custom.apple_link
https://example.com/apple/abc123
custom.google_link
https://example.com/google/abc123
custom.qr_code_url
https://example.com/qr/abc123.png
Shopify metafields are attached to resources such as customers and are identified by their namespace and key.
Shopify’s Admin GraphQL API also exposes customer metafields programmatically.
Step 2: Insert a personalised link into Shopify Email
Create or edit your campaign in Shopify Messaging and add a Custom Liquid section.
For an Apple Wallet link:
<a href=”https://api.example.com/shopify/apple?customer_id={{ customer.id }}”>
Add to Apple Wallet
</a>
For Google Wallet:
<a href=”https://api.example.com/shopify/google?customer_id={{ customer.id }}”>
Add to Google Wallet
</a>
Shopify replaces:
{{ customer.id }}
with the ID of the actual email recipient.
The flow becomes:
Customer receives Shopify email
↓
Customer clicks link
↓
Shopify customer ID is sent
↓
External application identifies customer
↓
Application retrieves customer-specific link
↓
Customer is redirected
Step 3: Make an image clickable
You don’t need to use a text link.
Shopify Messaging supports custom HTML and custom images inside Custom Liquid sections.
For example:
<a href=”https://api.example.com/shopify/apple?customer_id={{ customer.id }}”>
<img
src=”https://example.com/images/add-to-apple-wallet.png”
alt=”Add to Apple Wallet”
width=”180″
>
</a>
Every customer sees the same button image, but the destination behind the image is unique to them.
The same principle works for Google Wallet:
<a href=”https://api.example.com/shopify/google?customer_id={{ customer.id }}”>
<img
src=”https://example.com/images/add-to-google-wallet.png”
alt=”Add to Google Wallet”
width=”180″
>
</a>
How to add a unique QR code to every Shopify email
This is where the technique becomes particularly useful.
An <img> tag doesn’t require its image source to be static.
The image source can itself contain the Shopify customer ID.
For example:
<img
src=”https://api.example.com/shopify/qr?customer_id={{ customer.id }}”
alt=”Your QR code”
width=”220″
>
Shopify might send the first customer:
<img src=”https://api.example.com/shopify/qr?customer_id=123456789″>
and the next:
<img src=”https://api.example.com/shopify/qr?customer_id=987654321″>
Your server receives the request, determines which Shopify customer is involved, and returns that customer’s QR image.
The result is:
One Shopify campaign
↓
100,000 recipients
↓
100,000 customer IDs
↓
100,000 unique QR codes
You don’t need to manually build 100,000 emails.
What happens on the backend?
Your application needs an endpoint such as:
GET /shopify/qr
which accepts:
customer_id=123456789
The backend can then query the Shopify Admin API for that customer.
Conceptually:
query CustomerWalletData($id: ID!) {
customer(id: $id) {
appleLink: metafield(
namespace: “custom”
key: “apple_link”
) {
value
}
googleLink: metafield(
namespace: “custom”
key: “google_link”
) {
value
}
qrCode: metafield(
namespace: “custom”
key: “qr_code_url”
) {
value
}
}
}
Shopify’s Customer object supports retrieving metafields by namespace and key and requires the relevant customer-data access permissions.
Your application then has three possible behaviours.
For Apple:
/apple
↓
retrieve custom.apple_link
↓
redirect customer
For Google:
↓
retrieve custom.google_link
↓
redirect customer
For QR:
/qr
↓
retrieve custom.qr_code_url
↓
return QR image
Complete Shopify Email example
A complete Custom Liquid section could look like this:
<div style=”text-align:center;”>
<p>Add your membership to your phone:</p>
<!– Apple Wallet –>
<a href=”https://api.example.com/shopify/apple?customer_id={{ customer.id }}”>
<img
src=”https://example.com/images/apple-wallet.png”
alt=”Add to Apple Wallet”
width=”180″
style=”border:0;”
>
</a>
<br><br>
<!– Google Wallet –>
<a href=”https://api.example.com/shopify/google?customer_id={{ customer.id }}”>
<img
src=”https://example.com/images/google-wallet.png”
alt=”Add to Google Wallet”
width=”180″
style=”border:0;”
>
</a>
<br><br>
<p>Or scan this QR code with your phone:</p>
<!– Unique customer QR –>
<img
src=”https://api.example.com/shopify/qr?customer_id={{ customer.id }}”
alt=”Your unique QR code”
width=”220″
>
</div>
The merchant only manages one email. The personalisation happens automatically. A final example may look like the following:

Why not reference the metafield directly?
In other Shopify Liquid environments, you might normally reference a customer metafield using syntax such as:
{{ customer.metafields.custom.apple_link.value }}
But Shopify Messaging only permits its documented set of supported Liquid variables, and customer.metafields isn’t currently included.
So rather than relying on unsupported Liquid:
Shopify Email
→ customer metafield
use:
Shopify Email
→ customer.id
→ your application
→ Shopify API
→ customer metafield
This also keeps the integration logic outside the email template.
Dynamic images can go beyond QR codes
The same architecture can be used for any customer-specific image.
For example:
<img src=”https://api.example.com/member-image?customer_id={{ customer.id }}”>
Your application could return a different image depending on:
Gold Member
Silver Member
Bronze Member
$10 Reward Available
$20 Reward Available
VIP Member
Points: 1,250
Reward Expiring Soon
That allows a Shopify email to display content generated specifically for the person opening it.
Important security consideration
Avoid treating a bare Shopify customer ID as authentication.
Something like:
?customer_id=123456789
is useful as an identifier, but it shouldn’t automatically grant access to sensitive account information or transferable rewards.
If the QR code, wallet pass or destination provides access to valuable or private customer data, the implementation should use an appropriate secure token or verification layer.
Shopify also treats customer information as protected customer data and requires apps to request only the access needed for their functionality.
Using this with Apple Wallet and Google Wallet
For a platform such as Litecard, this architecture creates a simple bridge between Shopify and the mobile wallet.
The merchant can send a normal Shopify campaign containing:
Add to Apple Wallet
Add to Google Wallet
Unique QR Code (for Desktop users)
while Litecard handles:
Shopify customer identification
↓
Customer data lookup
↓
Wallet pass identification
↓
Apple / Google Wallet destination
↓
Dynamic QR generation
This means Shopify remains the email platform while the wallet platform handles the customer-specific wallet experience. The architecture and concept are very similar to if you are using Litecard with Klaviyo, Braze, Dotdigital, Insider One, Mailchimp, etc. (any other CDP/CEP)
In summary
Shopify Messaging already gives developers enough customer-level context to create highly personalised links and images because customer.id can be inserted dynamically into Custom Liquid.
The key is not to force customer metafields directly into the email.
Instead:
1. Store the personalised data against the Shopify customer.
2. Pass {{ customer.id }} from Shopify Messaging.
3. Resolve the customer’s metafields through your backend.
4. Return the correct link, image or QR code.
That creates a reusable architecture for personalised QR codes, loyalty journeys, membership experiences and Apple or Google Wallet activation directly from Shopify email.
Want to add personalised Apple Wallet and Google Wallet experiences to Shopify?
Litecard connects Shopify customer data with Apple and Google Wallet, allowing brands to distribute personalised wallet passes, QR codes and customer-specific wallet experiences directly through their existing marketing channels.
Scanning customers in at PoS? You can use Litecard’s Shopify PoS app here too: https://apps.shopify.com/litecard-pos
If you want to learn more about how Litecard works with other platforms, you can read our knowledge base here: https://litecard.com/knowledge-base/