Website Forms Integration

Last updated: Sep 10, 2025Section: General

Website Forms Integration

Connect your website contact and subscription forms to Mailoo for secure message processing and automated email campaigns.

Quick Start

  1. Create a project and form integration in your Mailoo dashboard
  2. Generate an API key for your project
  3. Add the subscription form HTML to your website
  4. Configure the JavaScript handler with your API credentials
  5. Test your form submission

Prerequisites

Mailoo Account Setup

: You need an active Mailoo account with a project and form integration configured.

Website Access

: Ability to edit HTML and JavaScript on your website.

API Key

: A valid API key generated from your Mailoo dashboard.

Step 1: Create Your Integration

Navigate to your Mailoo dashboard and create a new form integration:

  1. Go to Dashboard → Projects → [Your Project] → Integrations
  2. Click "Create New Integration"
  3. Select "Form Integration"
  4. Configure your integration:
  • Name: Give your integration a descriptive name (e.g., "Newsletter Signup")
  • Status: Set to Active
  • Form Endpoint URL: Your website URL where the form is located
  • Email Field Name: The HTML name attribute for your email field (usually "email")
  • Success Redirect URL: Optional URL to redirect users after successful submission

Step 2: Generate API Key

  1. In your integration settings, navigate to the API Keys section
  2. Click "Generate New API Key"
  3. Give your API key a descriptive name (e.g., "Website Forms")
  4. Important: Copy and securely store your API key - it's only shown once!

:::: warning ::: title Warning :::

Security: Never expose your API key in client-side JavaScript. For production use, implement server-side form processing. ::::

Step 3: "Stay Updated" Subscription Form

Here's a complete example of a "Stay Updated" subscription form:

HTML Structure:

<section class="newsletter-signup">
  <div class="container">
    <h2>Stay Updated</h2>
    <p>
      Get the latest features, tips, and mindfulness insights delivered to your
      inbox.
    </p>

    <form id="mailoo-subscribe-form" class="subscribe-form">
      <div class="form-group">
        <label for="email" class="sr-only">Enter your email</label>
        <input
          type="email"
          id="email"
          name="email"
          placeholder="Enter your email"
          required
          class="email-input"
        />
      </div>

      <div class="form-group">
        <input
          type="text"
          id="name"
          name="name"
          placeholder="Your name (optional)"
          class="name-input"
        />
      </div>

      <button type="submit" class="subscribe-btn">Subscribe</button>
    </form>

    <div id="mailoo-status" class="status-message" style="display: none;">
      <span id="mailoo-status-text"></span>
    </div>
  </div>
</section>

CSS Styling:

.newsletter-signup {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
  padding: 60px 0;
  text-align: center;
}

.subscribe-form {
  max-width: 400px;
  margin: 2rem auto 0;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.email-input,
.name-input {
  padding: 12px 16px;
  border: none;
  border-radius: 8px;
  font-size: 16px;
  width: 100%;
  box-sizing: border-box;
}

.subscribe-btn {
  background: #ff6b6b;
  color: white;
  border: none;
  padding: 12px 24px;
  border-radius: 8px;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.2s;
}

.subscribe-btn:hover {
  background: #ff5252;
}

.subscribe-btn:disabled {
  background: #ccc;
  cursor: not-allowed;
}

.status-message {
  margin-top: 1rem;
  padding: 10px;
  border-radius: 4px;
  text-align: center;
}

.status-success {
  background: rgba(76, 175, 80, 0.1);
  color: #4caf50;
  border: 1px solid #4caf50;
}

.status-error {
  background: rgba(244, 67, 54, 0.1);
  color: #f44336;
  border: 1px solid #f44336;
}

Step 4: JavaScript Implementation

Add this JavaScript code to handle form submissions:

document.addEventListener('DOMContentLoaded', function () {
  const form = document.getElementById('mailoo-subscribe-form')
  const statusDiv = document.getElementById('mailoo-status')
  const statusText = document.getElementById('mailoo-status-text')

  // Replace with your actual values from Mailoo dashboard
  const MAILOO_CONFIG = {
    apiUrl: 'https://api.mailoo.com/api/v1', // Production URL
    projectUid: 'your-project-uid-here', // From dashboard
    apiKey: 'your-api-key-here', // From API Keys section
  }

  form.addEventListener('submit', async function (e) {
    e.preventDefault()

    // Show loading state
    const submitBtn = form.querySelector('.subscribe-btn')
    const originalText = submitBtn.textContent
    submitBtn.textContent = 'Subscribing...'
    submitBtn.disabled = true

    try {
      // Collect form data
      const formData = {
        name: form.name.value.trim() || 'Subscriber',
        email: form.email.value.trim(),
        subject: 'Newsletter Subscription',
        message: `New newsletter subscription from ${form.name.value.trim() || form.email.value}`,
        source: window.location.href,
        metadata: {
          type: 'newsletter_subscription',
          timestamp: new Date().toISOString(),
          userAgent: navigator.userAgent,
          referrer: document.referrer || 'direct',
        },
      }

      // Validate required fields
      if (!formData.email) {
        throw new Error('Email is required')
      }

      // Submit to Mailoo
      const response = await fetch(
        `${MAILOO_CONFIG.apiUrl}/webhooks/forms/${MAILOO_CONFIG.projectUid}`,
        {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'X-API-Key': MAILOO_CONFIG.apiKey,
            Origin: window.location.origin,
          },
          body: JSON.stringify(formData),
        }
      )

      const result = await response.json()

      if (response.ok && result.success) {
        // Success
        showStatus(
          'success',
          'Thank you for subscribing! Check your email for confirmation.'
        )
        form.reset()

        // Optional: Track conversion with analytics
        if (typeof gtag !== 'undefined') {
          gtag('event', 'newsletter_signup', {
            event_category: 'engagement',
            event_label: 'success',
          })
        }
      } else {
        // API error
        throw new Error(result.message || 'Subscription failed')
      }
    } catch (error) {
      console.error('Subscription error:', error)
      showStatus(
        'error',
        'Subscription failed. Please try again or contact us directly.'
      )

      // Optional: Track error with analytics
      if (typeof gtag !== 'undefined') {
        gtag('event', 'newsletter_signup_error', {
          event_category: 'error',
          event_label: error.message,
        })
      }
    } finally {
      // Reset button
      submitBtn.textContent = originalText
      submitBtn.disabled = false
    }
  })

  function showStatus(type, message) {
    statusText.textContent = message
    statusDiv.className = `status-message status-${type}`
    statusDiv.style.display = 'block'

    // Auto-hide success messages after 5 seconds
    if (type === 'success') {
      setTimeout(() => {
        statusDiv.style.display = 'none'
      }, 5000)
    }
  }
})

