Customization
Advanced customization options for the Notedis feedback widget.
Overview
Beyond basic configuration, you can deeply customize the widget's appearance, behavior, and integration with your site.
Custom Styling with CSS
Targeting Widget Elements
The widget uses specific IDs and classes you can target with CSS:
/* Feedback button */
#notedis-feedback-button {
/* Your custom styles */
}
/* Modal overlay */
#notedis-modal-overlay {
/* Your custom styles */
}
/* Modal container */
#notedis-modal {
/* Your custom styles */
}
Change Button Size
#notedis-feedback-button {
padding: 16px 24px !important;
font-size: 18px !important;
}
Change Button Shape
/* Circular button */
#notedis-feedback-button {
border-radius: 50% !important;
width: 60px !important;
height: 60px !important;
padding: 0 !important;
}
/* Square button */
#notedis-feedback-button {
border-radius: 0 !important;
}
/* Pill shape */
#notedis-feedback-button {
border-radius: 50px !important;
}
Custom Button Shadow
#notedis-feedback-button {
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.3) !important;
}
/* Remove shadow */
#notedis-feedback-button {
box-shadow: none !important;
}
Adjust Z-Index
If the widget is appearing behind other elements:
#notedis-feedback-button {
z-index: 999999 !important;
}
#notedis-modal-overlay {
z-index: 999998 !important;
}
#notedis-modal {
z-index: 999999 !important;
}
Responsive Button Size
/* Default size */
#notedis-feedback-button {
padding: 12px 20px !important;
font-size: 14px !important;
}
/* Smaller on mobile */
@media (max-width: 768px) {
#notedis-feedback-button {
padding: 10px 16px !important;
font-size: 12px !important;
}
}
Custom Position with CSS
Override default position:
/* Centered at bottom */
#notedis-feedback-button {
left: 50% !important;
right: auto !important;
transform: translateX(-50%) !important;
bottom: 20px !important;
}
/* Top center */
#notedis-feedback-button {
left: 50% !important;
right: auto !important;
transform: translateX(-50%) !important;
top: 20px !important;
bottom: auto !important;
}
Custom Animations
/* Pulse animation */
@keyframes pulse {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(1.05);
}
}
#notedis-feedback-button {
animation: pulse 2s infinite !important;
}
/* Slide in from right */
@keyframes slideIn {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
#notedis-feedback-button {
animation: slideIn 0.5s ease-out !important;
}
Dark Theme Customization
If your site has a dark mode:
/* Dark mode widget button */
@media (prefers-color-scheme: dark) {
#notedis-feedback-button {
background-color: #1f2937 !important;
color: #f9fafb !important;
border: 1px solid #374151 !important;
}
#notedis-feedback-button:hover {
background-color: #374151 !important;
}
}
Custom Trigger Button
Hide the default button and use your own custom trigger.
Basic Custom Trigger
<!-- Your custom button -->
<button id="my-feedback-btn" class="my-custom-class">
Give Feedback
</button>
<script>
window.notedisConfig = {
siteKey: 'your-site-key',
apiUrl: 'https://notedis.com',
hideButton: true // Hide default button
};
</script>
<script src="https://notedis.com/js/widget.js" defer></script>
<script>
// Wait for widget to load
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('my-feedback-btn').addEventListener('click', function() {
if (window.notedisWidget) {
window.notedisWidget.open();
}
});
});
</script>
Multiple Trigger Buttons
<!-- Multiple buttons on different pages -->
<button class="feedback-trigger">Report Bug</button>
<button class="feedback-trigger">Send Feedback</button>
<button class="feedback-trigger">Contact Us</button>
<script>
window.notedisConfig = {
siteKey: 'your-site-key',
apiUrl: 'https://notedis.com',
hideButton: true
};
</script>
<script src="https://notedis.com/js/widget.js" defer></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Attach to all buttons with class
document.querySelectorAll('.feedback-trigger').forEach(function(button) {
button.addEventListener('click', function() {
if (window.notedisWidget) {
window.notedisWidget.open();
}
});
});
});
</script>
Custom Trigger with Icon
<!-- Font Awesome icon -->
<button id="feedback-icon" style="position: fixed; bottom: 20px; right: 20px; background: #3B82F6; color: white; border: none; border-radius: 50%; width: 60px; height: 60px; cursor: pointer; box-shadow: 0 4px 6px rgba(0,0,0,0.1);">
<i class="fas fa-comment-alt fa-lg"></i>
</button>
<script>
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('feedback-icon').addEventListener('click', function() {
window.notedisWidget?.open();
});
});
</script>
Trigger from Navigation Menu
<!-- In your site navigation -->
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/contact">Contact</a>
<a href="#" id="feedback-link">Feedback</a>
</nav>
<script>
document.getElementById('feedback-link').addEventListener('click', function(e) {
e.preventDefault();
window.notedisWidget?.open();
});
</script>
Callback Functions
Execute custom code when widget events occur.
Track When Widget Opens
window.notedisConfig = {
siteKey: 'your-site-key',
apiUrl: 'https://notedis.com',
onOpen: function() {
console.log('Feedback widget opened');
// Track with Google Analytics
if (window.gtag) {
gtag('event', 'feedback_opened', {
event_category: 'engagement'
});
}
// Track with Mixpanel
if (window.mixpanel) {
mixpanel.track('Feedback Widget Opened');
}
// Show a tooltip or help text
document.getElementById('help-text').style.display = 'block';
}
};
Track When Feedback Is Submitted
window.notedisConfig = {
siteKey: 'your-site-key',
apiUrl: 'https://notedis.com',
onSubmit: function(feedback) {
console.log('Feedback submitted:', feedback);
// Show thank you message
alert('Thank you for your feedback!');
// Track with analytics
if (window.gtag) {
gtag('event', 'feedback_submitted', {
event_category: 'engagement',
feedback_category: feedback.category,
feedback_priority: feedback.priority
});
}
// Redirect to thank you page
// window.location.href = '/thank-you';
// Or show a custom modal
document.getElementById('thank-you-modal').classList.add('show');
}
};
Track When Widget Closes
window.notedisConfig = {
siteKey: 'your-site-key',
apiUrl: 'https://notedis.com',
onClose: function() {
console.log('Feedback widget closed');
// Hide help text
document.getElementById('help-text').style.display = 'none';
// Track abandonment
if (window.gtag) {
gtag('event', 'feedback_closed', {
event_category: 'engagement'
});
}
}
};
Combined Example
window.notedisConfig = {
siteKey: 'your-site-key',
apiUrl: 'https://notedis.com',
onOpen: function() {
// Pause video if playing
const video = document.querySelector('video');
if (video && !video.paused) {
video.pause();
window.videoPausedByWidget = true;
}
// Track analytics
gtag?.('event', 'feedback_opened');
},
onClose: function() {
// Resume video if we paused it
if (window.videoPausedByWidget) {
const video = document.querySelector('video');
video?.play();
window.videoPausedByWidget = false;
}
},
onSubmit: function(feedback) {
// Show thank you message
const toast = document.createElement('div');
toast.textContent = 'Thank you for your feedback!';
toast.style.cssText = 'position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); background: #10b981; color: white; padding: 12px 24px; border-radius: 8px; z-index: 999999;';
document.body.appendChild(toast);
setTimeout(() => toast.remove(), 3000);
// Track detailed analytics
gtag?.('event', 'feedback_submitted', {
category: feedback.category,
priority: feedback.priority,
has_screenshot: !!feedback.screenshot,
page_url: window.location.href
});
}
};
Programmatic Control
Control the widget via JavaScript.
Open Widget Programmatically
// From anywhere in your code
if (window.notedisWidget) {
window.notedisWidget.open();
}
Close Widget Programmatically
if (window.notedisWidget) {
window.notedisWidget.close();
}
Trigger After User Action
// Open after user spends 30 seconds on page
setTimeout(() => {
window.notedisWidget?.open();
}, 30000);
// Open when user scrolls to bottom
window.addEventListener('scroll', function() {
const scrolledToBottom = (window.innerHeight + window.scrollY) >= document.body.offsetHeight;
if (scrolledToBottom) {
window.notedisWidget?.open();
}
});
// Open on exit intent
document.addEventListener('mouseout', function(e) {
if (e.clientY < 0) {
window.notedisWidget?.open();
}
});
Conditional Display
Show widget only in specific conditions.
Show Only for Logged-In Users
// Check if user is logged in
const isLoggedIn = document.body.classList.contains('logged-in');
// Or check a cookie, session storage, etc.
if (isLoggedIn) {
window.notedisConfig = {
siteKey: 'your-site-key',
apiUrl: 'https://notedis.com'
};
const script = document.createElement('script');
script.src = 'https://notedis.com/js/widget.js';
script.defer = true;
document.body.appendChild(script);
}
Hide on Specific Pages
// Don't show on checkout or payment pages
const hideOnPages = ['/checkout', '/payment', '/cart'];
const currentPath = window.location.pathname;
const shouldHide = hideOnPages.some(page => currentPath.includes(page));
if (!shouldHide) {
window.notedisConfig = {
siteKey: 'your-site-key',
apiUrl: 'https://notedis.com'
};
const script = document.createElement('script');
script.src = 'https://notedis.com/js/widget.js';
script.defer = true;
document.body.appendChild(script);
}
Show Only on Staging/Dev
// Only show on non-production environments
const isProduction = window.location.hostname === 'mysite.com';
if (!isProduction) {
window.notedisConfig = {
siteKey: 'your-dev-site-key',
apiUrl: 'https://notedis.com',
color: '#ef4444', // Red for dev
buttonText: '🚧 Dev Feedback'
};
const script = document.createElement('script');
script.src = 'https://notedis.com/js/widget.js';
script.defer = true;
document.body.appendChild(script);
}
Show Based on User Role
// Get user role from your app
const userRole = window.appData?.userRole; // 'admin', 'editor', 'subscriber', etc.
if (['admin', 'editor'].includes(userRole)) {
window.notedisConfig = {
siteKey: 'your-site-key',
apiUrl: 'https://notedis.com',
buttonText: 'Staff Feedback'
};
const script = document.createElement('script');
script.src = 'https://notedis.com/js/widget.js';
script.defer = true;
document.body.appendChild(script);
}
Integration Examples
Google Analytics Integration
window.notedisConfig = {
siteKey: 'your-site-key',
apiUrl: 'https://notedis.com',
onOpen: function() {
gtag('event', 'feedback_widget_opened', {
event_category: 'Engagement',
event_label: window.location.pathname
});
},
onSubmit: function(feedback) {
gtag('event', 'feedback_submitted', {
event_category: 'Engagement',
event_label: feedback.category,
value: feedback.priority === 'high' ? 3 : feedback.priority === 'medium' ? 2 : 1
});
}
};
Mixpanel Integration
window.notedisConfig = {
siteKey: 'your-site-key',
apiUrl: 'https://notedis.com',
onSubmit: function(feedback) {
mixpanel.track('Feedback Submitted', {
category: feedback.category,
priority: feedback.priority,
page: window.location.pathname,
has_screenshot: !!feedback.screenshot
});
}
};
Intercom Integration
window.notedisConfig = {
siteKey: 'your-site-key',
apiUrl: 'https://notedis.com',
onSubmit: function(feedback) {
// Log feedback submission in Intercom
if (window.Intercom) {
Intercom('trackEvent', 'feedback-submitted', {
category: feedback.category,
priority: feedback.priority
});
}
}
};
Advanced Customization
Detect Widget Load
// Check when widget is fully loaded
const checkWidgetLoaded = setInterval(() => {
if (window.notedisWidget) {
console.log('Widget loaded and ready');
clearInterval(checkWidgetLoaded);
// Now you can safely use widget methods
// window.notedisWidget.open();
}
}, 100);
Custom Loading Indicator
// Show loading indicator while widget loads
const loadingIndicator = document.createElement('div');
loadingIndicator.id = 'widget-loading';
loadingIndicator.textContent = 'Loading feedback widget...';
document.body.appendChild(loadingIndicator);
const checkLoaded = setInterval(() => {
if (window.notedisWidget) {
loadingIndicator.remove();
clearInterval(checkLoaded);
}
}, 100);
Pre-fill Feedback Data
While the widget doesn't support pre-filling user input directly, you can use callbacks to capture additional context:
window.notedisConfig = {
siteKey: 'your-site-key',
apiUrl: 'https://notedis.com',
onSubmit: function(feedback) {
// Send additional context to your backend
fetch('/api/feedback-context', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
feedbackId: feedback.id,
userId: window.currentUser?.id,
userPlan: window.currentUser?.plan,
pageLoadTime: performance.now(),
browserMemory: performance.memory?.usedJSHeapSize
})
});
}
};
Accessibility Customization
Keyboard Shortcuts
// Open widget with Ctrl+K or Cmd+K
document.addEventListener('keydown', function(e) {
if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
e.preventDefault();
window.notedisWidget?.open();
}
});
High Contrast Mode
/* For users with high contrast preferences */
@media (prefers-contrast: high) {
#notedis-feedback-button {
border: 2px solid currentColor !important;
font-weight: bold !important;
}
}
Reduced Motion
/* Respect user's motion preferences */
@media (prefers-reduced-motion: reduce) {
#notedis-feedback-button {
animation: none !important;
transition: none !important;
}
}
Next Steps
- Configuration - Basic widget configuration
- Features - Explore all widget features
- Troubleshooting - Common issues and solutions
- Team Collaboration - Work with your team