Vue Integration
Add FeedValue to your Vue 3 application with full TypeScript support.
Coming Soon
The @feedvalue/vue package is currently in development. Check back soon for availability on npm. In the meantime, use the script tag method.
Installation
npm install @feedvalue/vue
# or
pnpm add @feedvalue/vue
# or
yarn add @feedvalue/vueBasic Usage
Install the plugin and use the composable:
// main.ts
import { createApp } from 'vue';
import { createFeedValue } from '@feedvalue/vue';
import App from './App.vue';
const app = createApp(App);
app.use(createFeedValue({
widgetId: 'your-widget-id',
}));
app.mount('#app');<script setup>
import { useFeedValue } from '@feedvalue/vue';
const { open, isReady } = useFeedValue();
</script>
<template>
<button @click="open" :disabled="!isReady">
Give Feedback
</button>
</template>Plugin Options
| Option | Type | Default | Description |
|---|---|---|---|
widgetId | string | required | Your widget ID from the dashboard |
apiBaseUrl | string | - | Custom API URL (for self-hosted) |
config | object | - | Configuration overrides |
headless | boolean | false | Disable default UI rendering |
Composable Return Values
The useFeedValue composable returns reactive refs and methods:
const {
// Reactive State (Ref<>)
isReady, // Widget is ready (config loaded)
isOpen, // Modal is currently open
isVisible, // Trigger button is visible
isSubmitting, // Submission in progress
isHeadless, // Running in headless mode
error, // Current error (if any)
instance, // FeedValue instance (advanced usage)
// Methods
open, // Open the feedback modal
close, // Close the feedback modal
toggle, // Toggle the modal open/closed
show, // Show the trigger button
hide, // Hide the trigger button
submit, // Submit feedback programmatically
identify, // Identify the current user
setData, // Set user data
reset, // Reset user data
} = useFeedValue();Headless Mode
For complete UI control, use headless mode:
// main.ts
app.use(createFeedValue({
widgetId: 'your-widget-id',
headless: true,
}));<script setup>
import { ref } from 'vue';
import { useFeedValue } from '@feedvalue/vue';
const { isReady, isOpen, open, close, submit, isSubmitting } = useFeedValue();
const message = ref('');
const handleSubmit = async () => {
await submit({ message: message.value });
message.value = '';
close();
};
</script>
<template>
<button @click="open" :disabled="!isReady">
Feedback
</button>
<div v-if="isOpen" class="my-modal">
<textarea v-model="message" />
<button @click="handleSubmit" :disabled="isSubmitting">
{{ isSubmitting ? 'Sending...' : 'Submit' }}
</button>
<button @click="close">Cancel</button>
</div>
</template>Custom Fields (User-Facing Form Inputs)
Custom fields are form inputs shown in the widget UI that users fill in themselves. They must be defined in your widget configuration on the FeedValue dashboard.
When to Use Custom Fields vs User Identification
| Use Case | Solution |
|---|---|
| Collect user's name/email in the form | Custom Fields - define in dashboard, user fills in |
| Attach logged-in user's info automatically | User Identification - use identify(), hidden from UI |
| Let user select feedback category | Custom Fields - define dropdown in dashboard |
| Track internal account IDs | User Identification - use setData(), hidden from UI |
Setting Up Custom Fields
- Go to your widget settings in the FeedValue dashboard
- Add custom fields with types:
text,email, oremoji - Configure labels, placeholders, and whether fields are required
- The fields will automatically appear in the widget modal
Headless Mode: Submitting Custom Field Values
When using headless mode with your own UI, use customFieldValues to submit responses:
<script setup>
import { ref } from 'vue';
import { useFeedValue } from '@feedvalue/vue';
const { submit, isReady } = useFeedValue();
const name = ref('');
const category = ref('feature');
const handleSubmit = async () => {
await submit({
message: 'Detailed feedback message',
customFieldValues: {
// Field IDs must match those defined in your widget configuration
name: name.value,
category: category.value,
},
});
};
</script>
<template>
<form @submit.prevent="handleSubmit">
<input v-model="name" placeholder="Your name" />
<select v-model="category">
<option value="bug">Bug Report</option>
<option value="feature">Feature Request</option>
</select>
<button type="submit" :disabled="!isReady">Submit</button>
</form>
</template>Custom Fields Must Be Defined First
The field IDs in customFieldValues (e.g., name, category) should match field IDs defined in your widget configuration on the dashboard.
User Identification
Attach user context to feedback submissions. This data is not shown in the widget UI but is stored with the submission and visible in your FeedValue dashboard.
<script setup>
import { watch } from 'vue';
import { useFeedValue } from '@feedvalue/vue';
const props = defineProps<{ user: User }>();
const { identify, setData } = useFeedValue();
watch(() => props.user, (user) => {
if (user) {
identify(user.id, {
email: user.email,
name: user.name,
plan: user.plan,
company: user.company,
});
}
}, { immediate: true });
</script>User Data vs Custom Fields
- User data (
identify/setData): Hidden from users, automatically attached to submissions. Use for internal context like user IDs, subscription plans, etc. - Custom fields (
customFieldValues): Shown as form inputs in the widget. Users fill these in themselves. Must be defined in widget configuration first.
Standalone Usage (Without Plugin)
You can also use the composable without installing the plugin:
<script setup>
import { useFeedValue } from '@feedvalue/vue';
// Pass widgetId directly
const { open, isReady } = useFeedValue('your-widget-id');
</script>Options API
If you prefer Options API, access via $feedvalue:
<script>
export default {
mounted() {
// Access the FeedValue instance
this.$feedvalue?.open();
},
methods: {
submitFeedback() {
this.$feedvalue?.submit({ message: 'Great app!' });
},
},
};
</script>Nuxt 3
Create a client-side plugin:
// plugins/feedvalue.client.ts
import { createFeedValue } from '@feedvalue/vue';
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(createFeedValue({
widgetId: 'your-widget-id',
}));
});Use in your layout or components:
<!-- layouts/default.vue -->
<script setup>
import { useFeedValue } from '@feedvalue/vue';
const { open, isReady } = useFeedValue();
</script>
<template>
<div>
<slot />
<button @click="open" :disabled="!isReady" class="feedback-button">
Feedback
</button>
</div>
</template>For headless mode in Nuxt:
// plugins/feedvalue.client.ts
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(createFeedValue({
widgetId: 'your-widget-id',
headless: true, // Build your own UI
}));
});TypeScript Support
Full TypeScript support is included:
import type {
FeedValuePluginOptions,
UseFeedValueReturn,
} from '@feedvalue/vue';
import type {
FeedbackData,
UserTraits,
} from '@feedvalue/vue';
const handleSubmit = (feedback: FeedbackData) => {
console.log(feedback.message);
console.log(feedback.sentiment);
};Comparison: Default vs Headless
| Feature | Default Mode | Headless Mode |
|---|---|---|
| Trigger button | Dashboard-styled | You build it |
| Modal | Dashboard-styled | You build it |
| API methods | Available | Available |
| User tracking | Available | Available |
| Dashboard config | Fetched | Fetched |
TIP
Use headless: true when you want complete control over the UI, or when you have security concerns about external code injecting DOM elements.
