Advanced
Custom widget integrations
Integrate the UserJot widget with your own UI components and workflows.
Custom trigger buttons
Replace the default floating button with your own design.
Basic custom button
// Initialize with custom trigger
window.uj.init('YOUR_PROJECT_ID', {
widget: true,
trigger: 'custom' // Hides default button
});
// Open widget with your button
document.getElementById('feedback-btn').onclick = () => {
window.uj.showWidget();
};
Multiple trigger points
Add feedback triggers throughout your application:
// Header feedback button
document.querySelector('.header-feedback').onclick = () => {
window.uj.showWidget({ section: 'feedback' });
};
// Footer roadmap link
document.querySelector('.footer-roadmap').onclick = () => {
window.uj.showWidget({ section: 'roadmap' });
};
// Help menu updates option
document.querySelector('.help-updates').onclick = () => {
window.uj.showWidget({ section: 'updates' });
};
Conditional display
Show the widget based on user actions or application state.
Show after user action
// Show after task completion
function onTaskComplete() {
setTimeout(() => {
window.uj.showWidget({ section: 'feedback' });
}, 2000);
}
// Show on error
window.addEventListener('error', (event) => {
if (event.error?.userFacing) {
window.uj.showWidget({ section: 'feedback' });
}
});
Show based on user segment
// Show for specific user types
if (user.plan === 'premium' && user.daysActive > 30) {
window.uj.setWidgetEnabled(true);
} else {
window.uj.setWidgetEnabled(false);
}
State synchronization
Keep your app in sync with widget state.
Track widget visibility
// Monitor widget state changes
let previousState = { isOpen: false, section: null };
setInterval(() => {
const currentState = window.uj.getWidgetState();
if (currentState.isOpen !== previousState.isOpen) {
// Widget opened or closed
analytics.track('Widget Toggled', {
isOpen: currentState.isOpen,
section: currentState.section
});
}
previousState = currentState;
}, 1000);
Coordinate with modals
// Close widget when opening modal
function openModal() {
window.uj.hideWidget();
// Show your modal
}
// Check widget before showing modal
function showModal() {
const state = window.uj.getWidgetState();
if (state.isOpen) {
window.uj.hideWidget();
setTimeout(showModal, 300); // Wait for animation
} else {
// Show modal
}
}
Framework integrations
React
// Custom hook
function useUserJot() {
const [widgetState, setWidgetState] = useState({
isOpen: false,
section: null
});
useEffect(() => {
const interval = setInterval(() => {
setWidgetState(window.uj.getWidgetState());
}, 500);
return () => clearInterval(interval);
}, []);
const showWidget = (section) => {
window.uj.showWidget({ section });
};
const hideWidget = () => {
window.uj.hideWidget();
};
return { widgetState, showWidget, hideWidget };
}
// Component usage
function FeedbackButton() {
const { widgetState, showWidget, hideWidget } = useUserJot();
return (
<button
onClick={() =>
widgetState.isOpen ? hideWidget() : showWidget('feedback')
}
>
{widgetState.isOpen ? 'Close' : 'Feedback'}
</button>
);
}
Vue
<template>
<button @click="toggleWidget">
{{ widgetOpen ? 'Close' : 'Send Feedback' }}
</button>
</template>
<script>
export default {
data() {
return {
widgetOpen: false
};
},
methods: {
toggleWidget() {
if (this.widgetOpen) {
window.uj.hideWidget();
} else {
window.uj.showWidget({ section: 'feedback' });
}
this.widgetOpen = !this.widgetOpen;
}
},
mounted() {
// Check state periodically
setInterval(() => {
const state = window.uj.getWidgetState();
this.widgetOpen = state.isOpen;
}, 500);
}
};
</script>
Angular
@Component({
selector: 'app-feedback',
template: `
<button (click)="toggleWidget()">
{{ getButtonText() }}
</button>
`
})
export class FeedbackComponent implements OnInit {
widgetState = { isOpen: false, section: null };
ngOnInit() {
// Poll widget state
interval(500).subscribe(() => {
this.widgetState = (window as any).uj.getWidgetState();
});
}
toggleWidget() {
if (this.widgetState.isOpen) {
(window as any).uj.hideWidget();
} else {
(window as any).uj.showWidget({ section: 'feedback' });
}
}
getButtonText() {
return this.widgetState.isOpen ? 'Close' : 'Feedback';
}
}
Analytics integration
Track widget interactions for insights.
// Track widget events
function trackWidgetEvent(action, data = {}) {
// Your analytics tool
analytics.track(`Widget ${action}`, {
...data,
timestamp: Date.now()
});
}
// Track opens
document.querySelector('.feedback-trigger').onclick = () => {
trackWidgetEvent('Opened', {
trigger: 'custom_button',
section: 'feedback'
});
window.uj.showWidget({ section: 'feedback' });
};
// Track state changes
let lastState = { isOpen: false };
setInterval(() => {
const state = window.uj.getWidgetState();
if (state.isOpen && !lastState.isOpen) {
trackWidgetEvent('Opened', {
section: state.section
});
} else if (!state.isOpen && lastState.isOpen) {
trackWidgetEvent('Closed', {
lastSection: lastState.section
});
}
lastState = state;
}, 1000);
Keyboard shortcuts
Add keyboard shortcuts to open the widget.
document.addEventListener('keydown', (e) => {
// Cmd/Ctrl + K to open feedback
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
e.preventDefault();
const state = window.uj.getWidgetState();
if (state.isOpen) {
window.uj.hideWidget();
} else {
window.uj.showWidget({ section: 'feedback' });
}
}
});