Why route ActiveCampaign signups through your own form
ActiveCampaign is a powerful automation platform, and its forms are serviceable — but they're bound to its styling and script, and the richer form features live on higher plans. For a high-conversion landing page you usually want a custom, fast form that's yours.
Own the HTML and route it through splitforms: a fully custom form with an AI spam classifier, email notifications, and a submission dashboard — while ActiveCampaign stays your automation engine. A small proxy syncs the contact, adds it to a list, and (optionally) applies a tag to trigger an automation.
Step 1 — Get your API URL, key, and list ID
In ActiveCampaign open Settings → Developer and copy your API URL (e.g. https://youraccount.api-us1.com) and API Key. Find the target list ID under Lists (shown in the URL when you open a list). Store all three as environment variables on your proxy — never in the browser.
Step 2 — The splitforms → ActiveCampaign proxy
splitforms fires a signed webhook; the proxy syncs the contact, then adds it to a list. Cloudflare Worker version:
export default {
async fetch(req, env) {
if (req.method !== "POST") return new Response("Method Not Allowed", { status: 405 });
// 1. (Recommended) verify the splitforms HMAC signature header here.
const submission = await req.json();
const f = submission.data ?? submission;
if (!f.email) return new Response("no email", { status: 400 });
const base = env.AC_API_URL; // https://youraccount.api-us1.com
const headers = {
"Api-Token": env.AC_API_KEY,
"Content-Type": "application/json",
};
// 2. Sync (upsert) the contact by email
const sync = await fetch(`${base}/api/3/contact/sync`, {
method: "POST",
headers,
body: JSON.stringify({
contact: {
email: f.email,
firstName: (f.name ?? "").split(" ")[0],
lastName: (f.name ?? "").split(" ").slice(1).join(" "),
phone: f.phone,
},
}),
}).then((r) => r.json());
const contactId = sync.contact?.id;
if (!contactId) return new Response("sync failed", { status: 502 });
// 3. Add the contact to a list (status 1 = subscribed)
await fetch(`${base}/api/3/contactLists`, {
method: "POST",
headers,
body: JSON.stringify({
contactList: { list: Number(env.AC_LIST_ID), contact: contactId, status: 1 },
}),
});
return new Response("ok", { status: 200 });
},
};Deploy the Worker and paste its URL into your form's webhook settings in the splitforms dashboard. To kick off a specific automation, add a POST /api/3/contactTags call applying a tag the automation triggers on. Verify the webhook signature — see send form data to a webhook.
Step 3 — The form
Your public form only talks to splitforms with the public access key. Swap YOUR_ACCESS_KEY for the one from your free account.
<form action="https://splitforms.com/api/submit" method="POST">
<input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
<input name="name" placeholder="Name" />
<input name="email" type="email" required placeholder="Email" />
<input name="phone" type="tel" placeholder="Phone (optional)" />
<label><input type="checkbox" name="consent" required /> Keep me in the loop</label>
<!-- honeypot -->
<input type="checkbox" name="botcheck" style="display:none" tabindex="-1" autocomplete="off" />
<button type="submit">Subscribe</button>
</form>What to do next
- Other email tools: Kit (ConvertKit) · Brevo · Mailchimp
- CRMs: Salesforce · Pipedrive
- Webhook fundamentals: send form data to a webhook
- Ready to set it up: get a free access key
FAQ
Why not use ActiveCampaign's native forms?
ActiveCampaign's forms are tied to its styling and script, and the deeper form features sit on higher plans. If you want a fully custom, fast-loading form with your own spam protection and a submission dashboard you control, own the HTML, route through splitforms, and add the contact via the API. ActiveCampaign stays your automation engine; you just stop being limited by its form builder.
Where do I find my ActiveCampaign API URL and key?
In ActiveCampaign go to Settings → Developer. You'll see your API URL (looks like https://youraccount.api-us1.com) and your API Key. Both are required, and both are secrets — keep them on your proxy host, never in the browser.
How do I both create the contact and add it to a list?
ActiveCampaign separates the two: first create (or sync) the contact via POST /api/3/contacts, then add it to a list via POST /api/3/contactLists with the contact ID, the list ID, and status 1 (subscribed). The proxy example does both calls in sequence so the contact lands on the right list, ready for your automations.
Will duplicate submissions create duplicate contacts?
Use the contact/sync endpoint instead of plain create, or check for an existing contact by email first. ActiveCampaign's sync endpoint upserts by email, so a repeat submitter updates rather than duplicates. The proxy notes where to switch to sync if you prefer.
Can I trigger an automation when the contact is added?
Yes — that's the main reason to use ActiveCampaign. Once the contact is on a list (or has a tag you apply), any automation with that list/tag as its trigger fires automatically. Apply a tag in the proxy (POST /api/3/contactTags) to start a specific welcome or nurture sequence based on the form they filled out.