Step 5: Configuration

Required Configuration Values:


Variable Description


MAILOO_CONFIG.apiUrl Production: https://api.mailoo.com/api/v1

MAILOO_CONFIG.projectUid Your project UID from the dashboard URL

MAILOO_CONFIG.apiKey API key generated in Step 2


: Configuration Options

Finding Your Configuration Values:

  1. Project UID: Found in your dashboard URL: /dashboard/projects/[PROJECT_UID]
  2. API Key: Generated in your project's API Keys section
  3. API URL: Use production URL for live websites

Secure Server-Side Implementation

For production websites, implement form processing on your server to keep API keys secure:

Node.js/Express Example:

// server.js
const express = require('express')
const app = express()

app.use(express.json())
app.use(express.urlencoded({ extended: true }))

app.post('/api/subscribe', async (req, res) => {
  try {
    const { email, name } = req.body

    // Validate required fields
    if (!email || !email.includes('@')) {
      return res.status(400).json({
        error: 'Valid email is required',
      })
    }

    // Submit to Mailoo
    const response = await fetch(
      `${process.env.MAILOO_API_URL}/webhooks/forms/${process.env.PROJECT_UID}`,
      {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-API-Key': process.env.MAILOO_API_KEY,
          Origin: process.env.WEBSITE_ORIGIN,
        },
        body: JSON.stringify({
          name: name?.trim() || 'Subscriber',
          email: email.trim(),
          subject: 'Newsletter Subscription',
          message: `Newsletter subscription from ${name || email}`,
          source: req.headers.referer || 'server-side-form',
          metadata: {
            type: 'newsletter_subscription',
            ip: req.ip,
            userAgent: req.headers['user-agent'],
            timestamp: new Date().toISOString(),
          },
        }),
      }
    )

    const result = await response.json()

    if (response.ok && result.success) {
      res.json({
        success: true,
        message: 'Subscription successful!',
      })
    } else {
      throw new Error(result.message || 'Subscription failed')
    }
  } catch (error) {
    console.error('Subscription error:', error)
    res.status(500).json({
      error: 'Subscription failed. Please try again.',
    })
  }
})

Environment Variables (.env):

MAILOO_API_URL=https://api.mailoo.com/api/v1
PROJECT_UID=your-project-uid-here
MAILOO_API_KEY=your-api-key-here
WEBSITE_ORIGIN=https://yourdomain.com

Client-Side JavaScript (Secure Version):

// Updated form handler for server-side processing
form.addEventListener('submit', async function (e) {
  e.preventDefault()

  const submitBtn = form.querySelector('.subscribe-btn')
  const originalText = submitBtn.textContent
  submitBtn.textContent = 'Subscribing...'
  submitBtn.disabled = true

  try {
    const response = await fetch('/api/subscribe', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        email: form.email.value.trim(),
        name: form.name.value.trim(),
      }),
    })

    const result = await response.json()

    if (response.ok && result.success) {
      showStatus('success', 'Thank you for subscribing!')
      form.reset()
    } else {
      throw new Error(result.error || 'Subscription failed')
    }
  } catch (error) {
    showStatus('error', 'Subscription failed. Please try again.')
  } finally {
    submitBtn.textContent = originalText
    submitBtn.disabled = false
  }
})

Testing Your Integration

  1. Test Form Submission Fill out your subscription form and submit it. Check your Mailoo dashboard for the new message in the integration inbox.

  2. Check Integration Status Use the status endpoint to verify your integration is active:

    curl -X GET "https://api.mailoo.com/api/v1/webhooks/status/{integrationId}" \
      -H "X-API-Key: your-api-key"
    
  3. Monitor Logs Check your browser's developer console and network tab for any JavaScript errors or failed requests.

  4. Verify Email Collection Confirm that email addresses are being stored properly in your Mailoo message inbox.

Troubleshooting

401 - Invalid API Key

: - Verify your API key is correct and hasn't been regenerated

  • Ensure the API key is active in your dashboard
  • Check that you're using the correct project UID

403 - Origin Not Allowed

: - Add your website domain to the allowed origins in your integration settings

  • Ensure the Origin header matches your domain exactly (including protocol)

429 - Rate Limited

: - Too many requests from the same API key

  • Wait before retrying and consider implementing client-side throttling

CORS Errors

: - Ensure your domain is whitelisted in integration settings

  • Verify the Origin header is being sent correctly
  • Check that protocol and port match exactly

Form Validation Errors

: - Ensure email field contains valid email address

  • Check that required fields (name, email, message) are not empty
  • Verify field lengths don't exceed maximum limits

Advanced Usage

Multiple Form Types

: Use the same integration for different forms by adding identifiers:

``` javascript
metadata: {
  formType: 'newsletter',        // or 'contact', 'support'
  pageUrl: window.location.href,
  formId: 'newsletter-sidebar'
}
```

Custom Success Actions

: Handle successful submissions with custom actions:

``` javascript
if (response.ok && result.success) {
  // Show thank you modal
  showThankYouModal();

  // Redirect to thank you page
  setTimeout(() => {
    window.location.href = '/thank-you';
  }, 2000);

  // Add to email list for further marketing
  addToEmailList(formData.email);
}
```

Enhanced Analytics

: Track detailed subscription metrics:

``` javascript
// Track subscription source
gtag('event', 'newsletter_signup', {
  event_category: 'engagement',
  event_label: 'homepage-hero',
  custom_parameters: {
    form_location: 'above-fold',
    user_type: 'first-time-visitor'
  }
});
```

API Reference

Form Submission Endpoint

POST /api/v1/webhooks/forms/{projectUid}

Request Headers:


Header Required Description


Content-Type Yes application/json

X-API-Key Yes Your project API key

Origin Recommended For CORS validation


Request Body:

{
  "name": "John Doe",
  "email": "john@example.com",
  "subject": "Newsletter Subscription",
  "message": "Please add me to your mailing list",
  "source": "https://yoursite.com/newsletter",
  "metadata": {
    "type": "newsletter_subscription",
    "timestamp": "2024-01-15T10:30:00Z"
  }
}

Response Format:

{
  "success": true,
  "messageId": "msg_abc123def456",
  "message": "Form submission processed successfully"
}

Error Response:

{
  "error": "VALIDATION_ERROR",
  "message": "Request validation failed",
  "details": [
    {
      "field": "email",
      "message": "Invalid email format",
      "code": "invalid_string"
    }
  ]
}

Security Best Practices

  1. API Key Security
  • Never expose API keys in client-side code
  • Use environment variables for server-side implementations
  • Rotate API keys regularly
  • Use different keys for development and production
  1. Input Validation
  • Validate email addresses on both client and server
  • Sanitize user input before processing
  • Set appropriate field length limits
  • Implement rate limiting on your forms
  1. CORS Configuration
  • Configure allowed origins in integration settings
  • Use specific domains rather than wildcards
  • Validate Origin headers server-side
  1. Data Privacy
  • Comply with GDPR and other privacy regulations
  • Provide clear opt-in mechanisms
  • Include unsubscribe options in all communications
  • Secure transmission with HTTPS

Next Steps

Once your form integration is working:

  1. Set Up Automation: Configure automated welcome emails and drip campaigns
  2. Create Email Templates: Design professional email templates for your communications
  3. Monitor Performance: Track subscription rates and engagement metrics
  4. A/B Testing: Test different form designs and copy to optimize conversions

Need Help?

If you encounter issues or have questions:

The integration should now be collecting email addresses securely and enabling you to build your subscriber list effectively.

📚