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
| Property | Default | Description |
|---|---|---|
--ff-accent | #06b6d4 | Primary button and link color |
--ff-radius | 12px | Border radius for cards and inputs |
--ff-bg | #ffffff | Background color |
--ff-text | #171717 | Primary text color |
--ff-muted | #737373 | Secondary text color |
--ff-border | #e5e5e5 | Border color |
--ff-font | system-ui | Font 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
asyncordeferon the embed script - Host on a custom domain if branding matters
- Set a fallback
min-heightto 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-idmatches 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
:rootor the parent element - Verify the property names match the documented list above
- Check for CSS specificity conflicts
Slow loading
- Confirm you are using
asyncon 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-heightto the container div - Use the
content-visibility: autoCSS 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.