Sequel and custom form integration
Learn how to integrate Sequel with a custom form and render on submission
This documentation explains how to integrate Sequel with your custom forms, similar to how Marketo and HubSpot integrations work. When a user submits your form, Sequel will automatically register them for the event and render the event interface.
Overview
Custom form integration with Sequel follows this flow:
- User submits your custom form
- Your form handler captures the submission
- Extract user data (name, email)
- Call Sequel registration API
- Sequel renders the event interface
- User can join the event
This approach gives you complete control over the form design and validation while leveraging Sequel's event management capabilities.
Quick Start
1. Basic HTML Setup
<!DOCTYPE html>
<html>
<head>
<title>Event Registration</title>
</head>
<body>
<!-- Your custom form -->
<form id="customRegistrationForm">
<input type="text" id="firstName" name="firstName" placeholder="First Name" required>
<input type="text" id="lastName" name="lastName" placeholder="Last Name" required>
<input type="email" id="email" name="email" placeholder="Email" required>
<button type="submit">Register for Event</button>
</form>
<!-- Sequel will render here after registration -->
<div id="sequel_root"></div>
<!-- Include Sequel script -->
<script type="module" src="https://prod-assets.sequelvideo.com/uploads/toolkit/sequel.js"></script>
<script>
document.getElementById('customRegistrationForm').addEventListener('submit', async function(e) {
e.preventDefault();
// Get form data
const firstName = document.getElementById('firstName').value;
const lastName = document.getElementById('lastName').value;
const email = document.getElementById('email').value;
try {
// Register user with Sequel
const registration = await Sequel.registerUserForEvent({
name: `${firstName} ${lastName}`,
email: email,
eventId: 'your-sequel-event-id'
});
// Hide the form
document.getElementById('customRegistrationForm').style.display = 'none';
// Render Sequel event interface
Sequel.renderEvent({
eventId: 'your-sequel-event-id',
joinCode: registration.joinCode
});
} catch (error) {
console.error('Registration failed:', error);
alert('Registration failed. Please try again.');
}
});
</script>
</body>
</html>
Integration Methods
Method 1: Direct API Integration (Recommended)
This method directly calls the Sequel registration API from your form handler:
// Form submission handler
async function handleFormSubmission(formData) {
try {
// Register user with Sequel
const response = await fetch('https://api.introvoke.com/api/v3/events/your-event-id/registrant', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: `${formData.firstName} ${formData.lastName}`,
email: formData.email,
resendInvite: true,
ignoreCustomQuestions: true
})
});
if (!response.ok) {
throw new Error(`Registration failed: ${response.statusText}`);
}
const registration = await response.json();
// Store join code for future use
Sequel.setJoinCodeCookie('your-event-id', registration.joinCode);
// Render Sequel event interface
Sequel.renderEvent({
eventId: 'your-event-id',
joinCode: registration.joinCode
});
} catch (error) {
console.error('Registration error:', error);
// Handle error appropriately
}
}
Method 2: Using Sequel's Built-in Registration Helper
Use Sequel's built-in registration API wrapper:
// Form submission handler using Sequel helper
async function handleFormSubmission(formData) {
try {
// Use Sequel's registration helper
const registration = await Sequel.registerUserForEvent({
name: `${formData.firstName} ${formData.lastName}`,
email: formData.email,
eventId: 'your-sequel-event-id'
});
// Hide form and show event
hideForm();
Sequel.renderEvent({
eventId: 'your-sequel-event-id',
joinCode: registration.joinCode
});
} catch (error) {
console.error('Registration failed:', error);
showErrorMessage('Registration failed. Please try again.');
}
}
Method 3: PostMessage Integration
For iframe-based forms or cross-origin scenarios:
// In your form's iframe or separate domain
function submitForm(formData) {
// Send registration data to parent window
window.parent.postMessage({
type: 'customFormSubmission',
data: {
firstName: formData.firstName,
lastName: formData.lastName,
email: formData.email,
eventId: 'your-sequel-event-id'
}
}, '*');
}
// In your main page
window.addEventListener('message', async function(event) {
if (event.data.type === 'customFormSubmission') {
const { firstName, lastName, email, eventId } = event.data.data;
try {
const registration = await Sequel.registerUserForEvent({
name: `${firstName} ${lastName}`,
email: email,
eventId: eventId
});
// Render Sequel event
Sequel.renderEvent({
eventId: eventId,
joinCode: registration.joinCode
});
} catch (error) {
console.error('Registration failed:', error);
}
}
});
API Reference
Sequel.registerUserForEvent()
Registers a user for a Sequel event and returns registration details.
const registration = await Sequel.registerUserForEvent({
name: string, // Full name of the user
email: string, // Email address (required)
eventId: string // Sequel event ID
});
// Returns:
// {
// authToken: string,
// joinCode: string,
// email: string
// }
Sequel.renderEvent()
Renders the Sequel event interface after registration.
Sequel.renderEvent({
eventId: string, // Sequel event ID
joinCode: string, // Join code from registration
hybrid?: boolean, // Optional: enable hybrid mode
isPopup?: boolean // Optional: render in popup mode
});
Sequel.setJoinCodeCookie()
Stores the join code in a cookie for future visits.
Sequel.setJoinCodeCookie(eventId, joinCode);
Direct API Endpoint
For server-side integration or custom implementations:
POST https://api.introvoke.com/api/v3/events/{eventId}/registrant
Content-Type: application/json
{
"name": "John Doe",
"email": "[email protected]",
"resendInvite": true,
"ignoreCustomQuestions": true
}
Response:
{
"authToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
"joinCode": "ABC123DEF456",
"email": "[email protected]"
}
Complete Examples
Example 1: React Component Integration
import React, { useState } from 'react';
function EventRegistrationForm({ eventId }) {
const [formData, setFormData] = useState({
firstName: '',
lastName: '',
email: ''
});
const [isRegistered, setIsRegistered] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
const handleSubmit = async (e) => {
e.preventDefault();
setIsLoading(true);
setError(null);
try {
const registration = await window.Sequel.registerUserForEvent({
name: `${formData.firstName} ${formData.lastName}`,
email: formData.email,
eventId: eventId
});
setIsRegistered(true);
// Render Sequel event interface
window.Sequel.renderEvent({
eventId: eventId,
joinCode: registration.joinCode
});
} catch (err) {
setError('Registration failed. Please try again.');
console.error('Registration error:', err);
} finally {
setIsLoading(false);
}
};
if (isRegistered) {
return <div id="sequel_root"></div>;
}
return (
<form onSubmit={handleSubmit}>
<div>
<input
type="text"
placeholder="First Name"
value={formData.firstName}
onChange={(e) => setFormData({...formData, firstName: e.target.value})}
required
/>
</div>
<div>
<input
type="text"
placeholder="Last Name"
value={formData.lastName}
onChange={(e) => setFormData({...formData, lastName: e.target.value})}
required
/>
</div>
<div>
<input
type="email"
placeholder="Email"
value={formData.email}
onChange={(e) => setFormData({...formData, email: e.target.value})}
required
/>
</div>
{error && <div className="error">{error}</div>}
<button type="submit" disabled={isLoading}>
{isLoading ? 'Registering...' : 'Register for Event'}
</button>
</form>
);
}
Example 2: Multi-Step Form with Validation
<!DOCTYPE html>
<html>
<head>
<title>Multi-Step Event Registration</title>
<style>
.form-step { display: none; }
.form-step.active { display: block; }
.error { color: red; margin-top: 5px; }
.success { color: green; }
</style>
</head>
<body>
<div id="registration-container">
<form id="multiStepForm">
<!-- Step 1: Basic Info -->
<div class="form-step active" data-step="1">
<h2>Step 1: Basic Information</h2>
<input type="text" id="firstName" placeholder="First Name" required>
<input type="text" id="lastName" placeholder="Last Name" required>
<button type="button" onclick="nextStep()">Next</button>
</div>
<!-- Step 2: Contact Info -->
<div class="form-step" data-step="2">
<h2>Step 2: Contact Information</h2>
<input type="email" id="email" placeholder="Email Address" required>
<input type="tel" id="phone" placeholder="Phone Number">
<button type="button" onclick="prevStep()">Previous</button>
<button type="button" onclick="nextStep()">Next</button>
</div>
<!-- Step 3: Company Info -->
<div class="form-step" data-step="3">
<h2>Step 3: Company Information</h2>
<input type="text" id="company" placeholder="Company Name">
<input type="text" id="jobTitle" placeholder="Job Title">
<button type="button" onclick="prevStep()">Previous</button>
<button type="submit">Register for Event</button>
</div>
</form>
</div>
<div id="sequel_root"></div>
<script type="module" src="https://prod-assets.sequelvideo.com/uploads/toolkit/sequel.js"></script>
<script>
const SEQUEL_EVENT_ID = 'your-sequel-event-id';
let currentStep = 1;
function showStep(step) {
document.querySelectorAll('.form-step').forEach(el => {
el.classList.remove('active');
});
document.querySelector(`[data-step="${step}"]`).classList.add('active');
currentStep = step;
}
function nextStep() {
if (validateCurrentStep()) {
showStep(currentStep + 1);
}
}
function prevStep() {
showStep(currentStep - 1);
}
function validateCurrentStep() {
const currentStepEl = document.querySelector(`[data-step="${currentStep}"]`);
const inputs = currentStepEl.querySelectorAll('input[required]');
for (let input of inputs) {
if (!input.value.trim()) {
showError(input, 'This field is required');
return false;
}
if (input.type === 'email' && !isValidEmail(input.value)) {
showError(input, 'Please enter a valid email address');
return false;
}
}
clearErrors();
return true;
}
function isValidEmail(email) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
function showError(input, message) {
clearErrors();
const error = document.createElement('div');
error.className = 'error';
error.textContent = message;
input.parentNode.appendChild(error);
input.focus();
}
function clearErrors() {
document.querySelectorAll('.error').forEach(el => el.remove());
}
document.getElementById('multiStepForm').addEventListener('submit', async function(e) {
e.preventDefault();
if (!validateCurrentStep()) return;
const formData = {
firstName: document.getElementById('firstName').value,
lastName: document.getElementById('lastName').value,
email: document.getElementById('email').value,
phone: document.getElementById('phone').value,
company: document.getElementById('company').value,
jobTitle: document.getElementById('jobTitle').value
};
try {
// Show loading state
const submitBtn = e.target.querySelector('button[type="submit"]');
submitBtn.textContent = 'Registering...';
submitBtn.disabled = true;
// Register with Sequel
const registration = await Sequel.registerUserForEvent({
name: `${formData.firstName} ${formData.lastName}`,
email: formData.email,
eventId: SEQUEL_EVENT_ID
});
// Optional: Send additional data to your backend
await fetch('/api/save-registration', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
...formData,
sequelJoinCode: registration.joinCode
})
});
// Hide form and show Sequel event
document.getElementById('registration-container').style.display = 'none';
Sequel.renderEvent({
eventId: SEQUEL_EVENT_ID,
joinCode: registration.joinCode
});
} catch (error) {
console.error('Registration failed:', error);
showError(document.getElementById('email'), 'Registration failed. Please try again.');
// Reset submit button
const submitBtn = e.target.querySelector('button[type="submit"]');
submitBtn.textContent = 'Register for Event';
submitBtn.disabled = false;
}
});
</script>
</body>
</html>
Example 3: Server-Side Integration (Node.js)
// server.js - Express.js example
const express = require('express');
const axios = require('axios');
const app = express();
app.use(express.json());
app.use(express.static('public'));
// Registration endpoint
app.post('/api/register-for-event', async (req, res) => {
try {
const { firstName, lastName, email, eventId } = req.body;
// Validate input
if (!firstName || !lastName || !email || !eventId) {
return res.status(400).json({ error: 'Missing required fields' });
}
// Register with Sequel API
const sequelResponse = await axios.post(
`https://api.introvoke.com/api/v3/events/${eventId}/registrant`,
{
name: `${firstName} ${lastName}`,
email: email,
resendInvite: true,
ignoreCustomQuestions: true
},
{
headers: {
'Content-Type': 'application/json'
}
}
);
const registration = sequelResponse.data;
// Optional: Save to your database
await saveRegistrationToDatabase({
firstName,
lastName,
email,
eventId,
sequelJoinCode: registration.joinCode,
registeredAt: new Date()
});
// Return registration details
res.json({
success: true,
joinCode: registration.joinCode,
authToken: registration.authToken
});
} catch (error) {
console.error('Registration error:', error);
if (error.response) {
// Sequel API error
res.status(error.response.status).json({
error: 'Registration failed',
details: error.response.data
});
} else {
// Server error
res.status(500).json({
error: 'Internal server error'
});
}
}
});
async function saveRegistrationToDatabase(data) {
// Your database logic here
console.log('Saving registration:', data);
}
app.listen(3000, () => {
console.log('Server running on port 3000');
});
<!-- public/index.html -->
<!DOCTYPE html>
<html>
<head>
<title>Server-Side Registration</title>
</head>
<body>
<form id="registrationForm">
<input type="text" id="firstName" placeholder="First Name" required>
<input type="text" id="lastName" placeholder="Last Name" required>
<input type="email" id="email" placeholder="Email" required>
<button type="submit">Register</button>
</form>
<div id="sequel_root"></div>
<script type="module" src="https://prod-assets.sequelvideo.com/uploads/toolkit/sequel.js"></script>
<script>
const EVENT_ID = 'your-sequel-event-id';
document.getElementById('registrationForm').addEventListener('submit', async function(e) {
e.preventDefault();
const formData = {
firstName: document.getElementById('firstName').value,
lastName: document.getElementById('lastName').value,
email: document.getElementById('email').value,
eventId: EVENT_ID
};
try {
// Call your server endpoint
const response = await fetch('/api/register-for-event', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(formData)
});
if (!response.ok) {
throw new Error('Registration failed');
}
const result = await response.json();
// Hide form
document.getElementById('registrationForm').style.display = 'none';
// Render Sequel event
Sequel.renderEvent({
eventId: EVENT_ID,
joinCode: result.joinCode
});
} catch (error) {
console.error('Registration error:', error);
alert('Registration failed. Please try again.');
}
});
</script>
</body>
</html>
Event Handling
Listening for Registration Events
You can listen for registration success/failure events:
// Listen for successful registration
window.addEventListener('sequel:registration:success', function(event) {
const { eventId, joinCode, email } = event.detail;
console.log('User registered successfully:', { eventId, joinCode, email });
// Optional: Track in analytics
gtag('event', 'registration', {
event_category: 'sequel',
event_label: eventId
});
});
// Listen for registration errors
window.addEventListener('sequel:registration:error', function(event) {
const { error, eventId } = event.detail;
console.error('Registration failed:', error);
// Optional: Show user-friendly error message
showErrorNotification('Registration failed. Please try again.');
});
Custom Event Dispatching
If you want to dispatch custom events from your form:
function dispatchRegistrationEvent(type, data) {
const event = new CustomEvent(`sequel:registration:${type}`, {
detail: data,
bubbles: true
});
window.dispatchEvent(event);
}
// Usage in your form handler
try {
const registration = await Sequel.registerUserForEvent(userData);
dispatchRegistrationEvent('success', {
eventId: userData.eventId,
joinCode: registration.joinCode,
email: userData.email
});
} catch (error) {
dispatchRegistrationEvent('error', {
error: error.message,
eventId: userData.eventId
});
}
Best Practices
1. Form Validation
Always validate form data before submitting:
function validateRegistrationForm(formData) {
const errors = [];
if (!formData.firstName?.trim()) {
errors.push('First name is required');
}
if (!formData.lastName?.trim()) {
errors.push('Last name is required');
}
if (!formData.email?.trim()) {
errors.push('Email is required');
} else if (!isValidEmail(formData.email)) {
errors.push('Please enter a valid email address');
}
return errors;
}
function isValidEmail(email) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
2. Error Handling
Implement comprehensive error handling:
async function registerUser(formData) {
try {
const registration = await Sequel.registerUserForEvent(formData);
return { success: true, data: registration };
} catch (error) {
console.error('Registration error:', error);
// Handle specific error types
if (error.message.includes('already registered')) {
return {
success: false,
error: 'You are already registered for this event.'
};
} else if (error.message.includes('event not found')) {
return {
success: false,
error: 'Event not found. Please check the event ID.'
};
} else {
return {
success: false,
error: 'Registration failed. Please try again.'
};
}
}
}
3. Loading States
Provide visual feedback during registration:
function setLoadingState(isLoading) {
const submitBtn = document.querySelector('button[type="submit"]');
const form = document.getElementById('registrationForm');
if (isLoading) {
submitBtn.textContent = 'Registering...';
submitBtn.disabled = true;
form.style.opacity = '0.6';
} else {
submitBtn.textContent = 'Register for Event';
submitBtn.disabled = false;
form.style.opacity = '1';
}
}
4. Progressive Enhancement
Ensure your form works without JavaScript:
<form action="/fallback-registration" method="POST" id="registrationForm">
<input type="text" name="firstName" required>
<input type="text" name="lastName" required>
<input type="email" name="email" required>
<input type="hidden" name="eventId" value="your-event-id">
<button type="submit">Register for Event</button>
</form>
<script>
// Enhance with JavaScript if available
if (window.Sequel) {
document.getElementById('registrationForm').addEventListener('submit', handleJSSubmission);
}
</script>
5. Cookie Management
Properly handle join codes for returning users:
async function initializeEventPage(eventId) {
// Check if user already has a join code
const existingJoinCode = Sequel.getJoinCodeFromCookie(eventId);
if (existingJoinCode) {
// User is already registered, show event directly
document.getElementById('registrationForm').style.display = 'none';
Sequel.renderEvent({
eventId: eventId,
joinCode: existingJoinCode
});
} else {
// Show registration form
document.getElementById('registrationForm').style.display = 'block';
}
}
Troubleshooting
Common Issues
1. "Event not found" Error
// Check your event ID
const eventId = 'your-sequel-event-id'; // Must be valid Sequel event ID
// Verify event exists
const event = await Sequel.getEvent(eventId);
if (!event) {
console.error('Event not found:', eventId);
}
2. CORS Issues
If you're calling the API directly from the browser:
// Use Sequel's built-in methods instead of direct fetch
// ❌ This might cause CORS issues:
fetch('https://api.introvoke.com/api/v3/events/...')
// ✅ Use this instead:
Sequel.registerUserForEvent({...})
3. "Element not found" Error
// Ensure sequel_root exists before rendering
const sequelRoot = document.getElementById('sequel_root');
if (!sequelRoot) {
console.error('sequel_root element not found');
return;
}
4. Registration API Failures
// Add retry logic for network issues
async function registerWithRetry(userData, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await Sequel.registerUserForEvent(userData);
} catch (error) {
if (i === maxRetries - 1) throw error;
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
}
Debug Mode
Enable debug logging:
// Enable Sequel debug mode
window.SEQUEL_DEBUG = true;
// Your registration code here...
Network Debugging
Check network requests in browser dev tools:
- Open Developer Tools (F12)
- Go to Network tab
- Submit your form
- Look for requests to
api.introvoke.com
- Check response status and error messages
Support
For additional help with custom form integration:
- Email: [email protected]
- Documentation: https://docs.sequel.io
- Status Page: https://status.sequel.io
Updated about 19 hours ago