Using Client-Side Usertune.js with Vue 3 for Personalized Content
Simple guide to integrating client-side Usertune.js with Vue 3. Learn how to get user context in the browser, load personalized content, and update your components dynamically.
Technical Guide Expert
• 3 min read
Integrate client-side Usertune.js with Vue 3 to deliver personalized content in the browser. This guide shows you how to set up the basics, get user context, and update content dynamically on the client side.
Installation
First, install the Usertune JavaScript library in your Vue 3 project:
npm install usertune.js
This will add the official Usertune client library that works in both Node.js and browser environments.
Vue 3 Setup
To use Usertune throughout your Vue application, we'll create a plugin that makes the client available to all components.
Create a simple client-side plugin:
// plugins/usertune.js
import { Usertune } from 'usertune.js'
export default {
install(app, options) {
const client = new Usertune({
workspace: options.workspaceId,
accessToken: options.accessToken // Optional - only needed for private content
})
app.provide('usertune', client)
}
}
This plugin creates a single Usertune client instance and provides it to your entire Vue app using Vue's dependency injection system. The accessToken
is only required if you're fetching private or personalized content.
Now register the plugin in your main application file:
// main.js
import { createApp } from 'vue'
import UsertunePlugin from './plugins/usertune.js'
const app = createApp(App)
app.use(UsertunePlugin, {
workspaceId: import.meta.env.VITE_USERTUNE_WORKSPACE_ID,
accessToken: import.meta.env.VITE_USERTUNE_ACCESS_TOKEN
})
This makes the Usertune client available in any component throughout your application. The configuration values come from environment variables, keeping your credentials secure.
Basic Composable
The heart of your Usertune integration will be a composable that handles content fetching and tracking. Here's a reusable composable that follows Vue 3 best practices:
// composables/useUsertune.js
import { inject, ref, onMounted } from 'vue'
export function useUsertune() {
return inject('usertune')
}
export function usePersonalizedContent(contentSlug, attributes = {}) {
const client = useUsertune()
const data = ref(null)
const metadata = ref(null)
const loading = ref(true)
const loadContent = async () => {
loading.value = true
try {
// Client-side personalization call
const response = await client.content(contentSlug, attributes)
data.value = response.data
metadata.value = response.metadata
} catch (error) {
console.error('Failed to load content:', error)
} finally {
loading.value = false
}
}
onMounted(loadContent)
const track = async (conversionType, conversionValue) => {
await client.track(conversionType, conversionValue)
}
return { data, metadata, loading, loadContent, track }
}
How this works:
useUsertune()
- Gets the Usertune client from the dependency injection systemusePersonalizedContent()
- Main composable that fetches content and provides trackingdata
- Contains the actual content returned from Usertunemetadata
- Contains tracking information like variant IDsloading
- Reactive state for showing loading indicatorsloadContent()
- Function to manually refresh contenttrack()
- Function to track conversions and user interactions
The content automatically loads when the component mounts, but you can also call loadContent()
manually to refresh it based on user actions.
Dynamic Content Updates
One of the powerful features of client-side personalization is the ability to update content based on user interactions without page refreshes:
<!-- components/DynamicContent.vue -->
<template>
<div>
<div>
<label>
<input
type="checkbox"
v-model="userPreferences.darkMode"
@change="updateContent"
>
Dark Mode
</label>
</div>
<div>
<select v-model="userPreferences.language" @change="updateContent">
<option value="en">English</option>
<option value="es">Spanish</option>
<option value="fr">French</option>
</select>
</div>
<div v-if="loading">Updating content...</div>
<div v-else-if="data">
<h3>{{ data.heading }}</h3>
<p>{{ data.description }}</p>
<div v-if="data.theme" :class="data.theme">
Themed content based on your preferences
</div>
</div>
</div>
</template>
<script setup>
import { ref, reactive, computed } from 'vue'
import { usePersonalizedContent } from '@/composables/useUsertune'
const userPreferences = reactive({
darkMode: false,
language: 'en'
})
const attributes = computed(() => ({
theme: userPreferences.darkMode ? 'dark' : 'light',
language: userPreferences.language,
timestamp: Date.now()
}))
const { data, loading, loadContent } = usePersonalizedContent('dynamic-content', attributes.value)
const updateContent = async () => {
// Trigger client-side content refresh
await loadContent()
}
</script>
Key concepts in this example:
- Reactive preferences - User settings are stored in a reactive object that Vue tracks
- Computed attributes - The attributes sent to Usertune are automatically computed from user preferences
- Manual updates - When users change preferences, we manually trigger
loadContent()
to fetch new personalized content - Loading states - The UI shows loading indicators while content is being fetched
- Fallback content - If content fails to load, the component gracefully handles the error
This pattern allows you to create highly interactive, personalized experiences that respond immediately to user actions while maintaining good performance and user experience.
Best Practices
- Always handle loading states - Show users something is happening
- Provide fallback content - Don't break if personalization fails
- Use reactive attributes - Let Vue's reactivity trigger content updates
- Track user interactions - Measure what works with
client.track()
- Keep context lightweight - Only pass what you need
- Client-side only - Remember that Usertune.js runs in the browser
- Access token is optional - Only needed for private/personalized content
Ready to personalize your Vue 3 app with client-side Usertune? Sign up for Usertune and start delivering personalized experiences!