Shopify Metafields & Tags Reference
Appstle Loyalty uses Shopify metafields and tags to store loyalty program data, power storefront widgets, sync product reviews, and enable automation workflows. This reference covers every metafield and tag — what it contains, when it's set, and how to use it in your integration.
Appstle Loyalty uses three namespaces across multiple resource types:
| Namespace | Resources | Visibility | Purpose |
|---|---|---|---|
appstle_loyalty | Shop, Customer | Public (readable by any app/theme) | Loyalty program configuration, customer loyalty profiles |
$app:appstle_loyalty | Customer | Private (only readable by this app) | Customer reward discount codes for checkout |
appstle_review | Product, Shop | Public | Product reviews, ratings, and carousel data |
Private namespace note: The
$app:appstle_loyaltynamespace uses Shopify's app-owned metafield protection. Metafields in this namespace can only be read and written by the Appstle Loyalty app itself — not by themes, Liquid templates, or other apps.
These metafields store the complete loyalty program configuration and are used by the storefront widget to render the loyalty experience. They are written by SubscribeItScriptUtils.writeShopMetafield() whenever a merchant saves settings.
When updated: On every settings save in the Appstle admin, and when point rules or VIP tiers are modified. Updates are synchronous (immediate).
| Key | Type | Purpose |
|---|---|---|
app_url | string | App base URL for widget communication |
proxy_path_prefix | string | Custom proxy path prefix (default: apps/loyalty) |
public_domain | string | Store's public domain name |
shop_name | string | Store name from Shopify |
currency | string | ISO currency code (e.g., USD, EUR) |
store_front_access_token | string | Shopify Storefront API access token |
| Key | Type | Purpose |
|---|---|---|
bundle_js_path | url | CDN URL for widget JS bundle (with version params) |
bundle_css_path | url | CDN URL for widget CSS bundle (with version params) |
widget_setting | json | Full widget configuration object (colors, layout, positioning, etc.) |
shop_labels | json | Widget label translations (i18n support) |
| Key | Type | Purpose |
|---|---|---|
pointRoundType | string | Point rounding strategy: NO_ROUND, ROUND_DOWN, or ROUND_UP |
point_earn_rules | json | Array of all active point earn rules |
point_redeem_rules | json | Array of all active point redeem rules |
[
{
"id": 123,
"type": "PURCHASE",
"pointsPerDollar": 5,
"minimumOrderAmount": 0,
"enabled": true
},
{
"id": 124,
"type": "SIGNUP",
"fixedPoints": 100,
"enabled": true
},
{
"id": 125,
"type": "BIRTHDAY",
"fixedPoints": 200,
"enabled": true
}
][
{
"id": 456,
"type": "FIXED_AMOUNT",
"pointsCost": 500,
"discountValue": 5.00,
"discountType": "FIXED_AMOUNT",
"enabled": true
},
{
"id": 457,
"type": "PERCENTAGE",
"pointsCost": 1000,
"discountValue": 10,
"discountType": "PERCENTAGE",
"maxDiscountAmount": 50.00,
"enabled": true
}
]| Key | Type | Purpose |
|---|---|---|
enable_inactive_customer | boolean | Allow tracking inactive customers in the program |
has_dedicated_page_access | boolean | Access to dedicated loyalty page feature |
allow_customer_opt_in | boolean | Allow customer self-opt-in to the loyalty program |
enable_discount_to_apply_automatically | boolean | Auto-apply reward discounts at checkout |
show_store_credit_rewards | boolean | Show store credit rewards in the widget |
birthdate_format | string | Expected birthdate format (MM/DD, DD/MM, etc.) |
| Key | Type | Purpose |
|---|---|---|
referral_enabled | boolean | Referral program enabled flag |
referral_loyalty | json | Referral config (discount type, tags, amounts) |
{
"referrerDiscountType": "PERCENTAGE",
"referrerDiscountValue": 10,
"referredDiscountType": "FIXED_AMOUNT",
"referredDiscountValue": 5.00,
"referrerPoints": 500,
"referredPoints": 200
}| Key | Type | Purpose |
|---|---|---|
vip_tier_enabled | boolean | VIP tier program enabled flag |
vip_tiers | json | Array of VIP tier definitions |
vip_rewards | json | VIP tier-specific point redeem rules |
vip_point_rewards | json | VIP tier-specific point earn rules |
vip_tier_setting | json | VIP tier configuration object |
[
{
"id": 1,
"name": "Silver",
"threshold": 0,
"icon": "🥈",
"additionalTags": "silver-member"
},
{
"id": 2,
"name": "Gold",
"threshold": 1000,
"icon": "🥇",
"additionalTags": "gold-member, premium-support"
},
{
"id": 3,
"name": "Platinum",
"threshold": 5000,
"icon": "💎",
"additionalTags": "platinum-member, priority-shipping, premium-support"
}
]| Key | Type | Purpose |
|---|---|---|
points_expiration_setting | json | Point expiration config (interval and type) |
{
"enabled": true,
"interval": 12,
"intervalType": "MONTH"
}Shop metafields can be removed via MiscellaneousResource.removeShopMetafield() — this is used when resetting or disabling features.
| Property | Value |
|---|---|
| Type | json |
| Resource | Customer |
| Visibility | Public (readable by themes and other apps) |
| Set by | SubscribeItScriptUtils.writeCustomerMetafield() (loyalty-l / Lambda) |
| Updated when | After every loyalty event: point earn, point redeem, VIP tier change, referral, social engagement, etc. |
| Update mechanism | Processed by AWS Lambda (loyalty-l), updates are near real-time |
Important: This metafield is set only by the Lambda processor (loyalty-l), not by the main loyalty app. It's updated after every loyalty event.
{
"availablePoints": 1250,
"pendingPoints": 100,
"redeemedPoints": 500,
"creditedPoints": 1850,
"vipTier": {
"id": 2,
"name": "Gold"
},
"achievableTierId": 3,
"activeRewards": [
{
"discountCode": "REWARD-XYZ789",
"discountType": "PERCENTAGE",
"discountValue": 10
}
],
"socialMediaEngagement": {
"facebook": true,
"twitter": false,
"instagram": true,
"youtube": false,
"tiktok": false,
"pinterest": false,
"newsletter": true,
"sms": false,
"accountCreation": true,
"sharing": false
},
"referralInfo": {
"referralLink": "https://store.myshopify.com/?ref=abc123",
"completedReferrals": 3
},
"customerStatus": "ACTIVE",
"dateOfBirth": "1990-05-15",
"storeCreditBalance": 25.00,
"lastActivityDate": "2025-03-20T14:30:00Z",
"spentAmount": 450.75
}| Property | Value |
|---|---|
| Type | json |
| Resource | Customer |
| Visibility | Private — only readable by the Appstle Loyalty app |
| Set by | CommonUtils.syncCustomerRewardMetafield() (loyalty) and SubscribeItScriptUtils.syncCustomerRewardMetafield() (loyalty-l) |
| Updated when | Customer redeems points for a reward, reward expires, or reward is used |
| Purpose | Stores active discount codes for Shopify checkout discount functions |
{
"rewards": [
{ "discountCode": "REWARD-ABC123" },
{ "discountCode": "REWARD-DEF456" }
]
}Why private? This metafield uses the
$app:prefix to prevent external access. It contains discount codes that should only be validated by the Shopify discount function, not exposed to themes or third-party apps.
Product review metafields are set on individual Product resources and on the Shop resource (for carousel displays).
Set by: SubscribeItScriptUtils.createOrUpdateProductMetafield() in both loyalty and loyalty-l repos.
Updated when: A review is approved, updated, or deleted. Updates are synchronous in the main app and near real-time from Lambda.
| Key | Type | Purpose |
|---|---|---|
product_reviews | json | Array of approved reviews for the product detail page (paginated, max 5 per page) |
total_reviews | integer | Total review count for the product |
rating | rating | Overall product rating (Shopify native rating type: value, scale_min=1, scale_max=5) |
product_rating_details | json | Breakdown by star rating (map of rating → count) |
[
{
"id": 789,
"author": "John D.",
"rating": 5,
"title": "Amazing product!",
"body": "This is the best coffee I've ever had.",
"createdAt": "2025-03-15T10:00:00Z",
"verified": true
}
]{
"value": "4.5",
"scale_min": "1",
"scale_max": "5"
}{
"5": 42,
"4": 18,
"3": 7,
"2": 2,
"1": 1
}| Key | Type | Purpose |
|---|---|---|
carousel_product_reviews | json | Recent/featured reviews for the homepage carousel widget (max 15 reviews) |
carousel_total_reviews | integer | Total count of reviews in the carousel |
carousel_rating | rating | Overall rating for the carousel display (Shopify native rating type) |
Appstle Loyalty applies tags to Customer resources only. No tags are applied to orders or products.
All tags are applied using the Shopify GraphQL Admin API (TagsAddMutation / TagsRemoveMutation).
| Property | Value |
|---|---|
| Resource | Customer |
| Format | Dynamic — the VIP tier's name (e.g., Silver, Gold, Platinum) |
| Applied when | Customer achieves or is promoted to a VIP tier (automatic calculation or manual assignment) |
| Removed when | Customer's tier changes (upgrade, downgrade, or removal) |
| Mutual exclusivity | Only the current tier's name tag is active — previous tier name tags are removed |
When tier tags are applied:
- Automatic VIP tier calculation (based on spend, points, or order count thresholds)
- Manual tier assignment by merchant
- Referral flow VIP assignment
- Shopify Flow trigger VIP assignment
- Bulk operations VIP assignment
| Property | Value |
|---|---|
| Resource | Customer |
| Format | Comma-separated tags configured per tier in the additionalTags field |
| Applied when | Along with the tier name tag when a customer achieves a VIP tier |
| Removed when | Customer leaves the tier (upgrade, downgrade, or removal) |
| Configuration | Set per VIP tier in the Appstle admin under VIP Tiers |
A "Gold" tier configured with additionalTags = "premium-member, vip-support" will apply three tags when a customer reaches Gold:
Gold(the tier name)premium-member(additional tag)vip-support(additional tag)
When the customer upgrades to Platinum, all three Gold tags are removed and replaced with Platinum's tags.
| Property | Value |
|---|---|
| Resource | Customer |
| Format | Two tags per referral relationship |
| Applied when | A referral offer is accepted by both parties |
| Removed | Never (referral tags are permanent) |
| Tag Pattern | Applied To | Purpose |
|---|---|---|
referral:{referralCustomerId} | The referrer | Identifies the referred customer |
referred:{originalCustomerId} | The referred customer | Identifies who referred them |
Customer A (ID: 1111) refers Customer B (ID: 2222):
- Customer A gets tag:
referral:2222 - Customer B gets tag:
referred:1111
| Property | Value |
|---|---|
| Resource | Customer |
| Format | Wrote Appstle Web Review (static string) |
| Applied when | A new Shopify customer is created via product review submission (only if the customer didn't previously exist in Shopify) |
| Removed | Never (permanent tag) |
| # | Resource | Namespace | Key | Type | Visibility |
|---|---|---|---|---|---|
| 1 | Shop | appstle_loyalty | app_url | string | Public |
| 2 | Shop | appstle_loyalty | proxy_path_prefix | string | Public |
| 3 | Shop | appstle_loyalty | public_domain | string | Public |
| 4 | Shop | appstle_loyalty | shop_name | string | Public |
| 5 | Shop | appstle_loyalty | currency | string | Public |
| 6 | Shop | appstle_loyalty | pointRoundType | string | Public |
| 7 | Shop | appstle_loyalty | point_earn_rules | json | Public |
| 8 | Shop | appstle_loyalty | point_redeem_rules | json | Public |
| 9 | Shop | appstle_loyalty | bundle_js_path | url | Public |
| 10 | Shop | appstle_loyalty | bundle_css_path | url | Public |
| 11 | Shop | appstle_loyalty | widget_setting | json | Public |
| 12 | Shop | appstle_loyalty | shop_labels | json | Public |
| 13 | Shop | appstle_loyalty | enable_inactive_customer | boolean | Public |
| 14 | Shop | appstle_loyalty | has_dedicated_page_access | boolean | Public |
| 15 | Shop | appstle_loyalty | allow_customer_opt_in | boolean | Public |
| 16 | Shop | appstle_loyalty | enable_discount_to_apply_automatically | boolean | Public |
| 17 | Shop | appstle_loyalty | store_front_access_token | string | Public |
| 18 | Shop | appstle_loyalty | birthdate_format | string | Public |
| 19 | Shop | appstle_loyalty | show_store_credit_rewards | boolean | Public |
| 20 | Shop | appstle_loyalty | referral_enabled | boolean | Public |
| 21 | Shop | appstle_loyalty | referral_loyalty | json | Public |
| 22 | Shop | appstle_loyalty | vip_tier_enabled | boolean | Public |
| 23 | Shop | appstle_loyalty | vip_tiers | json | Public |
| 24 | Shop | appstle_loyalty | vip_rewards | json | Public |
| 25 | Shop | appstle_loyalty | vip_point_rewards | json | Public |
| 26 | Shop | appstle_loyalty | vip_tier_setting | json | Public |
| 27 | Shop | appstle_loyalty | points_expiration_setting | json | Public |
| 28 | Customer | appstle_loyalty | customer_loyalty | json | Public |
| 29 | Customer | $app:appstle_loyalty | customer_rewards | json | Private |
| 30 | Product | appstle_review | product_reviews | json | Public |
| 31 | Product | appstle_review | total_reviews | integer | Public |
| 32 | Product | appstle_review | rating | rating | Public |
| 33 | Product | appstle_review | product_rating_details | json | Public |
| 34 | Shop | appstle_review | carousel_product_reviews | json | Public |
| 35 | Shop | appstle_review | carousel_total_reviews | integer | Public |
| 36 | Shop | appstle_review | carousel_rating | rating | Public |
| # | Resource | Tag Pattern | When Applied | Permanent? |
|---|---|---|---|---|
| 1 | Customer | {VIP tier name} (dynamic) | VIP tier assignment | No (swapped on tier change) |
| 2 | Customer | {additionalTags} (merchant-configured per tier) | VIP tier assignment | No (swapped on tier change) |
| 3 | Customer | referral:{customerId} / referred:{customerId} | Referral acceptance | Yes |
| 4 | Customer | Wrote Appstle Web Review | New customer created via review | Yes |
| Mutation | Purpose |
|---|---|
MetafieldsSetMutation | Create or update metafields on any resource |
MetafieldsDeleteMutation | Delete metafields |
TagsAddMutation | Add tags to customers |
TagsRemoveMutation | Remove tags from customers |
Can I read loyalty metafields from my Liquid theme?
Yes — metafields in the appstle_loyalty and appstle_review namespaces are public. Access them in Liquid via {{ customer.metafields.appstle_loyalty.customer_loyalty }} or {{ product.metafields.appstle_review.rating }}. However, customer_rewards in the $app:appstle_loyalty namespace is private and not accessible in Liquid.
How quickly are customer loyalty metafields updated?
Customer loyalty metafields are updated by the Lambda processor (loyalty-l) after every loyalty event. Updates are near real-time — typically within a few seconds.
What happens to VIP tier tags when a customer is upgraded?
When a customer's VIP tier changes, the old tier's name tag and all its additionalTags are removed, and the new tier's name tag and additionalTags are added. Only one tier's tags are active at a time.
Can other apps read the customer_rewards discount codes?
No. The customer_rewards metafield uses the $app:appstle_loyalty namespace, which is a private app-owned namespace. Only the Appstle Loyalty app can read and write it. This protects discount codes from being exposed to unauthorized apps.
How do product review ratings work with Shopify's native rating type?
The rating metafield uses Shopify's native rating type (not JSON), which integrates directly with Shopify's built-in rating display, Google rich results, and other SEO features. The value is on a scale of 1 to 5.