Integrating Squarespace Forms with SendSquared: A Technical Overview
This guide explains how to integrate your Squarespace forms with the SendSquared API using Squarespace's Code Injection feature. When a form is submitted on your Squarespace site, the integration will send the visitor's information to SendSquared, allowing you to build your contact list automatically.
IMPORTANT: Before implementing this integration, ensure you have a Squarespace Business plan or higher, as Code Injection is not available on Personal plans.
Prerequisites
- A Squarespace site on a Business plan or higher
- A form on your Squarespace site
- Your SendSquared list group UUID (token)
- Basic knowledge of HTML and JavaScript
Implementation Steps
1. Locate Your Form IDs
First, you need to identify your form and its field names:
- View your Squarespace page with the form
- Right-click on the form and select "Inspect" or "Inspect Element" to open your browser's developer tools
- Identify the form element (usually with a class like
sqs-block-form
) - Note the field names in the form (look for
name
attributes in the input elements)
2. Access Code Injection
To add custom code to your Squarespace site:
- Log in to your Squarespace account
- Go to Settings > Advanced > Code Injection
- You can add code to the:
- Header (site-wide)
- Footer (site-wide)
- Page-specific areas (available in the Page Settings for individual pages)
3. Add the Integration Code
Copy and paste the following code into the Footer Code Injection area. Make sure to customize it with your SendSquared token.
<script>
document.addEventListener('DOMContentLoaded', function() {
// Find all forms on the page
const forms = document.querySelectorAll('.sqs-block-form form');
forms.forEach(form => {
// Add a listener for the form submission
form.addEventListener('submit', function(e) {
// Don't prevent default submission as Squarespace needs to process the form
// Get the form data
const formData = new FormData(form);
// Get email and name fields - update these to match your field names
const email = formData.get('email');
const name = formData.get('name');
// Only proceed if we have an email
if (!email) return;
// Set the API URL with your SendSquared token
const token = "your-list-group-uuid";
const apiUrl = `https://app-api.sendsquared.com/v1/pub/popup?token=${token}`;
// Set up the API data
const apiData = {
email: email,
name: name || '' // Handle case where name might be empty
};
// Send the data to the SendSquared API
fetch(apiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(apiData)
})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error ${response.status}`);
}
return response.json();
})
.then(data => {
console.log('Successfully sent to SendSquared:', data);
})
.catch(error => {
console.error('Error sending to SendSquared:', error);
});
});
});
});
</script>
4. Customize for Your Form Fields
The default code assumes your form has fields named "email" and "name". If your form uses different field names, update the code accordingly:
// If your form uses different field names, update these lines
const email = formData.get('your-email-field-name');
const name = formData.get('your-name-field-name');
5. Save Your Changes
Click Save to apply your changes. The integration will now be active on your site.
Additional Customization
Targeting Specific Forms
If you only want to target specific forms on your site, you can modify the selector:
// Target only a specific form with an ID
const forms = document.querySelectorAll('#my-newsletter-form');
// OR target forms on a specific page section
const forms = document.querySelectorAll('.newsletter-section .sqs-block-form form');
Adding Success and Error Messages
To provide feedback to users after submission:
// Add to your JavaScript
.then(data => {
console.log('Successfully sent to SendSquared:', data);
// Create and display success message
const successMsg = document.createElement('div');
successMsg.className = 'send-squared-success';
successMsg.textContent = 'Thanks for subscribing!';
successMsg.style.color = 'green';
successMsg.style.marginTop = '10px';
// Insert after the form
form.parentNode.insertBefore(successMsg, form.nextSibling);
})
.catch(error => {
console.error('Error sending to SendSquared:', error);
// Create and display error message
const errorMsg = document.createElement('div');
errorMsg.className = 'send-squared-error';
errorMsg.textContent = 'There was an error processing your subscription.';
errorMsg.style.color = 'red';
errorMsg.style.marginTop = '10px';
// Insert after the form
form.parentNode.insertBefore(errorMsg, form.nextSibling);
});
Adding More Form Fields
You can modify the code to include additional fields from your Squarespace form:
// Example of adding additional fields
const apiData = {
email: formData.get('email'),
name: formData.get('name') || '',
phone: formData.get('phone') || '',
company: formData.get('company') || '',
custom_field: formData.get('custom-field') || ''
};
Make sure that any additional fields you add are supported by the SendSquared API.
Advanced Implementation: Using AJAX Interceptor
For a more robust solution that works even if Squarespace changes their form handling, you can use an AJAX interceptor:
<script>
// Store the original XMLHttpRequest send method
const originalSend = XMLHttpRequest.prototype.send;
// Override the send method
XMLHttpRequest.prototype.send = function(data) {
// Add an event listener for when the request completes
this.addEventListener('load', function() {
// Check if this is a form submission (by checking the URL)
if (this.responseURL && this.responseURL.includes('/api/form-submitter')) {
try {
// Parse the form data that was submitted
const formData = JSON.parse(data);
// Extract email and name from the form data
const email = formData.form.find(field => field.name === 'email')?.value;
const name = formData.form.find(field => field.name === 'name')?.value;
if (email) {
// Set the API URL with your SendSquared token
const token = "your-list-group-uuid";
const apiUrl = `https://app-api.sendsquared.com/v1/pub/popup?token=${token}`;
// Send the data to SendSquared
fetch(apiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: email,
name: name || ''
})
})
.then(response => response.json())
.then(data => console.log('SendSquared success:', data))
.catch(error => console.error('SendSquared error:', error));
}
} catch (e) {
console.error('Error processing form data:', e);
}
}
});
// Call the original send method
return originalSend.apply(this, arguments);
};
</script>
Advanced Integration: Using Lead With Contact API
For more robust lead capture and management, you can integrate your Squarespace forms with SendSquared's Lead With Contact API. This allows you to create both a contact record and a lead record in a single API call, which is ideal for businesses that want to track potential customers through the sales process.
Prerequisites for Lead Integration
- Your SendSquared API key (different from the list group UUID)
- Your SendSquared lead type ID
- Your SendSquared lead status ID
- Your SendSquared user ID (for lead assignment)
- Your SendSquared source ID (optional)
Implementation Steps for Lead Integration
Add the following code to your Squarespace site's Code Injection area (Footer section):
<script>
document.addEventListener('DOMContentLoaded', function() {
// Find all lead forms on the page (you may want to use a specific class or ID)
const leadForms = document.querySelectorAll('.lead-capture-form form');
leadForms.forEach(form => {
// Add a listener for the form submission
form.addEventListener('submit', function(e) {
// Don't prevent default submission as Squarespace needs to process the form
// Get the form data
const formData = new FormData(form);
// Get values from form fields - update field names to match your form
const email = formData.get('email');
const firstName = formData.get('firstName');
const lastName = formData.get('lastName');
const phone = formData.get('phone'); // Must be in E.164 format (+1XXXXXXXXXX)
const interest = formData.get('interest');
const notes = formData.get('message');
// Only proceed if we have an email
if (!email) return;
// Format current date in ISO format
const now = new Date().toISOString();
// Contact data structure
const contactData = {
'email': email,
'first_name': firstName,
'last_name': lastName,
'mobile_phone': phone // must be in E.164 format (+1XXXXXXXXXX)
};
// Lead data structure
const leadData = {
// Update these IDs with your actual SendSquared IDs
'lead_type_id': 116, // Update with your lead type ID
'lead_status_id': 504, // Update with your lead status ID
'subject': `Interested in ${interest}`,
'interest_start_at': now,
'interest_end_at': now,
'quantity_1': 1, // Number of adults - customize as needed
'quantity_2': 0, // Number of children - customize as needed
'notes': [notes],
'user_id': 1446, // Update with your agent user ID
'source_id': 0, // Update with your source ID if needed
};
// Prepare request data
const requestData = {
'contact': contactData,
'lead': leadData
};
// Send data to the SendSquared API
fetch('https://api.sendsquared.com/v1/leads/lead-with-contact', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
// Update with your actual API key
'x-api-key': 'your-api-key-here'
},
body: JSON.stringify(requestData)
})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error ${response.status}`);
}
return response.json();
})
.then(data => {
console.log('Successfully sent lead to SendSquared:', data);
// Optionally display success message
const successMsg = document.createElement('div');
successMsg.className = 'send-squared-success';
successMsg.textContent = 'Your information has been submitted successfully!';
successMsg.style.color = 'green';
successMsg.style.marginTop = '10px';
// Insert after the form
form.parentNode.insertBefore(successMsg, form.nextSibling);
})
.catch(error => {
console.error('Error sending lead to SendSquared:', error);
// Optionally display error message
const errorMsg = document.createElement('div');
errorMsg.className = 'send-squared-error';
errorMsg.textContent = 'There was an error processing your submission.';
errorMsg.style.color = 'red';
errorMsg.style.marginTop = '10px';
// Insert after the form
form.parentNode.insertBefore(errorMsg, form.nextSibling);
});
});
});
});
</script>
Customizing the Lead Data
You can adapt the lead data structure to match your specific business needs:
// Example of a more detailed lead structure
const leadData = {
'lead_type_id': 116,
'lead_status_id': 504,
'subject': `${firstName} ${lastName} - ${interest} Inquiry`,
'interest_start_at': now,
'interest_end_at': addDays(now, 30), // Set end date 30 days in future
'quantity_1': parseInt(formData.get('adults')) || 1,
'quantity_2': parseInt(formData.get('children')) || 0,
'notes': [
`Interest: ${interest}`,
`Budget: ${formData.get('budget') || 'Not specified'}`,
`Preferred contact method: ${formData.get('contactMethod') || 'Not specified'}`,
`Additional notes: ${notes}`
],
'user_id': 1446,
'source_id': 0
};
// Helper function to add days to date
function addDays(dateString, days) {
let date = new Date(dateString);
date.setDate(date.getDate() + days);
return date.toISOString();
}
Using AJAX Interceptor for Lead Capture
For a more robust lead capture that works regardless of form structure changes, you can use an AJAX interceptor:
<script>
// Store the original XMLHttpRequest send method
const originalSend = XMLHttpRequest.prototype.send;
// Override the send method
XMLHttpRequest.prototype.send = function(data) {
// Add an event listener for when the request completes
this.addEventListener('load', function() {
// Check if this is a form submission (by checking the URL)
if (this.responseURL && this.responseURL.includes('/api/form-submitter')) {
try {
// Parse the form data that was submitted
const formData = JSON.parse(data);
// Only proceed for lead forms (you can add a check based on form name or ID)
if (formData.formId === 'your-lead-form-id') {
// Extract contact and lead info from the form data
const fields = formData.form;
const email = fields.find(field => field.name === 'email')?.value;
const firstName = fields.find(field => field.name === 'firstName')?.value;
const lastName = fields.find(field => field.name === 'lastName')?.value;
const phone = fields.find(field => field.name === 'phone')?.value;
const interest = fields.find(field => field.name === 'interest')?.value;
const notes = fields.find(field => field.name === 'message')?.value;
if (email) {
// Current date in ISO format
const now = new Date().toISOString();
// Create lead with contact in SendSquared
fetch('https://api.sendsquared.com/v1/leads/lead-with-contact', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': 'your-api-key-here'
},
body: JSON.stringify({
contact: {
'email': email,
'first_name': firstName || '',
'last_name': lastName || '',
'mobile_phone': phone || ''
},
lead: {
'lead_type_id': 116,
'lead_status_id': 504,
'subject': `Interested in ${interest || 'your services'}`,
'interest_start_at': now,
'interest_end_at': now,
'quantity_1': 1,
'quantity_2': 0,
'notes': [notes || ''],
'user_id': 1446,
'source_id': 0
}
})
})
.then(response => response.json())
.then(data => console.log('SendSquared lead success:', data))
.catch(error => console.error('SendSquared lead error:', error));
}
}
} catch (e) {
console.error('Error processing form data:', e);
}
}
});
// Call the original send method
return originalSend.apply(this, arguments);
};
</script>
Troubleshooting
If your integration isn't working properly, check these common issues:
- Verify that your Squarespace form field names match exactly what you've specified in the code
- Confirm that your SendSquared token or API key is correct
- Check your browser console for any JavaScript errors (use F12 to open Developer Tools)
- Ensure that you've added the code to the correct Code Injection area
- Make sure you're on a Business plan or higher to use Code Injection
- For the Lead API, ensure phone numbers are properly formatted in E.164 format (+1XXXXXXXXXX)
- Check that the Lead Type ID, Lead Status ID, and User ID are valid in your SendSquared account
Common Errors
CORS Issues
If you see errors about CORS (Cross-Origin Resource Sharing) in your console, it means the SendSquared API is blocking requests from your domain. Contact SendSquared support to whitelist your domain.
Form Not Found
If your code isn't capturing form submissions, check that the selector is correct:
console.log('Forms found:', document.querySelectorAll('.sqs-block-form form').length);
Debugging Form Data
To debug what data is being captured:
form.addEventListener('submit', function(e) {
const formData = new FormData(form);
console.log('Form submitted with these values:');
for (let pair of formData.entries()) {
console.log(pair[0] + ': ' + pair[1]);
}
// Rest of your code...
});
For additional support, contact SendSquared support at support@sendsquared.com or +1.855.340.7363.
Frequently Asked Questions
How do I test the Squarespace integration without affecting live data?
To test safely:
- Create a test list in SendSquared for development purposes
- Use the test list's UUID/token during development
- Submit test data with obvious test names (e.g., "Test User Test")
- Use browser developer tools to monitor network requests and console logs
- Test on a staging domain or password-protected page first
- Switch to production credentials only after thorough testing
What happens if the SendSquared API is temporarily down?
The Squarespace integration includes error handling that will:
- Log errors to the browser console without breaking the form submission
- Allow the form to still submit normally to Squarespace
- Display appropriate error messages to users if configured
- Not prevent the user from completing their form submission
- You can implement retry logic or queue failed submissions if needed
Can I integrate multiple Squarespace forms with different SendSquared lists?
Yes! You can modify the integration code to handle multiple forms:
document.addEventListener('DOMContentLoaded', function() {
// Newsletter form
const newsletterForm = document.querySelector('#newsletter-form');
if (newsletterForm) {
newsletterForm.addEventListener('submit', function(e) {
handleFormSubmission(this, 'newsletter-list-uuid', 'newsletter');
});
}
// Contact form
const contactForm = document.querySelector('#contact-form');
if (contactForm) {
contactForm.addEventListener('submit', function(e) {
handleFormSubmission(this, 'contact-list-uuid', 'contact');
});
}
});
function handleFormSubmission(form, token, formType) {
// Your integration logic here
}
How do I handle form validation errors from the SendSquared API?
You can enhance error handling for better user experience:
fetch(apiUrl, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(apiData)
})
.then(response => {
if (!response.ok) {
return response.json().then(err => {
throw new Error(`API Error ${response.status}: ${err.message || 'Unknown error'}`);
});
}
return response.json();
})
.then(data => {
console.log('Success:', data);
showSuccessMessage();
})
.catch(error => {
console.error('Error:', error);
if (error.message.includes('422')) {
showErrorMessage('Please check your email format and phone number.');
} else {
showErrorMessage('There was an error. Please try again.');
}
});
What data formats are required for SendSquared API fields?
- Email: Valid email format (HTML5 email validation)
- Phone: Must be in E.164 format (+1XXXXXXXXXX for US numbers) for Lead API
- Names: String values, can handle Unicode characters
- Custom fields: String values, prefix with '-' for custom fields in popup API
- Dates: ISO 8601 format (YYYY-MM-DDTHH:MM:SSZ) for Lead API
- Boolean values: true/false for checkboxes
Is the Squarespace integration GDPR compliant?
The integration respects GDPR requirements:
- Only processes data after explicit form submission by the user
- Doesn't store data locally beyond standard browser handling
- Transmits data securely via HTTPS to SendSquared
- You should add GDPR consent checkboxes to your Squarespace forms
- Consider adding privacy policy links near your forms
- Squarespace has built-in GDPR compliance features you can enable
Can I update existing contacts instead of creating duplicates?
Yes, both SendSquared APIs handle this automatically:
- Popup API: Updates existing contacts with matching email addresses
- Lead with Contact API: Updates existing contacts and creates new leads linked to them
- Email serves as the unique identifier for contact matching
- Multiple leads can be associated with the same contact
What are the API rate limits for SendSquared?
SendSquared API limits:
- 1000 requests per hour per API key
- 10 concurrent requests maximum
- For high-volume forms, consider implementing:
- Request queuing for peak times
- Exponential backoff for failed requests
- Client-side rate limiting
- Contact SendSquared support for higher limits if needed
- The integration handles rate limiting through error logging and user feedback