Want popup windows on your WordPress site without installing another plugin?
You do not need one. A short piece of code is enough to put a popup on a WordPress site.
Plugins come with upkeep. Each one is another thing to update and another possible way into your site's security. Some slow your pages down, too.
So why take on a plugin when the popup can run without one?
With Popupsmart, an easy-to-use popup builder, a single line of code runs your popups.
The whole setup is a 5-minute job.

What you'll need:
- An administrator login to your WordPress dashboard (on a multisite network, a super admin).
- A child theme if you use a classic theme, so a theme update doesn't wipe your code.
- For the embed method, a free Popupsmart account; for the hand-coded method, nothing else.
- A few minutes, and no coding for the embed method.
Which no-plugin method fits your WordPress site?
The embed script is the right method when you want a popup that collects leads and targets pages without code; the hand-coded <dialog> is right for one simple announcement. WordPress itself runs a large share of the web: according to W3Techs, it is used by 58.7% of the websites whose content management system is known, 40.2% of all websites (30 September 2026). Yet it has no popup block, so every WordPress popup comes from a plugin, a script or your own code.
| Popupsmart embed code | Hand-coded <dialog> popup |
A popup plugin | |
|---|---|---|---|
| What you add to WordPress | One <script> line |
HTML, CSS and JavaScript you write | A plugin you install and update |
| Where the popups are built | Popupsmart's dashboard | Your theme or a Custom HTML block | The WordPress admin |
| Collects emails | Yes, sent to your email tool | Only if you build the form handling | Usually through a form plugin |
| Triggers and targeting | Exit intent, scroll, time and page rules, set without code | Whatever you code | Depends on the plugin and its paid tier |
| Best for | Lead capture and offers across pages | One announcement or notice | Keeping everything inside WordPress |
How to Add Popup Code to Your WordPress Website?
The Popupsmart method adds one script to your theme, verifies the site, and then every popup is built and published from Popupsmart's dashboard. The steps below use a classic theme's Theme File Editor; the next section covers block themes and functions.php.
First, create your free account with Popupsmart.
1. After you sign up, you'll land on your dashboard. Start by adding your website: click your profile and choose "Websites."

2. Click the "New website" button.

3. Enter your website URL, and save it.

4. Your website will appear as "Unverified." Click on "Unverified" to see your embed code.

The code is one line, <script src="https://cdn.popupsmart.com/bundle.js" data-id="…" async defer></script>, and the data-id belongs to your account.
5. Copy the embed code to the clipboard. In your WordPress admin panel, go to "Appearance" and click "Theme File Editor."

6. Check your theme and click on the "Footer."

7. Paste your embed code before the </body> tag.

8. Don't forget to update your file.

Placement matters here. The code goes before the closing "body" tag, not after it.
footer.php. WordPress warns in the Theme File Editor that a theme update overwrites these files, and your popup disappears with it. Make the edit in a child theme's copy of footer.php.9. Go back to your Popupsmart dashboard and click "Verify".

That opens your WordPress site in the browser. If a small modal pops up saying "Popupsmart installation verified.", the install worked.

On Popupsmart's Websites page, a verified site looks like this:

And here's the popup, live on the site:

