solucx-survey-widget
v0.0.18
Published
A customizable survey widget component built with Vue.js that can be integrated into various web frameworks. This widget allows you to embed SoluCX surveys directly into your applications with support for different display modes and comprehensive event ha
Readme
SoluCX Survey Widget
A customizable survey widget component built with Vue.js that can be integrated into various web frameworks. This widget allows you to embed SoluCX surveys directly into your applications with support for different display modes and comprehensive event handling.
Features
- 🎯 Multiple widget types: inline, modal, bottom bar, bottom box (left/right)
- 📱 Responsive design with customizable dimensions
- 🔒 Security-focused with domain validation and data sanitization
- 📊 Built-in analytics and user behavior tracking
- ⚡ Framework agnostic - works with Vue, React, Angular, and more
- 🎨 Customizable styling and positioning
- 📡 Real-time event handling and callbacks
Installation
npm install solucx-survey-widgetConfiguration
The widget requires the following props:
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| soluCxKey | string | ✅ | Your SoluCX survey key |
| widgetType | WidgetType | ✅ | Display mode: 'inline', 'modal', 'bottomBar', 'bottomBox', 'bottomBoxLeft' |
| widgetData | WidgetData \| string | ✅ | Survey data (object or JSON string) |
| widgetOptions | WidgetOptions \| string | ❌ | Configuration options |
Widget Data Structure
interface WidgetData {
customer_id?: string
email?: string
name?: string
phone?: string
document?: string
transaction_id?: string
// ... other custom fields
}Widget Options
interface WidgetOptions {
width?: number // Widget width in pixels
height?: number // Widget height in pixels
retry?: {
attempts?: number // Max retry attempts (default: 5)
interval?: number // Retry interval in days (default: 1)
}
waitDelayAfterRating?: number // Days to wait after rating (default: 60)
}Basic Usage Examples
Direct Import and Use
// Import the component directly
import SoluCXSurveyWidget from 'solucx-survey-widget'
// Use in your template/JSX
<SoluCXSurveyWidget
solu-cx-key="your-survey-key"
widget-type="inline"
widget-data='{"customer_id": "12345", "email": "[email protected]"}'
/>Global Registration (Vue.js)
// main.js
import { createApp } from 'vue'
import SoluCXSurveyWidget from 'solucx-survey-widget'
import App from './App.vue'
const app = createApp(App)
// Register globally
app.component('SoluCXSurveyWidget', SoluCXSurveyWidget)
app.mount('#app')<!-- Now you can use it anywhere without importing -->
<template>
<div>
<SoluCXSurveyWidget
:solu-cx-key="surveyKey"
widget-type="modal"
:widget-data="customerData"
/>
</div>
</template>
<script setup>
// No need to import when registered globally
const surveyKey = 'your-survey-key'
const customerData = {
customer_id: '12345',
email: '[email protected]'
}
</script>Web Component (Vanilla HTML/JS)
<!DOCTYPE html>
<html>
<head>
<title>SoluCX Survey</title>
</head>
<body>
<!-- Include the widget -->
<script type="module">
import 'solucx-survey-widget'
</script>
<!-- Use the web component -->
<solucx-survey-widget
solu-cx-key="your-survey-key"
widget-type="bottomBox"
widget-data='{"customer_id": "12345", "email": "[email protected]"}'
widget-options='{"width": 400, "height": 300}'
></solucx-survey-widget>
<script>
// Listen to events
const widget = document.querySelector('solucx-survey-widget')
widget.addEventListener('widgetCompleted', (event) => {
console.log('Survey completed!')
// Handle completion
})
widget.addEventListener('widgetError', (event) => {
console.error('Widget error:', event.detail)
})
</script>
</body>
</html>CDN Usage
<!DOCTYPE html>
<html>
<head>
<title>SoluCX Survey - CDN</title>
</head>
<body>
<!-- Load from CDN -->
<script type="module" src="https://unpkg.com/solucx-survey-widget@latest/dist/index.js"></script>
<!-- Use the component -->
<solucx-survey-widget
solu-cx-key="your-survey-key"
widget-type="inline"
widget-data='{"customer_id": "67890", "name": "John Doe"}'
></solucx-survey-widget>
</body>
</html>Dynamic Component Creation
// Create widget programmatically
function createSurveyWidget(containerId, config) {
const container = document.getElementById(containerId)
if (!container) {
console.error('Container not found')
return
}
// Create the web component
const widget = document.createElement('solucx-survey-widget')
// Set properties
widget.setAttribute('solu-cx-key', config.surveyKey)
widget.setAttribute('widget-type', config.type || 'inline')
widget.setAttribute('widget-data', JSON.stringify(config.data))
if (config.options) {
widget.setAttribute('widget-options', JSON.stringify(config.options))
}
// Add event listeners
widget.addEventListener('widgetCompleted', config.onComplete || (() => {}))
widget.addEventListener('widgetClosed', config.onClose || (() => {}))
widget.addEventListener('widgetError', config.onError || (() => {}))
// Append to container
container.appendChild(widget)
return widget
}
// Usage
createSurveyWidget('survey-container', {
surveyKey: 'your-survey-key',
type: 'modal',
data: {
customer_id: '12345',
email: '[email protected]'
},
options: {
width: 600,
height: 400
},
onComplete: (userId) => {
console.log('Survey completed by:', userId)
// Redirect or show thank you message
},
onError: (error) => {
console.error('Survey error:', error)
}
})Conditional Loading
// Load widget only when needed
async function loadSurveyWidget() {
try {
// Dynamic import
await import('solucx-survey-widget')
// Create and configure widget
const widget = document.createElement('solucx-survey-widget')
widget.setAttribute('solu-cx-key', 'your-survey-key')
widget.setAttribute('widget-type', 'bottomBar')
widget.setAttribute('widget-data', JSON.stringify({
customer_id: '12345',
email: '[email protected]'
}))
document.body.appendChild(widget)
} catch (error) {
console.error('Failed to load survey widget:', error)
}
}
// Load on user interaction
document.getElementById('show-survey').addEventListener('click', loadSurveyWidget)
// Or load after page load
window.addEventListener('load', () => {
setTimeout(loadSurveyWidget, 3000) // Show survey after 3 seconds
})Framework Integration Examples
Vue.js
<template>
<div>
<SoluCXSurveyWidget
:solu-cx-key="surveyKey"
widget-type="inline"
:widget-data="surveyData"
:widget-options="options"
@widget-opened="onWidgetOpened"
@widget-closed="onWidgetClosed"
@widget-completed="onWidgetCompleted"
/>
</div>
</template>
<script setup>
import { ref } from 'vue'
import SoluCXSurveyWidget from 'solucx-survey-widget'
const surveyKey = 'your-survey-key'
const surveyData = ref({
customer_id: '12345',
email: '[email protected]',
name: 'John Doe'
})
const options = ref({
width: 600,
height: 400
})
const onWidgetOpened = (userId) => {
console.log('Widget opened for user:', userId)
}
const onWidgetClosed = () => {
console.log('Widget closed')
}
const onWidgetCompleted = (userId) => {
console.log('Survey completed by user:', userId)
}
</script>Nuxt.js
1. Create a plugin (plugins/solucx-widget.client.js):
import SoluCXSurveyWidget from 'solucx-survey-widget'
export default defineNuxtPlugin(nuxtApp => {
nuxtApp.vueApp.component('SoluCXSurveyWidget', SoluCXSurveyWidget)
})2. Use in your component:
<template>
<div>
<ClientOnly>
<SoluCXSurveyWidget
:solu-cx-key="surveyKey"
widget-type="modal"
:widget-data="surveyData"
@widget-completed="handleCompletion"
/>
</ClientOnly>
</div>
</template>
<script setup>
const surveyKey = 'your-survey-key'
const surveyData = {
customer_id: '12345',
email: '[email protected]'
}
const handleCompletion = (userId) => {
console.log('Survey completed!', userId)
// Navigate to thank you page
await navigateTo('/thank-you')
}
</script>React
1. Create a wrapper component (SoluCXWidget.jsx):
import React, { useEffect, useRef } from 'react'
import 'solucx-survey-widget'
const SoluCXWidget = ({
soluCxKey,
widgetType = 'inline',
widgetData,
widgetOptions = {},
onWidgetCompleted,
onWidgetClosed,
onWidgetError
}) => {
const widgetRef = useRef(null)
useEffect(() => {
const widget = widgetRef.current
if (widget) {
// Set properties
widget.soluCxKey = soluCxKey
widget.widgetType = widgetType
widget.widgetData = JSON.stringify(widgetData)
widget.widgetOptions = JSON.stringify(widgetOptions)
// Add event listeners
const handleCompleted = () => onWidgetCompleted?.(widgetData.customer_id)
const handleClosed = () => onWidgetClosed?.()
const handleError = (event) => onWidgetError?.(event.detail)
widget.addEventListener('widgetCompleted', handleCompleted)
widget.addEventListener('widgetClosed', handleClosed)
widget.addEventListener('widgetError', handleError)
// Cleanup
return () => {
widget.removeEventListener('widgetCompleted', handleCompleted)
widget.removeEventListener('widgetClosed', handleClosed)
widget.removeEventListener('widgetError', handleError)
}
}
}, [soluCxKey, widgetType, widgetData, widgetOptions])
return <solucx-survey-widget ref={widgetRef} />
}
export default SoluCXWidget2. Use in your React component:
import React, { useState } from 'react'
import SoluCXWidget from './SoluCXWidget'
const SurveyPage = () => {
const [surveyData] = useState({
customer_id: '12345',
email: '[email protected]',
name: 'John Doe'
})
const handleSurveyCompleted = (userId) => {
console.log('Survey completed by:', userId)
// Redirect or show success message
}
return (
<div className="survey-container">
<h2>Customer Feedback</h2>
<SoluCXWidget
soluCxKey="your-survey-key"
widgetType="inline"
widgetData={surveyData}
widgetOptions={{ width: 600, height: 400 }}
onWidgetCompleted={handleSurveyCompleted}
/>
</div>
)
}
export default SurveyPageNext.js
1. Create a dynamic component (components/SoluCXWidget.js):
import dynamic from 'next/dynamic'
import { useEffect, useRef } from 'react'
const SoluCXWidget = ({ soluCxKey, widgetType, widgetData, widgetOptions, onComplete }) => {
const widgetRef = useRef(null)
useEffect(() => {
// Import the web component dynamically
import('solucx-survey-widget')
}, [])
useEffect(() => {
const widget = widgetRef.current
if (widget) {
widget.soluCxKey = soluCxKey
widget.widgetType = widgetType
widget.widgetData = JSON.stringify(widgetData)
widget.widgetOptions = JSON.stringify(widgetOptions || {})
const handleComplete = () => onComplete?.(widgetData.customer_id)
widget.addEventListener('widgetCompleted', handleComplete)
return () => widget.removeEventListener('widgetCompleted', handleComplete)
}
}, [soluCxKey, widgetType, widgetData, widgetOptions, onComplete])
return <solucx-survey-widget ref={widgetRef} />
}
// Export as dynamic component to avoid SSR issues
export default dynamic(() => Promise.resolve(SoluCXWidget), { ssr: false })2. Use in your page (pages/survey.js):
import SoluCXWidget from '../components/SoluCXWidget'
import { useRouter } from 'next/router'
export default function SurveyPage() {
const router = useRouter()
const surveyData = {
customer_id: '12345',
email: '[email protected]',
transaction_id: 'tx_' + Date.now()
}
const handleSurveyComplete = (userId) => {
console.log('Survey completed!', userId)
router.push('/thank-you')
}
return (
<div style={{ padding: '20px' }}>
<h1>Customer Satisfaction Survey</h1>
<SoluCXWidget
soluCxKey="your-survey-key"
widgetType="inline"
widgetData={surveyData}
widgetOptions={{ width: 700, height: 500 }}
onComplete={handleSurveyComplete}
/>
</div>
)
}Angular
1. Create a wrapper component (survey-widget.component.ts):
import { Component, Input, Output, EventEmitter, OnInit, ViewChild, ElementRef, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'
@Component({
selector: 'app-survey-widget',
template: `
<solucx-survey-widget
#widget
[attr.solu-cx-key]="soluCxKey"
[attr.widget-type]="widgetType"
[attr.widget-data]="widgetDataString"
[attr.widget-options]="widgetOptionsString"
></solucx-survey-widget>
`,
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class SurveyWidgetComponent implements OnInit {
@Input() soluCxKey!: string
@Input() widgetType: string = 'inline'
@Input() widgetData: any = {}
@Input() widgetOptions: any = {}
@Output() widgetCompleted = new EventEmitter<string>()
@Output() widgetClosed = new EventEmitter<void>()
@Output() widgetError = new EventEmitter<string>()
@ViewChild('widget', { static: true }) widget!: ElementRef
get widgetDataString(): string {
return JSON.stringify(this.widgetData)
}
get widgetOptionsString(): string {
return JSON.stringify(this.widgetOptions)
}
async ngOnInit() {
// Import the web component
await import('solucx-survey-widget')
// Add event listeners
const widgetElement = this.widget.nativeElement
widgetElement.addEventListener('widgetCompleted', () => {
this.widgetCompleted.emit(this.widgetData.customer_id)
})
widgetElement.addEventListener('widgetClosed', () => {
this.widgetClosed.emit()
})
widgetElement.addEventListener('widgetError', (event: any) => {
this.widgetError.emit(event.detail)
})
}
}2. Use in your component (survey.component.ts):
import { Component } from '@angular/core'
import { Router } from '@angular/router'
@Component({
selector: 'app-survey',
template: `
<div class="survey-container">
<h2>Customer Feedback</h2>
<app-survey-widget
[soluCxKey]="surveyKey"
widgetType="inline"
[widgetData]="surveyData"
[widgetOptions]="surveyOptions"
(widgetCompleted)="onSurveyCompleted($event)"
(widgetError)="onSurveyError($event)"
></app-survey-widget>
</div>
`,
styles: [`
.survey-container {
padding: 20px;
max-width: 800px;
margin: 0 auto;
}
`]
})
export class SurveyComponent {
surveyKey = 'your-survey-key'
surveyData = {
customer_id: '12345',
email: '[email protected]',
name: 'John Doe'
}
surveyOptions = {
width: 600,
height: 400
}
constructor(private router: Router) {}
onSurveyCompleted(userId: string) {
console.log('Survey completed by:', userId)
this.router.navigate(['/thank-you'])
}
onSurveyError(error: string) {
console.error('Survey error:', error)
// Handle error
}
}3. Update your module (app.module.ts):
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { SurveyWidgetComponent } from './survey-widget.component'
@NgModule({
declarations: [
SurveyWidgetComponent
],
imports: [BrowserModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AppModule { }Events
The widget emits the following events:
| Event | Description | Payload |
|-------|-------------|---------|
| widgetOpened | Widget is displayed | userId: string |
| widgetClosed | Widget is closed | - |
| widgetCompleted | Survey completed | userId: string |
| widgetError | Error occurred | error: string |
| widgetResized | Widget height changed | height: number |
| widgetPageChanged | Survey page changed | page: string |
Widget Types
inline: Embedded directly in page contentmodal: Overlay modal with backdropbottomBar: Fixed bottom bar across full widthbottomBox: Fixed bottom-right corner boxbottomBoxLeft: Fixed bottom-left corner box
Development
# Install dependencies
npm install
# Run tests
npm test
# Build for production
npm run buildSupport
For support and questions, please contact the SoluCX team or refer to the official documentation.
