API Documentation

Track form submissions programmatically using FormTrackr's API. Perfect for React, Vue, Angular, and other custom implementations.

Overview

FormTrackr's API allows you to track form submissions directly from your application without using the default JavaScript snippet. This is ideal for:

  • React, Vue, Angular, and other JavaScript frameworks
  • Single-page applications (SPAs) with programmatic form handling
  • Multi-step forms that don't trigger native submit events
  • Server-side form processing
  • Custom form validation and submission logic

Note: If you're using standard HTML forms, you can use our default tracking snippet which automatically captures form submissions. This API documentation is for custom implementations.

Getting Started

Step 1: Get Your Project Key

Log in to your FormTrackr dashboard and navigate to your project. Your Project Key is displayed in the project settings. This unique identifier is required for all API requests.

Step 2: Make API Requests

Send POST requests to the FormTrackr API endpoint:

https://formtrackr.app/api/collect

API Endpoint

POST/api/collect

Request Headers

Content-Type: application/json

Request Body

{
  "projectKey": "string (required)",
  "sessionId": "string (required)",
  "pageUrl": "string (required, valid URL)",
  "formId": "string (optional)",
  "formName": "string (optional)",
  "fields": [{ "name": "string", "value": "string" }],
  "contact": {
    "name": "string (optional)",
    "email": "string (optional, valid email)",
    "phone": "string (optional)"
  },
  "attribution": {
    "landingPage": "string (optional)",
    "referrer": "string (optional)",
    "utms": {
      "source": "string (optional)",
      "medium": "string (optional)",
      "campaign": "string (optional)",
      "term": "string (optional)",
      "content": "string (optional)"
    },
    "gclid": "string (optional)"
  },
  "timestamp": "string (optional, ISO 8601)",
  "userAgent": "string (optional)"
}

Response

Success response (200):

{ "success": true, "leadId": "string", "requestId": "string" }

Error responses:

  • 400 Bad Request: Invalid request data or missing required fields
  • 403 Forbidden: Domain not allowed (if domain allowlist is configured)
  • 429 Too Many Requests: Rate limit exceeded
  • 500 Internal Server Error: Server error

React Example

Here's a complete example of tracking a form submission in a React component:

import React, { useState } from 'react';

const ContactForm = () => {
  const [formData, setFormData] = useState({ name: '', email: '', message: '' });

  const getSessionId = () => {
    let sessionId = localStorage.getItem('formtrackr_session_id');
    if (!sessionId) {
      sessionId = Math.random().toString(36).substring(2) + Date.now().toString(36);
      localStorage.setItem('formtrackr_session_id', sessionId);
    }
    return sessionId;
  };

  const getUrlParam = (name) => new URLSearchParams(window.location.search).get(name);

  const handleSubmit = async (e) => {
    e.preventDefault();
    const response = await fetch('/api/contact', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(formData),
    });

    if (response.ok) {
      try {
        await fetch('https://formtrackr.app/api/collect', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            projectKey: 'YOUR_PROJECT_KEY',
            sessionId: getSessionId(),
            pageUrl: window.location.href,
            formId: 'contact-form',
            formName: 'Contact Form',
            fields: [
              { name: 'name', value: formData.name },
              { name: 'email', value: formData.email },
              { name: 'message', value: formData.message },
            ],
            contact: { name: formData.name, email: formData.email },
            attribution: {
              landingPage: window.location.href,
              referrer: document.referrer || null,
              utms: {
                source: getUrlParam('utm_source'),
                medium: getUrlParam('utm_medium'),
                campaign: getUrlParam('utm_campaign'),
              },
              gclid: getUrlParam('gclid'),
            },
            timestamp: new Date().toISOString(),
            userAgent: navigator.userAgent,
          }),
        });
      } catch (error) {
        console.error('FormTrackr tracking error:', error);
      }
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" value={formData.name} onChange={(e) => setFormData({...formData, name: e.target.value})} placeholder="Name" required />
      <input type="email" value={formData.email} onChange={(e) => setFormData({...formData, email: e.target.value})} placeholder="Email" required />
      <textarea value={formData.message} onChange={(e) => setFormData({...formData, message: e.target.value})} placeholder="Message" required />
      <button type="submit">Submit</button>
    </form>
  );
};

export default ContactForm;

Plain JavaScript Example

function getSessionId() {
  let sessionId = localStorage.getItem('formtrackr_session_id');
  if (!sessionId) {
    sessionId = Math.random().toString(36).substring(2) + Date.now().toString(36);
    localStorage.setItem('formtrackr_session_id', sessionId);
  }
  return sessionId;
}

