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
- User submits form
- SpamBlock Pixel intercepts submission
- Submission scored at the edge
- If spam: submission blocked, event not fired
- If allowed:
spamblock:allowedevent fired - Vue component handles the allowed submission
Common Mistakes
- Not cleaning up event listeners - Always remove event listeners in
onUnmounted - Not cleaning up script tag - Remove the pixel script when component unmounts (Vue 3 only)
- Missing template ref - Use
refto access the form DOM element - Race conditions - Wait for pixel script to load before setting up listeners (Vue 3 only)
- Not using
.value- Remember to use.valuewhen accessing ref values in script (Vue 3 only) - Form reset - Reset both the form element and reactive data
- Missing
initattribute - Addinitto Petite Vue script tag for auto-initialization (Petite Vue only)
Learn More
- Pixel Getting Started - Learn the basics of SpamBlock Pixel
- Forms Getting Started - Explore our hosted form solution