That's a WordPress popup with no plugin installed.
The install is a one-time job. From here, you create a campaign in Popupsmart, choose your WordPress website, pick one of the popup templates, set who sees it and when, and publish. Popupsmart's free plan covers one website, one live popup and 5,000 pageviews a month, so you can finish this guide without paying. The WordPress popup guide covers the same install with Popupsmart's help-center screenshots.
header.php, footer.php and any Custom HTML blocks before you paste it again.Where to paste the embed code: block themes vs classic themes
Where the code goes depends on your theme type. A block theme (Twenty Twenty-Four, Twenty Twenty-Five) has no footer.php to edit and is changed in the Site Editor; a classic theme keeps header.php and footer.php files you can edit, ideally in a child theme. Any theme can load the script from functions.php.
Block themes: a Custom HTML block in the Site Editor
- Go to Appearance → Editor and open the Footer template part (under Patterns, or by clicking the footer on any template).
- Add a Custom HTML block at the end of the footer and paste the embed code.
- Click Save.
The Site Editor saves your changed template part in the database, so a theme update doesn't remove the code. Switching to another theme does, because the change belongs to that theme. The block keeps a <script> tag only for users who are allowed to post unfiltered HTML: administrators on a single site, super admins on a multisite network.
Classic themes: footer.php or header.php in a child theme
In Appearance → Theme File Editor, paste the code just before </body> in footer.php, as in steps 5 to 8 above, or just before </head> in header.php. Both work, because the script loads with async defer and doesn't hold up the page. Do it in a child theme: the parent theme's files are replaced on every update.
If you can't find the Theme File Editor, your host or a security setting has probably turned it off (the DISALLOW_FILE_EDIT constant does this). Then use SFTP, functions.php in a child theme, or the Google Tag Manager install.
Any theme: functions.php with wp_enqueue_script
The WordPress way to add a script is wp_enqueue_script. Since WordPress 6.3 it takes a loading strategy (async or defer), and a small filter adds the data-id attribute Popupsmart reads. All three snippets below load the same script:
<!-- Custom HTML block at the end of the Footer template part -->
<script src="https://cdn.popupsmart.com/bundle.js" data-id="YOUR_ACCOUNT_ID" async defer></script>
<?php /* Child theme's footer.php: keep wp_footer(), then the script, then </body> */ ?>
<?php wp_footer(); ?>
<script src="https://cdn.popupsmart.com/bundle.js" data-id="YOUR_ACCOUNT_ID" async defer></script>
</body>
</html>
// Child theme's functions.php, WordPress 6.3 or later.
add_action( 'wp_enqueue_scripts', function () {
wp_enqueue_script(
'popupsmart',
'https://cdn.popupsmart.com/bundle.js',
array(),
null, // no ?ver= query string
array( 'in_footer' => true, 'strategy' => 'async' )
);
} );
// Add the data-id attribute from your embed code.
add_filter( 'script_loader_tag', function ( $tag, $handle ) {
if ( 'popupsmart' === $handle ) {
$tag = str_replace( ' src=', ' data-id="YOUR_ACCOUNT_ID" src=', $tag );
}
return $tag;
}, 10, 2 );
Replace YOUR_ACCOUNT_ID with the number in your own embed code. You'll know it's working when the page source (Ctrl+U) shows one cdn.popupsmart.com/bundle.js line and Popupsmart's Verify step shows the installation message.
functions.php can take the whole site down. Edit it over SFTP with a backup, not in the Theme File Editor on a live site, so you can undo the change if the page goes blank.How to build a popup with HTML, CSS and JavaScript
A hand-coded WordPress popup is a <dialog> element opened with showModal(). The browser then does the hard parts for you: according to MDN's dialog reference, a modal dialog makes the rest of the page inert, draws a ::backdrop behind itself and closes on the Esc key. This example opens after five seconds, once per visitor, and closes on the × button, Esc or a click on the backdrop.
<dialog id="wp-popup" class="wp-popup" aria-labelledby="wp-popup-title">
<div class="wp-popup__inner">
<form method="dialog">
<button class="wp-popup__close" aria-label="Close">×</button>
</form>
<h2 id="wp-popup-title">Get new posts by email</h2>
<p>One email a week. Unsubscribe any time.</p>
<a class="wp-popup__cta" href="/newsletter/">Subscribe</a>
</div>
</dialog>
<style>
.wp-popup { width: min(420px, calc(100% - 2rem)); padding: 0; border: 0; border-radius: 12px; }
.wp-popup::backdrop { background: rgb(0 0 0 / 0.5); }
.wp-popup__inner { position: relative; padding: 2rem 1.5rem 1.5rem; text-align: center; }
.wp-popup__close { position: absolute; top: 0.5rem; right: 0.5rem; width: 44px; height: 44px;
border: 0; background: none; font-size: 1.5rem; cursor: pointer; }
.wp-popup__cta { display: block; padding: 0.75rem; border-radius: 8px;
background: #1b6ef3; color: #fff; text-decoration: none; }
@media (prefers-reduced-motion: no-preference) {
.wp-popup[open] { animation: wp-popup-in 0.2s ease-out; }
}
@keyframes wp-popup-in { from { opacity: 0; transform: translateY(8px); } }
</style>
<script>
(function () {
var popup = document.getElementById('wp-popup');
if (!popup || typeof popup.showModal !== 'function') return;
try { if (localStorage.getItem('wpPopupSeen')) return; } catch (e) {}
setTimeout(function () {
popup.showModal();
try { localStorage.setItem('wpPopupSeen', '1'); } catch (e) {}
}, 5000);
// A click on the backdrop lands on the dialog itself, not its inner box.
popup.addEventListener('click', function (event) {
if (event.target === popup) popup.close();
});
})();
</script>
Where to put it: in a Custom HTML block on the one page that needs the popup, or in the footer template part (or footer.php) to show it on every page. The WordPress editor keeps the <script> only for users allowed to post unfiltered HTML, as with the embed code.
What this popup doesn't do is the rest of the job. The Subscribe button only links to a page: storing an email address means wiring a form to your email tool or a form plugin. There is no targeting by page, device or traffic source, no A/B test and no report of how many people saw it, unless you write each of those. For one announcement that is fine; for lead capture it is where the embed method earns its line of code.
Accessibility checklist for a hand-coded popup:
- The dialog is named by its heading (
aria-labelledby), and the close button has an accessible name (aria-label="Close"). showModal(), notshow(): only the modal version makes the page behind it inert and closes on Esc.- A close target of at least 44×44 px, so it can be tapped on a phone.
- Motion only inside
prefers-reduced-motion: no-preference. - Once per visitor (the
localStorageflag), not on every page view.
Why five seconds? It's a sensible default, nothing more. In Popupsmart's 2026 popup benchmark, popups that wait before appearing convert 0.83% vs 0.61% for popups shown the instant the page loads (median campaign); the direction holds in every year of data but the difference is not statistically reliable, so treat it as a lean, not a rule.
The exact delay length (0-5 seconds vs 21-60 seconds) makes no measurable difference to conversion, so don't spend long tuning the number in setTimeout.
Those numbers are why the min(420px, calc(100% - 2rem)) width and the 44 px close button matter: most people who see your popup will see it on a phone. Test it at a 375 px viewport before you publish, and read the mobile popups guide for the layout rules.
For image and video popups, you may not need any code. The core Image block has an Expand on click setting that opens the image in a lightbox, and the modal popup tutorial covers more hand-coded modal patterns. To open a popup from a button instead of a timer, see popups that open on a button click.
How do popups perform on WordPress sites?
Popups on WordPress sites ask for an email or phone number in a quarter of campaigns, and the median WordPress campaign converts 0.66% of its displays. Across Popupsmart's data, 43% of the businesses in the benchmark (January 2024 - September 2026) run on Shopify; the WordPress ecosystem (WordPress and WooCommerce) accounts for 14%, custom-built sites on frameworks like Next.js for 2.5%. 35% of popup campaigns on Shopify stores ask for an email or phone number, against 25% on WordPress sites. Popups on Shopify stores convert at 1.07% vs 0.66% on WordPress sites (median campaign).
| Popups in Popupsmart's benchmark | Shopify stores | WordPress sites |
|---|---|---|
| Campaigns that ask for an email or phone number | 35% | 25% |
| Median campaign conversion rate | 1.07% | 0.66% |
We read the WordPress figure as a description of the sites, not of the install method: a WordPress site is often a blog or a company site, where fewer popups ask for anything. How you add the popup, plugin or script, isn't in the data. What you ask for, and when, is what you can change.
When is a popup plugin still the better choice?
A plugin is the better choice when you want everything inside WordPress, or when you can't add code to the site at all. Pick one when:
- Leads must stay in your WordPress database, for example under a data policy that rules out a third-party service.
- You already run a form plugin such as Contact Form 7, Gravity Forms or WPForms, and a popup plugin can open those forms.
- You can't edit theme files,
functions.phpor Custom HTML, for example as an editor on a multisite network, and Google Tag Manager isn't an option. - You want popups that follow WordPress content rules, such as showing on posts in one category, managed by the people who already work in the WordPress admin.
The comparison of WordPress popup plugins covers the main options and what each charges. If Mailchimp is your email tool, the guide to adding a Mailchimp popup on WordPress shows both Mailchimp's own popup form and the builder route.
WordPress popup not showing? Check these
When a plugin-free popup doesn't appear, check the cache first, then the code, then the trigger:
- A cache is serving the old page. Clear your caching plugin and CDN after adding the code, then test in a private window.
- An optimization plugin delays or combines JavaScript. "Delay JavaScript" and "combine scripts" settings can hold the embed code until the visitor interacts. Exclude
cdn.popupsmart.comfrom them. - The theme was updated. Code pasted into the parent theme's
footer.phpis gone after an update; paste it into a child theme or the Site Editor. - The code is on the page twice. Search the page source for
bundle.js; keep one copy. - The website isn't verified, or the address doesn't match.
www.example.comandexample.comare different sites to Popupsmart. Add the address your visitors use. - You've already seen it. A once-per-visitor rule (Popupsmart's frequency setting or the
localStorageflag above) hides it on your second visit. A private window starts fresh.
WordPress popup without plugin FAQ
Can you add a popup to WordPress without a plugin?
Yes. WordPress has no popup block, but you can paste a popup tool's embed script into your theme, add it through a Custom HTML block in the Site Editor, or hand-code a popup with the HTML dialog element. Each method adds a popup without installing a plugin.
Where do I paste popup code in WordPress?
On a block theme, paste it into a Custom HTML block in the Footer template part through Appearance → Editor. On a classic theme, paste it into your child theme's footer.php just before the closing body tag, or into header.php before the closing head tag.
Will a theme update delete my popup code?
Yes, if you pasted it into the parent theme's files: a theme update replaces them. Put the code in a child theme, or on a block theme in the Site Editor, which saves your template part changes in the database instead of the theme files.
Is there a free way to add a popup to WordPress without a plugin?
Yes. A hand-coded dialog popup costs nothing but your time. Popupsmart's free plan also runs a popup from its embed code, with one website, one live popup and 5,000 pageviews a month.
Can I make an exit-intent popup in WordPress without a plugin?
Yes. Popupsmart's embed code supports exit intent, scroll and time triggers that you set in the dashboard. In hand-written JavaScript you would listen for the cursor leaving the page yourself, and that doesn't work on phones, where there is no cursor.
Why is my WordPress popup not showing?
The usual causes are a caching or optimization plugin serving an old or delayed script, code pasted into a theme that was since updated, the same embed code added twice, or a website that isn't verified in Popupsmart. Clear the cache and test in a private window first.
Does a popup script slow down WordPress?
Popupsmart's embed code loads with async and defer, so the browser doesn't wait for it before showing the page, and Popupsmart measures the script at about 97 KB. A hand-coded dialog popup adds only the few lines you write.
Conclusion
A WordPress popup without a plugin comes down to one decision: write the popup yourself with <dialog>, or paste one script and build the popup in Popupsmart. Put either one in a child theme or the Site Editor so an update can't erase it, and test it on a phone first.
After that, the work is in the campaigns themselves. The conversion rate optimization guide walks through ways to increase your conversions once your popups are live.
You may also like: