Vue.js - SpamBlock Pixel and Forms Integration

Learn how to integrate SpamBlock Pixel and Forms solution with Vue.js forms. Complete examples for Vue 3 Composition API and Petite Vue with reactive state management.

Overview

This guide shows how to integrate both the SpamBlock Pixel and SpamBlock Forms solution with Vue.js applications. The Pixel intercepts form submissions and scores them at the edge, while the Forms solution provides a hosted endpoint for receiving submissions. Choose the approach that best fits your project.

Note: While the SpamBlock Pixel works with any backend endpoint, these examples specifically demonstrate using both the Pixel and SpamBlock Forms together. The SpamBlock Forms endpoint (https://api.spamblock.io/f/{form_id}) provides a complete hosted form solution. Learn more about Forms or use your own backend endpoint with the Pixel.

Vue 3 Composition API

For full Vue.js applications using the Composition API:

<template>
  <form ref="formRef" @submit.prevent="handleSubmit">
    <label for="name">Name</label>
    <input id="name" v-model="formData.name" name="name" type="text" required />

    <label for="email">Email Address</label>
    <input
      id="email"
      v-model="formData.email"
      name="email"
      type="email"
      required
    />

    <label for="message">Message</label>
    <textarea
      id="message"
      v-model="formData.message"
      name="message"
      required
    ></textarea>

    <button type="submit" :disabled="isSubmitting">
      {{ isSubmitting ? "Sending..." : "Send" }}
    </button>

    <p v-if="message">{{ message }}</p>
  </form>
</template>

<script setup>
import { onMounted, onUnmounted, ref } from "vue";

const formRef = ref(null);
const isSubmitting = ref(false);
const message = ref("");
const formData = ref({
  name: "",
  email: "",
  message: "",
});

let pixelScript = null;
let allowedHandler = null;

onMounted(() => {
  // Load SpamBlock Pixel
  pixelScript = document.createElement("script");
  pixelScript.src = "https://pixel.spamblock.io/latest.js";
  pixelScript.defer = true;
  document.head.appendChild(pixelScript);

  // Wait for pixel to load, then set up event listener
  pixelScript.onload = () => {
    if (formRef.value) {
      allowedHandler = async (event) => {
        event.preventDefault();
        isSubmitting.value = true;
        message.value = "";

        const formDataObj = new FormData(event.target);

        try {
          const response = await fetch(
            "https://api.spamblock.io/f/{form_id}",
            {
              method: "POST",
              body: formDataObj,
            }
          );

          if (response.ok) {
            message.value = "Submission successful!";
            formRef.value.reset();
            formData.value = { name: "", email: "", message: "" };
          } else {
            message.value = "There was an error submitting the form.";
          }
        } catch (error) {
          message.value = "Network error. Please try again.";
          console.error("Error:", error);
        } finally {
          isSubmitting.value = false;
        }
      };

      formRef.value.addEventListener("spamblock:allowed", allowedHandler);
    }
  };
});

onUnmounted(() => {
  if (formRef.value && allowedHandler) {
    formRef.value.removeEventListener("spamblock:allowed", allowedHandler);
  }
  if (pixelScript && document.head.contains(pixelScript)) {
    document.head.removeChild(pixelScript);
  }
});
</script>

When to Use:

  • You're building a full Vue.js application (Vue 3 recommended)
  • You want to use the Composition API
  • You need component-level form handling
  • You prefer reactive data binding with build tooling

Petite Vue

For lightweight progressive enhancement without a build step:

<!-- Load Petite Vue -->
<script src="https://unpkg.com/petite-vue" defer init></script>

<!-- Load SpamBlock Pixel -->
<script src="https://pixel.spamblock.io/latest.js" defer></script>

<div v-scope="{ 
  name: '', 
  email: '', 
  message: '', 
  isSubmitting: false, 
  statusMessage: '',
  async handleSubmit(event) {
    event.preventDefault();
    this.isSubmitting = true;
    this.statusMessage = '';

    const form = event.target;
    const formData = new FormData(form);

    try {
      const response = await fetch('https://api.spamblock.io/f/{form_id}', {
        method: 'POST',
        body: formData
      });

      if (response.ok) {
        this.statusMessage = 'Submission successful!';
        form.reset();
        this.name = '';
        this.email = '';
        this.message = '';
      } else {
        this.statusMessage = 'There was an error submitting the form.';
      }
    } catch (error) {
      this.statusMessage = 'Network error. Please try again.';
      console.error('Error:', error);
    } finally {
      this.isSubmitting = false;
    }
  }
}">
  <form 
    id="contact-form" 
    @submit.prevent="handleSubmit"
    @spamblock:allowed="handleSubmit"
  >
    <label for="name">Name</label>
    <input 
      id="name" 
      v-model="name" 
      name="name" 
      type="text" 
      required 
    />

    <label for="email">Email Address</label>
    <input 
      id="email" 
      v-model="email" 
      name="email" 
      type="email" 
      required 
    />

    <label for="message">Message</label>
    <textarea 
      id="message" 
      v-model="message" 
      name="message" 
      required
    ></textarea>

    <button type="submit" :disabled="isSubmitting">
      {{ isSubmitting ? 'Sending...' : 'Send' }}
    </button>

    <p v-if="statusMessage">{{ statusMessage }}</p>
  </form>
</div>

When to Use:

  • You want lightweight Vue-like functionality without a build step
  • You're doing progressive enhancement on existing HTML
  • You need minimal JavaScript overhead
  • You want Vue-like syntax without full Vue.js framework
  • You're working with static sites or simple pages

What This Example Shows

  • How to integrate SpamBlock Pixel with Vue.js components
  • Vue 3 Composition API patterns (<script setup>)
  • Petite Vue for progressive enhancement
  • Reactive state management with ref
  • Proper lifecycle hooks (onMounted, onUnmounted)
  • Template refs for accessing DOM elements

How it Works

  1. User submits form
  2. SpamBlock Pixel intercepts submission
  3. Submission scored at the edge
  4. If spam: submission blocked, event not fired
  5. If allowed: spamblock:allowed event fired
  6. Vue component handles the allowed submission

Common Mistakes

  1. Not cleaning up event listeners - Always remove event listeners in onUnmounted
  2. Not cleaning up script tag - Remove the pixel script when component unmounts (Vue 3 only)
  3. Missing template ref - Use ref to access the form DOM element
  4. Race conditions - Wait for pixel script to load before setting up listeners (Vue 3 only)
  5. Not using .value - Remember to use .value when accessing ref values in script (Vue 3 only)
  6. Form reset - Reset both the form element and reactive data
  7. Missing init attribute - Add init to Petite Vue script tag for auto-initialization (Petite Vue only)

Learn More