Create a pop-up survey in Drupal
Written by NewTrick
15 Jul 2025
#Drupal #webforms

This guide outlines the steps to build a simple pop up survey using Drupal webforms.
The goal is to build a small user satisfaction survey that appears on the bottom of the page (and then leaves the user in peace once done).
This would be useful for anyone wanting to gauge user feedback. Because Drupal webforms and blocks are so flexible, this can be set up on a single page, a section of the site, or the whole website. On top of that, you can do this as through the CMS with the right permissions because, even though it needs some CSS and JavaScript, this can be added via the webforms module. So no code changes needed!
Create a webform
You'll need a Drupal project with the webform module installed. Make sure the module is configured to allow whatever role you are using to have access to the settings you need. Once installed, you can begin.
Create the form via structure->webforms and then 'Add Webform'.
To begin making the form, we will add three pages via 'Add pages'. You only need to fill out the Title field (Page 1, Page 2, and Page 3 are fine) and set the page settings button labels to '< prev' and 'next >'. Using pages allows you to display one question at a time, so that the survey doesn't take up too much of the page.
We are then going to add three questions--one for each page. Use radios, ratings,
and Likert scales so you don't make the whole thing too onerous. Questions could be things like "Rate your experience using this website", followed by a 1 to 5 scale. The simpler the better. Whatever questions you choose, just make sure there is one per page. You can drag the question to the right to indent it under each page.
Create the settings
We now need to tweak some of the settings.
There might be more you would like to play with, but these are the key changes:
- Under 'General', change the Ajax settings to 'Use Ajax', the progress bar to 'Throbber', and set the effect to 'Slide'. This will make sure that your form does not reload the page that it is on, and still submits and progresses to each question.
- Under 'Settings', disable the show progress bar.
- Under 'Submissions', we can handle whether users can submit the form more than once. We are going to allow users to answer once per day. To do this select 'Show the notification about previous submissions' under 'Submission behaviour' Set 'Submission Access Denied Settings' to the page option, and change the 'per user' options to 1 every day. You can also set a custom message that will display to the user if they try and resubmit. Webforms uses IP addresses to determine whether submissions have been made.
- Under 'Confirmation', we will set the confirmation type to be 'Inline...', so that we are not taken to a new page, and set the message to 'Thanks! Your submission was received. You can close this box.' or similar.
We will leave the rest for now, but we will be back to the CSS/JS tab later.
Create a block
We will need to create a block to display the webform. Thankfully, Drupa makes this very easy. You can simply create a new webform block via content->blocks->Add content block->webform block. Just select the webform you have just created. Hide the label for webform via 'Manage Display' if you haven't already.
In terms of placement, I used a hidden region so that I could have the block on each page, but you could otherwise place it in any region. We'll be setting the position later, so it will be visible for now, until we set it's position as absolute. You can also select which pages you would like it to be visible or hidden on. If you don't have a hidden region, it's best to limit this to a test page for now so it doesn't appear across your site.
Create the JavaScript
Jump back into the webform settings and we will deal with the functionality. The cool thing about webforms is that you can add custom JS and CSS that will load on any page with the webform. Developers might not love this workflow, but it does allow more immediate control over the form.
I've added comments to this script to explain what is happening, but the main thing is that you have the name as your block set as $popup.
(function ($, Drupal) {
Drupal.behaviors.popUpSurvey = {
attach: function (context, settings) {
var formAdded = false;
var isOpen = true; // Start open when first shown
// Function to initialize popup elements
function initializePopup() {
var $popup = $('#block-finance-popupsurvey');
// Check if popup exists
if (!$popup.length) {
return false;
}
// Check if elements already exist to prevent duplicates
if ($popup.find('.popup-tab').length || $popup.find('.popup-close').length) {
return false;
}
$popup.addClass('popup-made-visible');
// Add close/open tab
var $tab = $('<div class="popup-tab" role="button" aria-label="Reopen survey">Help us improve this website</div>');
var $closeBtn = $('<button class="popup-close" aria-label="Close survey">×</button>');
// Verify elements were created
if (!$tab.length || !$closeBtn.length) {
return false;
}
// Prepend tab and close button to popup
$popup.prepend($closeBtn);
$popup.prepend($tab);
// Bind events directly to the elements after creation
$closeBtn.on('click.popupClose', function(e) {
e.preventDefault();
e.stopPropagation();
// Force state change
$popup.removeClass('popup-open').addClass('popup-closed');
$popup.attr('aria-expanded', 'false');
// Make tab keyboard accessible when closed
$tab.attr({
'tabindex': '0',
'aria-pressed': 'false'
});
isOpen = false;
});
$tab.on('click.popupTab keydown.popupTab', function(e) {
// Handle keyboard activation (Enter or Space)
if (e.type === 'keydown' && e.which !== 13 && e.which !== 32) {
return;
}
e.preventDefault();
e.stopPropagation();
if (!isOpen) {
$popup.removeClass('popup-closed').addClass('popup-open');
$popup.attr('aria-expanded', 'true');
// Remove keyboard focus from tab when open
$tab.removeAttr('tabindex').removeAttr('aria-pressed');
isOpen = true;
}
});
// Start in open state with proper attributes
$popup.addClass('popup-open').attr('aria-expanded', 'true');
// Initially, tab should not be keyboard focusable (form is open)
$tab.removeAttr('tabindex');
return true;
}
// Scroll listener - only handles showing/hiding
window.addEventListener('scroll', function (e) {
if (window.scrollY > 500 && !formAdded) {
if (initializePopup()) {
formAdded = true;
}
}
});
}
}
})(jQuery, Drupal);
This will do a couple of things:
- The form will appear when the user scrolls down the page--but only if the form is not already there.
- Handle the form so that elements are not re-added on each ajax request.
- Make it a bit more accessible to allow tabindex and keyboard functionality.
- Create an open/close click function using either the tab that is created or an X icon.
Create the styling
We will need to combine this functionality with some styling.
Just be sure to change the name of the block to the id of the block you created earlier:
/* Base popup styles */
.popup-made-visible {
position: fixed;
right: 10px;
bottom: 10px;
z-index: 1000;
display: flex;
flex-direction: column;
justify-content: flex-end;
background-color: white;
border: 4px solid black;
border-radius: 10px;
transition: all 0.3s ease;
overflow: hidden;
box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
}
/* Tab that's always visible */
.popup-tab {
color: black;
font-size: large !important;
padding: 8px 16px;
cursor: pointer;
text-align: center;
font-weight: bold;
font-size: 14px;
order: -2; /* Always appears at top */
transition: background-color 0.3s ease;
}
.popup-tab:hover {
background-color: black;
color: white;
}
/* Close button */
.popup-close {
color: black;
border: none;
background-color: white;
border-radius: 50%;
cursor: pointer;
font-size: 26px;
line-height: 1;
position: absolute;
top: 2px;
right: 2px;
z-index: 10;
order: -1;
transition: background-color 0.3s ease;
}
.popup-close:hover {
background: #c82333;
}
/* Open state */
.popup-open {
padding: 1rem;
max-height: 400px;
width: 300px;
}
.popup-open .popup-tab {
pointer-events: none; /* Disable clicking when open */
cursor: default;
border-bottom: 1px dotted black;
}
/* Closed state */
.popup-closed {
padding: 0;
max-height: fit-content;
width: 120px;
border: 4px solid black;
}
.popup-closed .popup-close {
display: none;
}
.popup-closed > *:not(.popup-tab) {
display: none;
}
/* Form styling */
#YOUR-BLOCK-ID {
text-align: center;
}
/* Accessibility */
#YOUR-BLOCK-ID:has(.popup-tab:focus),
.popup-close:focus,
{
outline:4px solid #64ccc9;
}
.popup-closed .popup-tab:focus {
background-color: #005a87;
color: white;
}
This will provide the box with what you need to show and hide the survey, as
well as supporting the accessibility.
Save and test. You should see the box appear once a user scrolls down. It will
also disappear once the user has responded, so it doesn't bother them when they
have already done.
A note on accessibility
Just a note on accessibility. Because we are using position: absolute to place the form, and because you might have placed the form in the footer, it can be a bit of a pain to tab through a busy page to get to the form. We've made sure that keyboard users can access the form, and added some visual highlights, but it might be worth adding a static page with the same webform to allow all users to access the form more easily.
And that's it! Leveraging Drupal's powerful webform module, we have a quick and easy pop up survey.
Photo credit:
Photo by Towfiqu barbhuiya on Unsplash.