Technical Guide

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.

AL

Technical Guide Expert

• 3 min read

Vue.js Vue 3 Usertune Personalization Composition API

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 system
  • usePersonalizedContent() - Main composable that fetches content and provides tracking
  • data - Contains the actual content returned from Usertune
  • metadata - Contains tracking information like variant IDs
  • loading - Reactive state for showing loading indicators
  • loadContent() - Function to manually refresh content
  • track() - 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

  1. Always handle loading states - Show users something is happening
  2. Provide fallback content - Don't break if personalization fails
  3. Use reactive attributes - Let Vue's reactivity trigger content updates
  4. Track user interactions - Measure what works with client.track()
  5. Keep context lightweight - Only pass what you need
  6. Client-side only - Remember that Usertune.js runs in the browser
  7. 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!