Custom Events

Events API

The widget dispatches custom events that bubble from the host element, allowing you to integrate with analytics, tracking systems, or your existing JavaScript. All events include detailed payloads with relevant data.

Event Reference

All events are dispatched on the widget's host element and bubble up to document. Use standard addEventListener() to listen for them.

EventPayloadWhen Fired
cdn-calculator:ready{ countries: Country[] }Widget finished initialization and country data loaded
cdn-calculator:calculate{ country, currency, gross, period }User clicked calculate button (before API request)
cdn-calculator:resultResultCalculation completed successfully
cdn-calculator:view{ view: '<viewType>'}User switched between form and result views
cdn-calculator:errorApiErrorAPI request failed or validation error occurred

Event Details

cdn-calculator:ready

Fired when the widget is fully loaded and ready for user interaction.

mount.addEventListener('cdn-calculator:ready', e => {
  console.log('Widget ready with', e.detail.countries.length, 'countries');
});

cdn-calculator:calculate

Fired when user submits the form, before making the API request.

mount.addEventListener('cdn-calculator:calculate', e => {
  console.log('Calculating for', e.detail.country.name, 'at', e.detail.gross);
  // Track user intent
  analytics.track('salary_calculation_started', e.detail);
});

cdn-calculator:result

Fired when calculation completes successfully.

mount.addEventListener('cdn-calculator:result', e => {
  console.log('Total employer cost:', e.detail.totalEmployerCost);
  // Update URL with country code
  const url = new URL(window.location);
  url.searchParams.set('country', e.detail.country.code);
  history.replaceState({}, '', url);
});

cdn-calculator:view

Fired when user navigates between form and result views.

mount.addEventListener('cdn-calculator:view', e => {
  console.log('User switched to', e.detail.view, 'view');
});

cdn-calculator:error

Fired when an error occurs (invalid API key, network issues, etc.).

mount.addEventListener('cdn-calculator:error', e => {
  console.error('Widget error:', e.detail.message);
  // Show custom error message or fallback
});

Integration Examples

Google Analytics 4:

mount.addEventListener('cdn-calculator:result', e => {
  gtag('event', 'salary_calculated', {
    country: e.detail.country.code,
    gross_amount: e.detail.grossAmount.amount,
    employer_cost: e.detail.totalEmployerCost.amount
  });
});

Error Handling:

mount.addEventListener('cdn-calculator:error', e => {
	// Handle Error
});
📘

All event payloads are immutable and contain the exact data at the time the event was fired.


Event Payload Structures

cdn-calculator:ready

{
  countries: [
    {
      code: "CO",
      name: "Colombia",
      regions: [
        { code: "AMA", name: "Amazonas" },
        { code: "ANT", name: "Antioquia" }
      ]
    }
  ]
}

cdn-calculator:calculate

{
  country: {
    code: "CO",
    name: "Colombia"
  },
  currency: {
    code: "COP",
    name: "Colombian Peso"
  },
  gross: 2000000,  // in whole currency units
  period: "monthly"
}

cdn-calculator:result

{
  grossAmount: {
    amount: 200000000,  // in cents
    currency: "COP"
  },
  netAmount: {
    amount: 142824527,  // in cents
    currency: "COP"
  },
  deductions: [
    {
      name: "Pension Fund",
      isStatutory: true,
      amount: {
        amount: 8000000,  // in cents
        currency: "COP"
      }
    }
    // ... additional deductions
  ],
  employerContributions: [
    {
      name: "Pension Fund",
      isStatutory: true,
      amount: {
        amount: 24000000,  // in cents
        currency: "COP"
      }
    }
    // ... additional employer contributions
  ],
  totalEmployerCost: {
    amount: 43044000,  // in cents
    currency: "COP"
  },
  country: {
    code: "CO",
    name: "Colombia"
  }
}

cdn-calculator:view

{
  view: "form" | "result"
}

cdn-calculator:error

{
  message: "Unable to load calculator. Please ensure your key is valid.",
  status: 401,
  code: "UNAUTHORIZED"
}
📘

All monetary amounts are returned in cents to avoid floating-point precision issues. Divide by 100 to get the actual currency amount.