JavaScript Beacon
Basic Usage
Learn how to use the AgentShield Beacon for AI agent detection
Getting Started
Once you've installed the beacon, here's how to use it effectively.
Basic Initialization
import { AgentShieldBeacon } from '@kya-os/agentshield-beacon';
// Minimal configuration
const beacon = new AgentShieldBeacon({
apiKey: 'your-api-key'
});
// With recommended settings
const beacon = new AgentShieldBeacon({
apiKey: 'your-api-key',
batchSize: 20, // Batch 20 events before sending
flushInterval: 5000, // Auto-send every 5 seconds
useWorker: true, // Use WebWorker for better performance
debug: false // Set to true in development
});
Tracking Page Views
The most basic use case is tracking page views:
// Track current page view
beacon.collect('pageview');
// Track on route changes (SPA)
window.addEventListener('popstate', () => {
beacon.collect('pageview');
});
// React Router example
import { useLocation } from 'react-router-dom';
function App() {
const location = useLocation();
useEffect(() => {
beacon.collect('pageview');
}, [location]);
return <Routes>...</Routes>;
}
Tracking Custom Events
Track specific user interactions and behaviors:
Basic Event Tracking
// Simple event
beacon.trackEvent('button_click');
// Event with metadata
beacon.trackEvent('form_submit', {
formId: 'signup-form',
fields: ['email', 'name'],
timestamp: Date.now()
});
// Async with error handling
try {
await beacon.trackEvent('purchase', {
productId: 'SKU123',
price: 29.99,
currency: 'USD'
});
console.log('Purchase tracked');
} catch (error) {
console.error('Tracking failed:', error);
}
Common Event Patterns
// User authentication
beacon.trackEvent('login_attempt', {
method: 'email',
success: true
});
// Content interaction
beacon.trackEvent('article_read', {
articleId: '123',
readTime: 45,
scrollDepth: 0.8
});
// E-commerce
beacon.trackEvent('add_to_cart', {
productId: 'PROD-456',
quantity: 2,
value: 59.98
});
// Search
beacon.trackEvent('search', {
query: 'javascript tutorial',
results: 42,
filters: ['beginner', 'free']
});
Session Management
The beacon automatically manages sessions, but you can customize behavior:
const beacon = new AgentShieldBeacon({
apiKey: 'your-api-key',
sessionTimeout: 1800000, // 30 minutes
sessionCookieName: '_as_session' // Custom cookie name
});
// Get current session ID
const sessionId = beacon.getSessionId();
// Force new session
beacon.resetSession();
Page Unload Tracking
Ensure events are sent even when users leave:
// Track page unload
window.addEventListener('beforeunload', () => {
beacon.trackPageUnload();
});
// Or use visibilitychange for better reliability
document.addEventListener('visibilitychange', () => {
if (document.hidden) {
beacon.flush(); // Send all pending events
}
});
Working with Forms
const form = document.getElementById('contact-form');
form.addEventListener('submit', async (e) => {
e.preventDefault();
// Track form submission
await beacon.trackEvent('form_submit', {
formId: 'contact-form',
fields: Array.from(form.elements)
.filter(el => el.name)
.map(el => el.name)
});
// Submit form
form.submit();
});
// Track form abandonment
let formStarted = false;
form.addEventListener('input', () => {
if (!formStarted) {
formStarted = true;
beacon.trackEvent('form_start', {
formId: 'contact-form'
});
}
});
window.addEventListener('beforeunload', () => {
if (formStarted && !form.submitted) {
beacon.trackEvent('form_abandon', {
formId: 'contact-form'
});
}
});
function ContactForm() {
const [started, setStarted] = useState(false);
const handleSubmit = async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
await beacon.trackEvent('form_submit', {
formId: 'contact-form',
fields: Array.from(formData.keys())
});
// Submit logic
};
const handleInput = () => {
if (!started) {
setStarted(true);
beacon.trackEvent('form_start', {
formId: 'contact-form'
});
}
};
useEffect(() => {
return () => {
if (started) {
beacon.trackEvent('form_abandon', {
formId: 'contact-form'
});
}
};
}, [started]);
return (
<form onSubmit={handleSubmit} onInput={handleInput}>
{/* Form fields */}
</form>
);
}
<template>
<form @submit.prevent="handleSubmit" @input="handleInput">
<!-- Form fields -->
</form>
</template>
<script setup>
import { ref, onUnmounted } from 'vue';
const started = ref(false);
const handleSubmit = async (e) => {
const formData = new FormData(e.target);
await beacon.trackEvent('form_submit', {
formId: 'contact-form',
fields: Array.from(formData.keys())
});
// Submit logic
};
const handleInput = () => {
if (!started.value) {
started.value = true;
beacon.trackEvent('form_start', {
formId: 'contact-form'
});
}
};
onUnmounted(() => {
if (started.value) {
beacon.trackEvent('form_abandon', {
formId: 'contact-form'
});
}
});
</script>
Error Tracking
Automatically track JavaScript errors:
// Global error handler
window.addEventListener('error', (event) => {
beacon.trackEvent('error', {
message: event.message,
source: event.filename,
line: event.lineno,
column: event.colno,
stack: event.error?.stack
});
});
// Promise rejection handler
window.addEventListener('unhandledrejection', (event) => {
beacon.trackEvent('unhandled_rejection', {
reason: event.reason,
promise: event.promise.toString()
});
});
Performance Monitoring
Track performance metrics:
// Page load performance
window.addEventListener('load', () => {
const perfData = performance.getEntriesByType('navigation')[0];
beacon.trackEvent('performance', {
domContentLoaded: perfData.domContentLoadedEventEnd - perfData.domContentLoadedEventStart,
loadComplete: perfData.loadEventEnd - perfData.loadEventStart,
domInteractive: perfData.domInteractive,
firstPaint: performance.getEntriesByName('first-paint')[0]?.startTime
});
});
// Track slow interactions
const startTime = performance.now();
// After some operation
const duration = performance.now() - startTime;
if (duration > 1000) {
beacon.trackEvent('slow_interaction', {
operation: 'data_fetch',
duration: Math.round(duration)
});
}
User Engagement Tracking
// Time on page
let startTime = Date.now();
window.addEventListener('beforeunload', () => {
const timeOnPage = Date.now() - startTime;
beacon.trackEvent('engagement', {
timeOnPage: Math.round(timeOnPage / 1000), // seconds
page: window.location.pathname
});
});
// Scroll depth
let maxScroll = 0;
window.addEventListener('scroll', () => {
const scrollPercent = (
window.scrollY /
(document.documentElement.scrollHeight - window.innerHeight)
) * 100;
maxScroll = Math.max(maxScroll, scrollPercent);
});
window.addEventListener('beforeunload', () => {
beacon.trackEvent('scroll_depth', {
maxDepth: Math.round(maxScroll),
page: window.location.pathname
});
});
// Click tracking
document.addEventListener('click', (e) => {
const target = e.target.closest('[data-track]');
if (target) {
beacon.trackEvent('click', {
element: target.dataset.track,
text: target.textContent,
href: target.href
});
}
});
Conditional Tracking
Respect user privacy preferences:
// Check Do Not Track
const respectDNT = navigator.doNotTrack === '1';
if (!respectDNT) {
beacon.collect('pageview');
}
// Check user consent
const hasConsent = localStorage.getItem('tracking-consent') === 'true';
if (hasConsent) {
beacon.trackEvent('user_action', data);
}
// Conditional initialization
function initializeTracking() {
if (shouldTrack()) {
return new AgentShieldBeacon({
apiKey: 'your-key',
respectDoNotTrack: true
});
}
return null;
}
Best Practices
Performance Tip: Use batching and WebWorker mode to minimize impact on your application's performance.
1. Initialize Once
// Good: Single instance
const beacon = new AgentShieldBeacon(config);
export default beacon;
// Bad: Multiple instances
function trackEvent() {
const beacon = new AgentShieldBeacon(config); // Don't do this
beacon.trackEvent('action');
}
2. Use Async/Await
// Good: Handle async properly
async function trackAction() {
try {
await beacon.trackEvent('action', data);
// Continue after tracking
} catch (error) {
// Handle error gracefully
console.error('Tracking failed:', error);
}
}
// Bad: Fire and forget without error handling
beacon.trackEvent('action', data); // No error handling
3. Clean Up Resources
// Good: Clean up on unmount
useEffect(() => {
const beacon = new AgentShieldBeacon(config);
return () => {
beacon.destroy();
};
}, []);
// Bad: Memory leak
useEffect(() => {
const beacon = new AgentShieldBeacon(config);
// No cleanup
}, []);
4. Batch Related Events
// Good: Use batching
beacon.trackEvent('product_view', { id: '1' });
beacon.trackEvent('product_view', { id: '2' });
beacon.trackEvent('product_view', { id: '3' });
// These will be sent in one batch
// Bad: Force immediate sends
beacon.trackEvent('product_view', { id: '1' });
beacon.flush();
beacon.trackEvent('product_view', { id: '2' });
beacon.flush();
// Multiple network requests
Debugging
Enable debug mode during development:
const beacon = new AgentShieldBeacon({
apiKey: 'your-key',
debug: true,
logLevel: 'debug'
});
// Check the console for:
// - Event tracking logs
// - API requests and responses
// - Configuration details
// - Error messages
Next Steps
- Events Guide - Deep dive into event tracking
- Configuration - Advanced configuration options
- API Reference - Complete API documentation
- Worker Mode - Performance optimization