async function trackFormSubmission(formData) {
  try {
    await fetch('https://formtrackr.app/api/collect', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        projectKey: 'YOUR_PROJECT_KEY',
        sessionId: getSessionId(),
        pageUrl: window.location.href,
        fields: [
          { name: 'name', value: formData.name },
          { name: 'email', value: formData.email },
        ],
        contact: { name: formData.name, email: formData.email },
        attribution: {
          gclid: new URLSearchParams(window.location.search).get('gclid'),
          utms: {
            source: new URLSearchParams(window.location.search).get('utm_source'),
            medium: new URLSearchParams(window.location.search).get('utm_medium'),
            campaign: new URLSearchParams(window.location.search).get('utm_campaign'),
          },
        },
        timestamp: new Date().toISOString(),
      }),
    });
  } catch (error) {
    console.error('Tracking error:', error);
  }
}

document.getElementById('contact-form').addEventListener('submit', async (e) => {
  e.preventDefault();
  const formData = {
    name: document.getElementById('name').value,
    email: document.getElementById('email').value,
  };
  const response = await fetch('/api/contact', {
    method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(formData),
  });
  if (response.ok) trackFormSubmission(formData);
});

Server-Side Example (Node.js)

const express = require('express');
const fetch = require('node-fetch');
const app = express();
app.use(express.json());

app.post('/api/contact', async (req, res) => {
  const { name, email, message } = req.body;
  // Process your form submission here...

  try {
    await fetch('https://formtrackr.app/api/collect', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        projectKey: process.env.FORMTRACKR_PROJECT_KEY,
        sessionId: req.body.sessionId || 'server-session',
        pageUrl: req.headers.referer || 'unknown',
        fields: [
          { name: 'name', value: name },
          { name: 'email', value: email },
          { name: 'message', value: message },
        ],
        contact: { name, email },
        attribution: req.body.attribution || {},
        timestamp: new Date().toISOString(),
        userAgent: req.headers['user-agent'],
      }),
    });
  } catch (error) {
    console.error('FormTrackr tracking error:', error);
  }

  res.json({ success: true });
});

app.listen(3000);

Best Practices

1. Track After Successful Submission

Always track form submissions after your form has been successfully processed to prevent spam from being tracked.

❌ Don't: Track before validation or submission

✅ Do: Track only after successful backend submission

1.1 Recommended: UseBasin + FormTrackr (Static Sites)

For static sites on Netlify or Vercel, use UseBasin as your primary form backend and spam filter. Track only successful submissions in FormTrackr. UseBasin handles spam protection and delivery; FormTrackr focuses on lead attribution and analytics.

2. Session ID Management

Generate a unique session ID when a user first visits your site and store it in localStorage. Reuse the same session ID for all form submissions during that session to ensure proper attribution.

3. Capture Attribution Data

Capture UTM parameters and GCLID from the URL when the user first lands on your site. Store this data and include it in all form submission tracking requests.

4. Handle Errors Gracefully

FormTrackr tracking should never block your form submission. Wrap tracking calls in try-catch blocks.

Rate Limiting

  • 100 requests per minute per project key and IP address combination
  • Exceeding the rate limit returns a 429 Too Many Requests response
  • Rate limits reset after the time window expires

Domain Allowlist

If you've configured a domain allowlist in your project settings, API requests must originate from an allowed domain. The API checks the Origin or Referer header to validate the request source.

Field Reference

Required Fields

  • projectKey — Your project's unique identifier
  • sessionId — Unique session identifier (generate and store in localStorage)
  • pageUrl — Valid URL of the page where the form was submitted

Optional Fields

  • formId — HTML form element ID
  • formName — HTML form element name attribute
  • fields — Array of form field name/value pairs
  • contact — Object with name, email, and/or phone
  • attribution — UTM parameters, GCLID, referrer, etc.
  • timestamp — ISO 8601 timestamp (defaults to current time)
  • userAgent — User agent string (defaults to request header)

Troubleshooting

Invalid Project Key (400)

Make sure you're using the correct project key from your FormTrackr dashboard. Project keys are case-sensitive.

Domain Not Allowed (403)

If you've configured a domain allowlist, ensure your request originates from an allowed domain. Check the Origin or Referer header.

Leads Not Appearing in Dashboard

  • You're viewing the correct project
  • Your browser cache is cleared
  • There are no filters applied in the leads view

Need Help?