Pro Plan10 minutesintermediate

Custom Event Goals

Track conversions with custom JavaScript events - form submissions, video plays, AJAX actions, and complex interactions.

goalseventsjavascriptcustomtracking
Last updated: January 15, 2025
Pro Plan

Custom event goals let you track any action by firing JavaScript events. Perfect for forms, video plays, and complex interactions.

When to Use Custom Events

Best for tracking:

  • Form submissions (AJAX)
  • Video interactions (play, complete)
  • Single-page app navigation
  • Add to cart actions
  • Feature usage in web apps
  • Any JavaScript-triggered action

How Custom Events Work

  1. You add JavaScript code to your site
  2. Code fires when action occurs
  3. Zenovay receives the event
  4. Goal is recorded

Basic Implementation

Tracking an Event

// Simple event
zenovay('goal', 'event_name');

// Event with value
zenovay('goal', 'purchase', { value: 99.99 });

// Event with properties
zenovay('goal', 'signup', {
  value: 50,
  plan: 'pro',
  source: 'homepage'
});

Creating the Goal

  1. Go to Goals and click New Goal
  2. Select "Custom Event"
  3. Enter event name (e.g., purchase)
  4. Set name and value options
  5. Save

Event Naming

Best Practices

Good NamesBad Names
signup_completegoal1
purchaseclick
video_50_percentevent
add_to_cart123

Naming Conventions

Choose a consistent pattern:

  • snake_case: form_submit
  • camelCase: formSubmit
  • kebab-case: form-submit

Categories with Prefixes

Organize events with prefixes:

// E-commerce events
zenovay('goal', 'ecom_add_to_cart');
zenovay('goal', 'ecom_checkout_start');
zenovay('goal', 'ecom_purchase');

// Engagement events
zenovay('goal', 'engage_video_play');
zenovay('goal', 'engage_scroll_50');

Common Implementations

Form Submission

document.querySelector('form').addEventListener('submit', function(e) {
  zenovay('goal', 'contact_form');
});

// Or for AJAX forms
function onFormSuccess() {
  zenovay('goal', 'contact_form');
}

Video Interactions

const video = document.querySelector('video');

video.addEventListener('play', function() {
  zenovay('goal', 'video_play');
});

video.addEventListener('ended', function() {
  zenovay('goal', 'video_complete');
});

// Track 50% progress
video.addEventListener('timeupdate', function() {
  if (video.currentTime / video.duration > 0.5) {
    zenovay('goal', 'video_50_percent');
  }
});

E-commerce Actions

// Add to cart
function addToCart(product) {
  // Your cart logic...

  zenovay('goal', 'add_to_cart', {
    value: product.price,
    product_id: product.id
  });
}

// Purchase complete
function onPurchaseComplete(order) {
  zenovay('goal', 'purchase', {
    value: order.total,
    order_id: order.id,
    items: order.items.length
  });
}

Sign Up / Registration

async function handleSignup(formData) {
  try {
    const response = await api.signup(formData);

    if (response.success) {
      zenovay('goal', 'signup_complete', {
        value: 50, // Estimated lead value
        plan: formData.plan
      });
    }
  } catch (error) {
    // Handle error
  }
}

Passing Values

Static Value

Set in Zenovay dashboard:

  • Goal value: $50
  • Every event = $50

Dynamic Value

Pass from your code:

// Order value
zenovay('goal', 'purchase', {
  value: orderTotal
});

// Calculated value
const leadValue = isPremium ? 100 : 25;
zenovay('goal', 'lead', { value: leadValue });

Value from Page

Read from DOM:

const price = parseFloat(
  document.querySelector('.price').textContent.replace('$', '')
);
zenovay('goal', 'purchase', { value: price });

Event Properties

Passing Properties

Include additional data:

zenovay('goal', 'signup', {
  value: 50,
  plan: 'pro',
  source: 'homepage',
  referrer: document.referrer
});

Property Types

PropertyTypeExample
valuenumber99.99
currencystring"USD"
product_idstring"SKU123"
categorystring"electronics"
quantitynumber2

Using Properties in Reports

Scale Plan

Properties enable:

  • Filtering by property
  • Grouping by category
  • Custom segmentation

Framework Integrations

React

import { useCallback } from 'react';

function SignupForm() {
  const handleSubmit = useCallback((data) => {
    // Submit logic...

    window.zenovay('goal', 'signup');
  }, []);

  return <form onSubmit={handleSubmit}>...</form>;
}

Vue

<script>
export default {
  methods: {
    handleSubmit() {
      // Submit logic...

      window.zenovay('goal', 'signup');
    }
  }
}
</script>

Next.js

// In your component or API route
export default function handler(req, res) {
  // Server logic...

  // Client-side tracking (in component)
  if (typeof window !== 'undefined') {
    window.zenovay('goal', 'api_success');
  }
}

Single Page Apps (SPAs)

Route Change Tracking

For virtual pageviews:

// React Router
history.listen(() => {
  zenovay('page');
});

// Vue Router
router.afterEach(() => {
  zenovay('page');
});

Goal After Navigation

// Navigate then track
router.push('/success').then(() => {
  zenovay('goal', 'signup_complete');
});

Conditional Tracking

Track Based on Conditions

// Only track if conditions met
if (user.isNewUser && !user.hasConvertedBefore) {
  zenovay('goal', 'first_conversion');
}

// A/B test variant
if (experimentVariant === 'B') {
  zenovay('goal', 'variant_b_conversion');
}

Debouncing Events

Prevent duplicate fires:

let hasTracked = false;

function trackOnce(eventName) {
  if (!hasTracked) {
    zenovay('goal', eventName);
    hasTracked = true;
  }
}

Error Handling

Safe Tracking

Handle cases where Zenovay isn't loaded:

function safeTrackGoal(eventName, properties) {
  if (typeof zenovay === 'function') {
    zenovay('goal', eventName, properties);
  } else {
    console.warn('Zenovay not loaded');
  }
}

Async Tracking

For critical conversions:

// Wait for Zenovay to load
function trackWhenReady(eventName, properties) {
  if (window.zenovay) {
    window.zenovay('goal', eventName, properties);
  } else {
    window.addEventListener('zenovay:ready', function() {
      window.zenovay('goal', eventName, properties);
    });
  }
}

Testing Events

Debug Mode

Enable console logging:

zenovay('debug');

// Now track something
zenovay('goal', 'test_event');
// Check console for output

Verify in Dashboard

  1. Fire test event
  2. Go to Analytics → Real-time
  3. Verify goal appears
  4. Check goal value

Network Tab

  1. Open DevTools → Network
  2. Fire event
  3. Look for request to Zenovay
  4. Verify payload

Troubleshooting

Events Not Recording

Check script loaded:

console.log(typeof zenovay); // Should be 'function'

Check event name matches:

  • Dashboard: signup
  • Code: zenovay('goal', 'signup')
  • Code: zenovay('goal', 'Signup')

Check for errors:

  • Browser console for errors
  • Network tab for failed requests

Value Not Recording

Ensure value is a number:

// Wrong
zenovay('goal', 'purchase', { value: "$99.99" });

// Correct
zenovay('goal', 'purchase', { value: 99.99 });

Next Steps

Was this article helpful?