astro tutorial embed

How to Add a Form to Your Astro Site

A step by step guide to embedding OziForms forms in Astro projects. Zero JavaScript framework dependencies, optimal performance, and production-ready patterns.

Astro’s philosophy is simple: ship less JavaScript. That’s exactly why our embed runtime pairs so well with it. At 2KB, the OziForms embed adds less weight than most analytics scripts.

This guide covers everything from basic embed to advanced patterns for production Astro sites.

The Basic Embed

Every published form has an embed snippet. Copy it from your form’s Share page and paste it into any Astro component:

<div
  data-formflows
  data-form-id="your-form-id"
  data-theme="glass"
></div>
<script src="https://forms.oziforms.com/embed.js" async></script>

That’s it. The script is deferred, so it won’t block your page render. The form hydrates when the browser is idle.

Why this works with Astro:

  • Astro ships zero client-side JavaScript by default
  • The embed script is the only JS loaded on that page
  • At 2KB gzipped, it fits comfortably within any performance budget
  • No framework conflicts. No React or Vue required.

Using It in an Astro Page

For a contact page at src/pages/contact.astro:

---
import Layout from '../layouts/Layout.astro';
---

<Layout title="Contact">
  <h1>Get in touch</h1>
  <div data-formflows data-form-id="abc123" data-theme="glass"></div>
  <script src="https://forms.oziforms.com/embed.js" async></script>
</Layout>

Because Astro ships zero client side JavaScript by default, your page stays fast. The embed script is the only JS loaded, and it’s under 2KB gzipped.

Using It in an Astro Component

For reusable form components, create src/components/ContactForm.astro:

---
export interface Props {
  formId: string;
  theme?: 'glass' | 'minimal' | 'dark';
}

const { formId, theme = 'glass' } = Astro.props;
---

<div data-formflows data-form-id={formId} data-theme={theme}></div>
<script src="https://forms.oziforms.com/embed.js" async></script>

Then use it anywhere:

<ContactForm formId="abc123" theme="minimal" />

Custom Domains for Production

If you’re on a paid plan, host the form on your own domain instead of forms.oziforms.com. This eliminates any third party cookie concerns and keeps everything under your brand.

Set your custom domain in OziForms, add the CNAME record, and update the embed script URL:

<script src="https://forms.yourdomain.com/embed.js" async></script>

Benefits of custom domains:

  • No third-party cookie warnings
  • Full brand consistency
  • Better ad tracking (Meta Pixel works without domain mismatch)
  • Improved trust with privacy-conscious users

Styling Considerations

The embed uses Shadow DOM, so your global styles won’t leak in. This is usually what you want. It prevents conflicts. If you need to override specific styles, use CSS custom properties:

:root {
  --ff-accent: #your-brand-color;
  --ff-radius: 12px;
  --ff-bg: #0a0a0a;
  --ff-text: #ededed;
}

These properties pierce the Shadow DOM boundary and are picked up by the embed runtime.

Available CSS Custom Properties

PropertyDefaultDescription
--ff-accent#06b6d4Primary button and link color
--ff-radius12pxBorder radius for cards and inputs
--ff-bg#ffffffBackground color
--ff-text#171717Primary text color
--ff-muted#737373Secondary text color
--ff-border#e5e5e5Border color
--ff-fontsystem-uiFont family

Dark Mode Support

If your Astro site supports dark mode, the embed adapts automatically when you set the properties:

[data-theme="dark"] {
  --ff-bg: #0a0a0a;
  --ff-text: #ededed;
  --ff-muted: #a3a3a3;
  --ff-border: #262626;
}

Preventing Layout Shift

To prevent Cumulative Layout Shift (CLS), set a minimum height on the container:

<div
  data-formflows
  data-form-id="abc123"
  style="min-height: 400px;"
></div>

For multipage forms, estimate based on your longest page:

  • Short forms (1–3 fields): min-height: 250px
  • Medium forms (4–8 fields): min-height: 400px
  • Long forms (9+ fields): min-height: 600px

Handling Multiple Forms on One Page

You can embed multiple forms on a single Astro page. Each needs its own container:

<section>
  <h2>Newsletter</h2>
  <div data-formflows data-form-id="newsletter123"></div>
</section>

<section>
  <h2>Contact</h2>
  <div data-formflows data-form-id="contact456"></div>
</section>

<!-- One script handles all forms -->
<script src="https://forms.oziforms.com/embed.js" async></script>

The embed script initializes all [data-formflows] elements on the page automatically.

Astro Islands and Partial Hydration

If you are using Astro Islands with a framework like React or Vue, you can still use the embed. Just place it outside the island:

---
import InteractiveWidget from '../components/InteractiveWidget.jsx';
---

<InteractiveWidget client:load />

<!-- Form embed stays vanilla JS -->
<div data-formflows data-form-id="abc123"></div>
<script src="https://forms.oziforms.com/embed.js" async></script>

This keeps your form embed lightweight while allowing interactive components to hydrate separately.

SSR and Static Generation

The embed works with both output: 'static' and output: 'server' in Astro. For static sites (the default), the form container renders at build time and hydrates on the client. For SSR, the same happens at request time.

No special configuration is needed. The embed script detects the container and initializes when the DOM is ready.

Performance Checklist

Before deploying your form to production, verify these items:

  • Use async or defer on the embed script
  • Host on a custom domain if branding matters
  • Set a fallback min-height to prevent layout shift
  • Test with JavaScript disabled. The form has a graceful noscript fallback
  • Verify Core Web Vitals with PageSpeed Insights
  • Test on mobile devices with slow connections
  • Confirm the form submits correctly end-to-end

Troubleshooting

Form not appearing

  • Check that data-form-id matches your published form ID
  • Verify the form is published (not in draft mode)
  • Check browser console for CORS errors (use custom domain if needed)

Styles not applying

  • Ensure CSS custom properties are defined on :root or the parent element
  • Verify the property names match the documented list above
  • Check for CSS specificity conflicts

Slow loading

  • Confirm you are using async on the script tag
  • Check if other scripts are blocking the main thread
  • Consider using a custom domain for faster DNS resolution

Layout shift

  • Add min-height to the container div
  • Use the content-visibility: auto CSS property for offscreen forms

The Bottom Line

Astro + OziForms is the fastest way to add production ready forms to a static site without sacrificing performance budgets. The 2KB embed means you can add forms to every page without worrying about bundle size.

For Astro sites where performance is the selling point, this pairing is hard to beat.