Introduction
Rivo's account widget provides a powerful way to customize the display of customer data using Alpine.js. You can dynamically insert customer information—like email, points balance, VIP tier, and more—directly into your widget translations and custom HTML. This guide will show you how to create personalized, data-driven experiences for your customers.
✨ All customer data is automatically available through the rivo_profile_customer Alpine.js store when customers view their account pages.
Understanding the Customer Data Store
Rivo exposes customer data through an Alpine.js store called rivo_profile_customer. This store is automatically populated when a customer views their account page and contains all their loyalty program information, preferences, and activity.
Accessing the Store
You can access the store in two ways:
1. In JavaScript:
RivoProfileAlpine.store("rivo_profile_customer")
2. In HTML with Alpine directives:
<span rivo-ax-text="$store.rivo_profile_customer?.email"></span>
Available Customer Data
Here's the complete structure of the customer object with example values:
{
"id": 9552283369761,
"tags": ["Login with Shop", "Rivo VIP Tier: Gold", "Rivo Advocate"],
"email": "[email protected]",
"accepts_marketing": true,
"first_name": "Jane",
"last_name": "Smith",
"orders_count": 12,
"total_spent": 1450.75,
"phone": "+1234567890",
"addresses": [
{
"address1": "123 Main St",
"city": "San Francisco",
"province": "CA",
"zip": "94102"
}
],
"status_points_tally": 1200,
"status_credits_tally": "25.50",
"account_activated_at": "2024-01-15T10:30:00.000Z",
"referral_stats": {
"clicked_count": 24,
"claimed_count": 8,
"completed_count": 5
},
"shop_id": 86674604321,
"remote_id": 9552283369761,
"points_tally": 1500,
"credits_tally": 25.50,
"dob": "05-15",
"points_expiry": "17th Oct 2026",
"completed_custom_action_names": ["Follow on Instagram", "Join Newsletter"],
"loyalty_status": "vip",
"loyalty_status_last_changed_at": "2025-11-03T22:19:02.000Z",
"referral_url": "https://www.example.com?referral_code=LJdx6BLduxn16QeRz",
"pretty_points_tally": "1,500",
"pretty_credits_tally": "$25.50",
"expected_points_tally": 1500,
"lifetime_earnings_tally": 3200,
"full_name": "Jane Smith",
"phone_number": "+1234567890",
"buyer_accepts_sms_marketing": true
}
Using Alpine.js in Widget Translations
Basic Text Display
To display customer data in your widget translations, use the special rivo-ax-text attribute:
<span rivo-ax-text="$store.rivo_profile_customer?.email"></span>
💡 Why rivo-ax-text? We use a custom Alpine prefix (rivo-ax-) to avoid conflicts with other Alpine.js implementations on your store.
Displaying HTML Content
To render HTML content (not just plain text), use rivo-ax-html:
<!-- This will render HTML tags --> <div rivo-ax-html="$store.rivo_profile_customer?.custom_html_field"></div>
⚠️ Security Warning: Only use rivo-ax-html with trusted content. Never use it with user-generated content that hasn't been sanitized, as it could introduce security vulnerabilities.
Common Display Patterns
Display Customer Email:
Welcome, <span rivo-ax-text="$store.rivo_profile_customer?.email"></span>!
Display Points Balance (Formatted):
You have <strong rivo-ax-text="$store.rivo_profile_customer?.pretty_points_tally"></strong> points
Display Credits Balance:
Your credit balance: <strong rivo-ax-text="$store.rivo_profile_customer?.pretty_credits_tally"></strong>
Display Customer Name with Fallback:
<span rivo-ax-text="$store.rivo_profile_customer?.full_name || 'Valued Customer'"></span>
📝 Tip: Use the || 'fallback' pattern to provide a default value when data is empty.
Advanced Alpine.js Directives
Conditional Display (rivo-ax-show)
Show or hide elements based on customer data:
Show message only if customer has points:
<div rivo-ax-show="$store.rivo_profile_customer?.points_tally > 0"> Congratulations! You have points to redeem. </div>
Show message only for VIP customers:
<div rivo-ax-show="$store.rivo_profile_customer?.tags.includes('Rivo VIP Tier: Gold')">
Welcome, Gold VIP Member! Enjoy your exclusive benefits.
</div>
Show welcome message for new customers:
<div rivo-ax-show="$store.rivo_profile_customer?.orders_count === 0"> Welcome! Complete your first order to start earning points. </div>
Conditional Classes (rivo-ax-bind:class)
Apply CSS classes dynamically based on customer data:
<div rivo-ax-bind:class="$store.rivo_profile_customer?.points_tally > 1000 ? 'high-balance' : 'low-balance'"> Your balance: <span rivo-ax-text="$store.rivo_profile_customer?.pretty_points_tally"></span> </div>
Loops (rivo-ax-for)
Loop through arrays of data:
Display completed action names:
<div rivo-ax-show="$store.rivo_profile_customer?.completed_custom_action_names.length > 0">
<h3>Completed Actions:</h3>
<ul>
<template rivo-ax-for="action in $store.rivo_profile_customer?.completed_custom_action_names">
<li rivo-ax-text="action"></li>
</template>
</ul>
</div>
Display customer tags:
<div>
<h3>Your Tags:</h3>
<template rivo-ax-for="tag in $store.rivo_profile_customer?.tags">
<span class="tag" rivo-ax-text="tag"></span>
</template>
</div>
Complete Examples
Example 1: Personalized Welcome Banner
<div class="welcome-banner">
<h2>
Welcome back,
<span rivo-ax-text="$store.rivo_profile_customer?.full_name || $store.rivo_profile_customer?.email"></span>!
</h2> <div class="stats">
<div class="stat">
<strong rivo-ax-text="$store.rivo_profile_customer?.pretty_points_tally"></strong>
<span>Points</span>
</div> <div class="stat">
<strong rivo-ax-text="$store.rivo_profile_customer?.orders_count"></strong>
<span>Orders</span>
</div> <div class="stat" rivo-ax-show="$store.rivo_profile_customer?.credits_tally > 0">
<strong rivo-ax-text="$store.rivo_profile_customer?.pretty_credits_tally"></strong>
<span>Credits</span>
</div>
</div>
</div>
Example 2: VIP Tier Badge
<div class="tier-display" rivo-ax-show="$store.rivo_profile_customer?.tags.some(tag => tag.includes('Rivo VIP Tier:'))">
<template rivo-ax-for="tag in $store.rivo_profile_customer?.tags">
<span
rivo-ax-show="tag.includes('Rivo VIP Tier:')"
rivo-ax-text="tag.replace('Rivo VIP Tier: ', '')"
class="vip-badge">
</span>
</template>
</div>
Example 3: Referral Stats Dashboard
<div class="referral-stats">
<h3>Your Referral Performance</h3> <div class="stat-row">
<span>Link Clicks:</span>
<strong rivo-ax-text="$store.rivo_profile_customer?.referral_stats.clicked_count"></strong>
</div> <div class="stat-row">
<span>Sign-ups:</span>
<strong rivo-ax-text="$store.rivo_profile_customer?.referral_stats.claimed_count"></strong>
</div> <div class="stat-row">
<span>Completed Referrals:</span>
<strong rivo-ax-text="$store.rivo_profile_customer?.referral_stats.completed_count"></strong>
</div> <div class="referral-link">
<label>Your Referral Link:</label>
<input
type="text"
readonly
rivo-ax-bind:value="$store.rivo_profile_customer?.referral_url">
</div>
</div>
Example 4: Points Expiry Warning
<div class="expiry-warning" rivo-ax-show="$store.rivo_profile_customer?.points_expiry && $store.rivo_profile_customer?.points_tally > 0"> ⚠️ Your <strong rivo-ax-text="$store.rivo_profile_customer?.pretty_points_tally"></strong> points will expire on <strong rivo-ax-text="$store.rivo_profile_customer?.points_expiry"></strong>. <a href="/collections/all">Shop now to use them!</a> </div>
Example 5: Conditional Messaging by Order Count
<!-- Message for new customers --> <div rivo-ax-show="$store.rivo_profile_customer?.orders_count === 0"> <h3>🎉 Welcome to our loyalty program!</h3> <p>Place your first order to start earning points and unlock rewards.</p> </div><!-- Message for returning customers --> <div rivo-ax-show="$store.rivo_profile_customer?.orders_count > 0 && $store.rivo_profile_customer?.orders_count < 5"> <h3>Thanks for being a loyal customer!</h3> <p>You've placed <span rivo-ax-text="$store.rivo_profile_customer?.orders_count"></span> orders. Keep shopping to unlock VIP status!</p> </div><!-- Message for VIP customers --> <div rivo-ax-show="$store.rivo_profile_customer?.orders_count >= 5"> <h3>🌟 You're a VIP!</h3> <p>Thank you for your continued support with <span rivo-ax-text="$store.rivo_profile_customer?.orders_count"></span> orders!</p> </div>
Field Reference
Basic Information
Field | Type | Description | Example |
| Number | Customer's internal Rivo ID |
|
| Number | Customer's Shopify ID |
|
| String | Customer's email address | |
| String/null | Customer's first name |
|
| String/null | Customer's last name |
|
| String | Combined first and last name |
|
| String/null | Customer's phone number |
|
| String/null | Alternate phone field |
|
| String/null | Date of birth |
|
Points & Credits
Field | Type | Description | Example |
| Number | Raw points balance |
|
| String | Formatted points balance |
|
| Number | Raw credits balance |
|
| String | Formatted credits with currency |
|
| Number | Points counting toward tier status |
|
| String | Credits counting toward tier status |
|
| String/null | Date when points expire |
|
| Number/null | Total points earned all time |
|
Status & Tiers
Field | Type | Description | Example |
| String | Current loyalty tier status |
|
| String | Last status change timestamp |
|
| Array | All Shopify tags for this customer |
|
Orders & Spending
Field | Type | Description | Example |
| Number | Total number of orders |
|
| Number | Lifetime spending amount |
|
Referral Program
Field | Type | Description | Example |
| String | Customer's unique referral link |
|
| Number | Times referral link was clicked |
|
| Number | Sign-ups from referral link |
|
| Number | Completed referrals (purchases) |
|
Actions & Engagement
Field | Type | Description | Example |
| Array | Custom action names completed |
|
| String/null | When account was first activated |
|
Marketing & Preferences
Field | Type | Description | Example |
| Boolean | Email marketing opt-in status |
|
| Boolean/null | SMS marketing opt-in status |
|
Debugging Customer Data
View the Full Customer Object
To see all available data in your browser console:
console.log(JSON.stringify(RivoProfileAlpine.store("rivo_profile_customer"), null, 2));
Check if Data is Loaded
if (RivoProfileAlpine.store("rivo_profile_customer")) {
console.log("Customer data loaded:", RivoProfileAlpine.store("rivo_profile_customer").email);
} else {
console.log("Customer data not yet loaded");
}
Best Practices
1. Always Provide Fallbacks
Use the || operator to provide default values when data might be missing:
<span rivo-ax-text="$store.rivo_profile_customer?.full_name || 'Valued Customer'"></span>
2. Check Before Accessing Nested Properties
For nested objects, check existence first:
<div rivo-ax-show="$store.rivo_profile_customer?.referral_stats && $store.rivo_profile_customer?.referral_stats.completed_count > 0"> You have completed referrals! </div>
3. Use Semantic HTML
Wrap dynamic content in appropriate HTML elements:
<!-- Good --> <strong rivo-ax-text="$store.rivo_profile_customer?.pretty_points_tally"></strong><!-- Avoid --> <span style="font-weight: bold;" rivo-ax-text="$store.rivo_profile_customer?.pretty_points_tally"></span>
4. Prefer Pretty Fields for Display
Always use pretty_points_tally and pretty_credits_tally instead of raw values for user-facing displays:
<!-- Good - Formatted with commas and currency --> <span rivo-ax-text="$store.rivo_profile_customer?.pretty_credits_tally"></span><!-- Avoid - Raw number without formatting --> <span rivo-ax-text="$store.rivo_profile_customer?.credits_tally"></span>
Troubleshooting
Data Not Displaying
Symptom: Alpine directive shows nothing or displays the literal text
Check:
Verify you're using
rivo-ax-prefix (notx-)Check browser console for JavaScript errors
Confirm customer is logged in
Verify the field exists in the customer object
Example Debug:
// In browser console
console.log(RivoProfileAlpine.store("rivo_profile_customer"));
Null or Undefined Values
Symptom: Some fields show as blank or cause errors
Cause: Not all fields are populated for all customers
Fix: Always use fallbacks with ||:
<span rivo-ax-text="$store.rivo_profile_customer?.first_name || 'there'"></span>
Conditional Not Working
Symptom: rivo-ax-show doesn't hide/show elements as expected
Check:
Verify the condition evaluates to a boolean
Use browser console to test the expression
Check for typos in field names
Array Methods Not Working
Symptom: .includes(), .some(), .filter() not working
Cause: Field might be null or not an array
Fix: Check array exists before using methods:
<div rivo-ax-show="$store.rivo_profile_customer?.tags && $store.rivo_profile_customer?.tags.includes('Rivo VIP')">
VIP Content
</div>
Frequently Asked Questions
Q: Can I use regular Alpine.js directives (x-text, x-show)?
A: No, you must use the rivo-ax- prefix to avoid conflicts. Use rivo-ax-text, rivo-ax-show, etc.
Q: How often is customer data updated?
A: The data is loaded when the account page loads and reflects the most recent information from the database.
Q: Can I modify the customer data from the frontend?
A: No, the store is read-only. All customer data changes must go through Rivo's backend systems.
Q: What happens if a customer isn't logged in?
A: The store will either be empty or contain guest/anonymous customer data. Always handle empty states gracefully.
Q: Can I use this data outside the account widget?
A: The rivo_profile_customer store is only available within Rivo's account widget pages. For other pages, use Rivo's JavaScript SDK or API.
Q: Are there any performance concerns?
A: No, the customer data is small and loaded once per page. Alpine.js reactivity is efficient for this use case.
Getting Help
If you need assistance with advanced customizations:
Check the data structure - Use
JSON.stringify()in console to see exactly what's availableTest expressions - Run JavaScript expressions in browser console before adding to HTML
Review Alpine.js docs - Visit https://alpinejs.dev for full directive documentation (remember to use
rivo-ax-prefix)Contact Rivo Support - Email [email protected] with specific questions about your customization
💡 Pro Tip: Bookmark this page and keep the customer object structure handy for quick reference when building customizations!
