Skip to content
Greeto

June 29, 2026 · 9 min read · Updated June 29, 2026

Add HubSpot Forms to WordPress: Plugin vs Embed Done Right

The plain, operator's way to put HubSpot forms on WordPress, style them, and capture leads without breaking your site.

By Tal Gerafi, Founder & Website Engineer

B2B websitesLead capture

There are two reliable ways to add a HubSpot form to WordPress: install the HubSpot WordPress plugin and drop the form in with a block or shortcode, or paste HubSpot's embed code into a Custom HTML block. Use the plugin when your marketing team wants to publish without a developer. Use the raw embed when you need exact control over markup and styling. Both submit straight to HubSpot, so your CRM, workflows, and lead routing work the same either way.

The choice matters because it decides who can edit forms later, how much your theme can break them, and how cleanly you can track submissions. Below is the plain version of how to set each up, style them so a theme update doesn't wreck them, and make sure leads actually land in HubSpot.

Plugin vs embed: which should I use for HubSpot forms in WordPress?

Pick the plugin when speed and self-service matter more than pixel control. Pick the embed when design control matters more than editor convenience. Here is the trade-off side by side.

HubSpot WordPress pluginRaw embed code
Setup speedFast (install, connect, drop block)Medium (paste two scripts)
Who can editMarketers, no codeUsually a developer
Styling controlMediumHigh
Risk from theme/plugin updatesHigher (markup can shift)Lower (you own the container)
Extra weightLoads HubSpot's plugin assets sitewideLoads only where you place it
Best fitMarketing-led teamsDesign-strict or performance-strict sites

A practical rule: if the same five people who write the blog posts also need to change the form, use the plugin. If a developer owns the front end and cares about page weight and markup, use the embed. Many teams run the plugin for general landing pages and a hand-placed embed on the homepage hero where design has to be exact. That mix is fine as long as you load HubSpot's form script once per page, not twice.

How do I add a HubSpot form using the plugin?

