Form Embedding
Embed forms on your website using JavaScript widgets, iframes, or standalone pages.
Overview
ArcanFlows forms can be embedded in your website or application using multiple methods. Choose the approach that best fits your technical requirements and use case.
Embedding Methods
| Method | Use Case | Customization | Setup |
|---|---|---|---|
| JavaScript Widget | Most flexible, full styling control | High | Medium |
| Iframe | Simple, isolated styling | Medium | Easy |
| Standalone Page | Quick sharing, no code | Low | None |
| React Component | React applications | High | Medium |
JavaScript Widget
Basic Installation
Add the script to your HTML:
html<script src="https://cdn.arcanflows.com/forms.js"></script>
Render Form
html<div id="my-form"></div> <script> ArcanFlows.form({ formId: 'form_abc123', container: '#my-form' }); </script>
With Options
html<script> ArcanFlows.form({ formId: 'form_abc123', container: '#my-form', theme: 'light', prefill: { email: 'user@example.com', name: 'John Doe' }, onSubmit: function(data) { console.log('Form submitted:', data); }, onError: function(error) { console.error('Form error:', error); } }); </script>
Full Configuration
javascriptArcanFlows.form({ // Required formId: 'form_abc123', container: '#my-form', // Theme theme: 'light', // 'light', 'dark', 'auto', 'custom' customTheme: { primaryColor: '#6366F1', backgroundColor: '#FFFFFF', textColor: '#1F2937', borderRadius: '8px', fontFamily: 'Inter, sans-serif' }, // Behavior showBranding: false, submitButtonText: 'Send Message', successMessage: 'Thank you for your submission!', redirectUrl: '/thank-you', resetOnSubmit: true, // Prefill prefill: { field1: 'value1', field2: 'value2' }, // Hidden fields hiddenFields: { source: 'website', campaign: 'summer2025', referrer: document.referrer }, // Validation validateOnBlur: true, validateOnChange: false, showInlineErrors: true, // Callbacks onLoad: function() { console.log('Form loaded'); }, onSubmit: function(data) { console.log('Submitted:', data); // Return false to prevent default success behavior }, onSuccess: function(response) { console.log('Success:', response); }, onError: function(error) { console.error('Error:', error); }, onFieldChange: function(field, value) { console.log('Field changed:', field, value); }, onPageChange: function(from, to) { console.log('Page changed:', from, '->', to); } });
Multiple Forms
html<div id="contact-form"></div> <div id="newsletter-form"></div> <script> // Contact form const contactForm = ArcanFlows.form({ formId: 'form_contact', container: '#contact-form' }); // Newsletter form const newsletterForm = ArcanFlows.form({ formId: 'form_newsletter', container: '#newsletter-form' }); </script>
Programmatic Control
javascriptconst form = ArcanFlows.form({ formId: 'form_abc123', container: '#my-form' }); // Methods form.reset(); // Reset form form.submit(); // Programmatic submit form.validate(); // Validate all fields form.setValue('email', 'new@example.com'); form.getValue('email'); // Get field value form.getValues(); // Get all values form.setPage(2); // Go to page (multi-step) form.disable(); // Disable form form.enable(); // Enable form form.destroy(); // Remove form // Events form.on('submit', function(data) { }); form.on('error', function(error) { }); form.on('field:change', function(field, value) { }); form.off('submit'); // Remove listener
Iframe Embed
Basic Iframe
html<iframe src="https://forms.arcanflows.com/f/form_abc123" width="100%" height="600" frameborder="0" ></iframe>
With Parameters
html<iframe src="https://forms.arcanflows.com/f/form_abc123?theme=dark&prefill_email=user@example.com" width="100%" height="600" frameborder="0" allow="clipboard-write" ></iframe>
URL Parameters
| Parameter | Description | Example |
|---|---|---|
theme | Color theme | ?theme=dark |
prefill_* | Prefill fields | ?prefill_email=x@y.com |
hide_* | Hide fields | ?hide_company=true |
branding | Show branding | ?branding=false |
redirect | Success redirect | ?redirect=/thanks |
embed | Embed mode | ?embed=true |
Responsive Iframe
html<style> .form-container { position: relative; width: 100%; padding-bottom: 75%; /* Aspect ratio */ height: 0; overflow: hidden; } .form-container iframe { position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none; } </style> <div class="form-container"> <iframe src="https://forms.arcanflows.com/f/form_abc123?embed=true"></iframe> </div>
Auto-Resize Iframe
html<iframe id="arcanflows-form" src="https://forms.arcanflows.com/f/form_abc123?embed=true" width="100%" height="400" frameborder="0" ></iframe> <script> window.addEventListener('message', function(e) { if (e.data.type === 'arcanflows:resize') { document.getElementById('arcanflows-form').height = e.data.height; } }); </script>
Cross-Origin Communication
javascriptwindow.addEventListener('message', function(e) { // Verify origin if (e.origin !== 'https://forms.arcanflows.com') return; switch (e.data.type) { case 'arcanflows:loaded': console.log('Form loaded'); break; case 'arcanflows:submit': console.log('Form submitted:', e.data.submission); break; case 'arcanflows:resize': // Handle resize break; case 'arcanflows:error': console.error('Form error:', e.data.error); break; } });
Standalone Page
Direct Link
Share your form with a direct link:
https://forms.arcanflows.com/f/form_abc123
Custom Domain
Configure your own domain:
https://forms.yourcompany.com/contact
QR Code
Generate a QR code for your form URL to use in print materials, signage, or events.
Link Parameters
https://forms.arcanflows.com/f/form_abc123?
theme=dark&
prefill_name=John&
prefill_email=john@example.com&
utm_source=campaign
React Component
Installation
bashnpm install @arcanflows/react-forms
Basic Usage
jsximport { Form } from '@arcanflows/react-forms'; function ContactPage() { return ( <Form formId="form_abc123" onSubmit={(data) => console.log(data)} /> ); }
With Props
jsximport { Form } from '@arcanflows/react-forms'; function ContactPage() { const handleSubmit = async (data) => { // Custom submit handling await myApi.createContact(data); }; return ( <Form formId="form_abc123" theme="dark" prefill={{ email: user?.email, name: user?.name }} hiddenFields={{ userId: user?.id }} onSubmit={handleSubmit} onError={(error) => toast.error(error.message)} className="my-form" showBranding={false} /> ); }
Controlled Mode
jsximport { Form, useForm } from '@arcanflows/react-forms'; function ContactPage() { const form = useForm('form_abc123'); return ( <div> <Form form={form} /> <button onClick={() => form.reset()}>Reset</button> <button onClick={() => form.submit()}>Submit</button> </div> ); }
TypeScript
typescriptimport { Form, FormSubmission } from '@arcanflows/react-forms'; interface ContactFormData { name: string; email: string; message: string; } function ContactPage() { const handleSubmit = (data: FormSubmission<ContactFormData>) => { console.log(data.values.email); }; return ( <Form<ContactFormData> formId="form_abc123" onSubmit={handleSubmit} /> ); }
Popup/Modal Forms
JavaScript Popup
javascriptArcanFlows.popup({ formId: 'form_abc123', trigger: 'button#contact-btn', size: 'medium', // 'small', 'medium', 'large', 'fullscreen' animation: 'fade', // 'fade', 'slide', 'scale' closeOnOverlayClick: true, closeOnEscape: true });
Trigger Types
javascript// Button click ArcanFlows.popup({ formId: 'form_abc123', trigger: { type: 'click', selector: '.open-form' } }); // Time delay ArcanFlows.popup({ formId: 'form_abc123', trigger: { type: 'delay', delay: 5000 // 5 seconds } }); // Scroll percentage ArcanFlows.popup({ formId: 'form_abc123', trigger: { type: 'scroll', percentage: 50 } }); // Exit intent ArcanFlows.popup({ formId: 'form_abc123', trigger: { type: 'exit' } }); // Programmatic const popup = ArcanFlows.popup({ formId: 'form_abc123', trigger: { type: 'manual' } }); popup.open(); popup.close();
Modal Styling
javascriptArcanFlows.popup({ formId: 'form_abc123', style: { overlay: { backgroundColor: 'rgba(0, 0, 0, 0.7)' }, modal: { maxWidth: '600px', borderRadius: '16px', padding: '32px' } } });
Slider/Slide-in Forms
javascriptArcanFlows.slider({ formId: 'form_abc123', position: 'right', // 'left', 'right', 'bottom' width: '400px', trigger: 'button#help-btn' });
Inline Embed Options
Replace Element
html<div data-arcanflows-form="form_abc123" data-theme="light" data-prefill-email="user@example.com" ></div> <script src="https://cdn.arcanflows.com/forms.js" async></script>
Auto-Discovery
javascript// Initialize all forms on page ArcanFlows.initAll();
Styling Embedded Forms
CSS Override
css/* Target embedded form */ .arcanflows-form { --af-primary: #6366F1; --af-background: #F9FAFB; --af-text: #1F2937; --af-border: #E5E7EB; --af-error: #EF4444; --af-success: #10B981; --af-radius: 8px; --af-font: 'Inter', sans-serif; } /* Specific elements */ .arcanflows-form .af-input { border-width: 2px; } .arcanflows-form .af-button-submit { text-transform: uppercase; font-weight: 600; }
Shadow DOM Styling
javascriptArcanFlows.form({ formId: 'form_abc123', container: '#my-form', useShadowDom: false, // Disable for full CSS access injectStyles: true });
Security
Content Security Policy
Add ArcanFlows to your CSP:
Content-Security-Policy:
script-src 'self' https://cdn.arcanflows.com;
frame-src 'self' https://forms.arcanflows.com;
connect-src 'self' https://api.arcanflows.com;
Domain Restrictions
Configure allowed embedding domains in your form settings to prevent unauthorized embedding.
Performance
Lazy Loading
javascript// Load form when visible ArcanFlows.form({ formId: 'form_abc123', container: '#my-form', lazyLoad: true, lazyLoadThreshold: 200 // pixels before viewport });
Async Loading
html<script src="https://cdn.arcanflows.com/forms.js" async defer></script> <script> window.ArcanFlowsReady = window.ArcanFlowsReady || []; window.ArcanFlowsReady.push(function() { ArcanFlows.form({ formId: 'form_abc123', container: '#my-form' }); }); </script>
Analytics & Tracking
Built-in Analytics
javascriptArcanFlows.form({ formId: 'form_abc123', container: '#my-form', analytics: { enabled: true, trackViews: true, trackInteractions: true, trackSubmissions: true, trackAbandonment: true } });
Custom Tracking
javascriptArcanFlows.form({ formId: 'form_abc123', container: '#my-form', onLoad: function() { gtag('event', 'form_view', { form_id: 'contact' }); }, onSubmit: function(data) { gtag('event', 'form_submit', { form_id: 'contact' }); }, onError: function(error) { gtag('event', 'form_error', { form_id: 'contact', error: error.message }); } });
Troubleshooting
Common Issues
Form not loading:
- Check formId is correct
- Verify script is loaded
- Check browser console for errors
- Ensure container element exists
Styling issues:
- Check CSS specificity
- Disable Shadow DOM if needed
- Use CSS custom properties
Submission errors:
- Check network requests
- Verify API connectivity
- Check form configuration
Debug Mode
javascriptArcanFlows.form({ formId: 'form_abc123', container: '#my-form', debug: true // Enables console logging });
Best Practices
- Use async loading - Don't block page render
- Lazy load below fold - Improve initial load
- Match site styling - Consistent UX
- Test responsively - Works on all devices
- Handle errors - Graceful fallbacks
- Track analytics - Monitor performance
- Secure embedding - Restrict domains
- Prefill when possible - Reduce friction