Install the official HubSpot plugin from the WordPress plugin directory, then connect it to your HubSpot account (you'll authorize once via OAuth). After that, every form you build in HubSpot is available inside WordPress.

To place a form, edit a page and add the HubSpot Form block in the block editor, then select the form from the dropdown. If you use the classic editor or a page builder, the shortcode works anywhere:

[hubspot type="form" portal="YOUR_PORTAL_ID" id="YOUR_FORM_ID"]

The plugin's strength is that a marketer can change fields in HubSpot and the WordPress page updates without a deploy. Its weakness is that it adds tracking and chat scripts across your whole site by default, and a plugin update can change the form's HTML classes, which breaks any custom CSS you wrote against them. Two habits keep this calm: turn off the plugin features you don't use (live chat, the tracking code if you load it elsewhere), and scope your CSS to a wrapper class you control rather than HubSpot's internal class names.

How do I embed a HubSpot form with raw code?

Copy the embed snippet from HubSpot (Marketing → Forms → your form → Share → Embed code), then paste it into a Custom HTML block where you want the form. It looks like this:

<div id="wp-hs-form" class="hs-form-shell"></div>
<script charset="utf-8" type="text/javascript" src="//js.hsforms.net/forms/embed/v2.js"></script>
<script>
  hbspt.forms.create({
    portalId: "YOUR_PORTAL_ID",
    formId: "YOUR_FORM_ID",
    target: "#wp-hs-form",
    region: "na1"
  });
</script>

A few things make this robust. Give the target <div> a unique id and your own wrapper class (hs-form-shell above) so your styles never depend on HubSpot's markup. Load embed/v2.js once per page even if you have two forms. And set a min-height on the shell so the page doesn't jump when the form loads — that jump shows up as Cumulative Layout Shift in Core Web Vitals, and reserving space fixes it.

The embed route is also what you reach for when WordPress itself is getting heavy and you're eyeing a WordPress to Next.js migration: a hand-placed HubSpot embed moves to a new stack cleanly because it has no plugin dependency.

How do I style a HubSpot form so a theme update doesn't break it?

Style a wrapper you own, not HubSpot's classes. Wrap the form in a container class like .hs-form-shell, then write all your CSS as descendants of it. That way a theme update that changes generic input styles can't reach inside your form, and a HubSpot update that renames a class only affects the parts you didn't override.

.hs-form-shell input,
.hs-form-shell textarea,
.hs-form-shell select {
  width: 100%;
  min-height: 46px;
  border: 1px solid #ccd5e3;
  border-radius: 10px;
  padding: 10px 12px;
  font-size: 16px; /* 16px stops iOS from zooming on focus */
}

.hs-form-shell .hs-button {
  border: 0;
  border-radius: 999px;
  min-height: 46px;
  background: #102648;
  color: #fff;
  font-weight: 600;
  padding: 0 18px;
}

.hs-form-shell .hs-error-msg {
  color: #b42318;
  font-size: 13px;
}

Three details earn their keep. Set input font-size to 16px or larger so mobile Safari doesn't zoom on tap. Keep tap targets at least ~44px tall. And style the error and focus states, not just the resting state — most "the form feels cheap" complaints are really invisible focus rings and unreadable error text. Never style HubSpot's generic input selector at the theme level; keep every rule scoped to the shell.

Why is my HubSpot form not showing up in WordPress?

A HubSpot form that won't render almost always traces to one of four causes: the embed script is blocked or loaded twice, the target div ID doesn't match, a caching or optimization plugin is mangling the script, or a consent banner is holding the script until the visitor accepts cookies.

Work through them in order:

  1. Open the browser console. A hbspt is not defined error means the embed/v2.js script didn't load — check for ad blockers, a Content Security Policy, or a script-deferral plugin that broke the order.
  2. Match the IDs. The target in hbspt.forms.create must match the id on your div exactly, including the #.
  3. Check caching/minification. Plugins like WP Rocket or Autoptimize can combine or defer the HubSpot scripts in a way that breaks them. Exclude js.hsforms.net from JS optimization.
  4. Check consent gating. If you load HubSpot only after consent, the form won't appear until the visitor accepts. That can be correct behavior — but confirm it's intentional, and give a fallback such as a visible email or contact link.

If you run both the plugin and a manual embed on the same page, you can end up loading the form script twice, which is another common cause of forms that flicker, duplicate, or fail to bind.

How do I track HubSpot form submissions reliably?

Pick one source of truth for the submit event and stick to it. The most common mistake is firing a conversion from HubSpot's onFormSubmit callback and from a Google Tag Manager trigger, which double-counts every lead. Choose one path, and use the embed's built-in callback when you want a clean, single event.

<script>
  hbspt.forms.create({
    portalId: "YOUR_PORTAL_ID",
    formId: "YOUR_FORM_ID",
    target: "#wp-hs-form",
    region: "na1",
    onFormSubmit: function () {
      window.dataLayer = window.dataLayer || [];
      window.dataLayer.push({
        event: "hubspot_form_submit",
        form_id: "YOUR_FORM_ID",
        form_location: "contact_page"
      });
    }
  });
</script>

You don't need twenty events — you need the few that drive decisions: a submit event, and a form_location field so you can tell which page converts. Pass campaign context (UTM values) into HubSpot through hidden fields so sales sees where a lead came from, and review them each campaign so they don't go stale. If analytics only fire after cookie consent, wire the form event through the same consent gate you use for everything else — the same pattern as the Next.js consent-gated analytics playbook, which applies on WordPress too.

When does it make sense to move off WordPress entirely?

If forms keep breaking after every plugin or theme update, the form isn't the real problem — the stack is. A site weighed down by a dozen plugins (form, cache, security, builder, SEO) accumulates the kind of drift where a "small update" quietly breaks lead capture.

That's when teams look at rebuilding. A HubSpot embed carries over to a WordPress to Next.js rebuild almost unchanged, because it's just a script and a container with no plugin behind it. The harder part of any move is preserving rankings — handled with a proper redirect map and 301 redirects so old URLs don't drop. None of that is required to use HubSpot forms today; it's the path you take when WordPress maintenance costs more than it saves. And if conversion is the real goal, the form matters less than the page around it — that's building a B2B homepage that converts.

FAQ

Do HubSpot forms work without the WordPress plugin?

Yes. The raw embed code works on any WordPress site without the plugin — you paste two scripts into a Custom HTML block and the form submits directly to HubSpot. The plugin only adds an editor-friendly block and sitewide tracking; it isn't required for the form to function.

Will the HubSpot plugin slow down my WordPress site?

It can. By default the plugin loads tracking and chat assets across the whole site, not just on pages with forms. Disable the features you don't use, and if page weight is critical, the raw embed loads only where you place it.

Can I fully control HubSpot form styling in WordPress?

You can get very close. Wrap the form in your own class and scope all CSS to that wrapper, then style inputs, buttons, focus, and error states. You won't be able to restructure HubSpot's markup, but you can match your brand reliably without depending on HubSpot's internal class names.

Why does my HubSpot form load twice or flicker?

Usually because the embed/v2.js script is included more than once on the page, often from running the plugin and a manual embed together, or from a caching plugin duplicating scripts. Load the form script a single time per page and the flicker stops.

How do I stop the page from jumping when a HubSpot form loads?

Set a min-height on the form's container so the space is reserved before the script renders the fields. The jump is Cumulative Layout Shift, a Core Web Vitals signal, so fixing it helps both UX and search performance.

Should I send leads to a thank-you page or show an inline message?

Either works. Inline success messages create less friction and are simpler to track, while a dedicated thank-you page gives you a clean URL for a conversion goal and room for a next step. Choose based on your measurement setup, and label the event so you can tell completed submissions apart.