# Vanilla JavaScript (/docs/developer/vanilla-js)





# Vanilla JavaScript [#vanilla-javascript]

The package exposes a browser global (`window.ucoderInsight`) when loaded from a CDN — no build step or bundler required. Wait for the SDK ready event before initializing it.

```html
<script
  defer
  src="https://cdn.jsdelivr.net/npm/ucoder-insight@1/dist/index.js"
></script>
<script>
  window.addEventListener("ucoderInsightReady", () => {
    window.ucoderInsight.init("YOUR_PUBLIC_TRACKING_ID");
  });
</script>
```

Place both `<script>` tags before the closing `</body>` tag, or in `<head>` with `defer` as shown above.

<Callout type="warn">
  Pin a major version in the CDN URL (`ucoder-insight@1`) instead of using the
  unversioned/`@latest` URL. This prevents a future breaking release from
  silently changing behavior on your live site.
</Callout>

## Why wait for `ucoderInsightReady` [#why-wait-for-ucoderinsightready]

The CDN script loads asynchronously (`defer`), so `window.ucoderInsight` isn't guaranteed to exist the instant your page's inline script runs. Listening for `ucoderInsightReady` guarantees the global is available before you call `.init()`.

<Callout type="info">
  Events sent before initialization aren't lost — they're queued internally by
  the browser global and flushed once `init()` runs. In practice, waiting for
  `ucoderInsightReady` is still the recommended pattern.
</Callout>

## Tracking custom events [#tracking-custom-events]

After initialization, send custom events with `trackCustomEvent`:

```html
<script>
  window.ucoderInsight.trackCustomEvent({
    event_name: "signup_started",
    action_category: "form",
  });
</script>
```

| Field             | Required | Description                                                                                                                                  |
| :---------------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------- |
| `event_name`      | Yes      | The primary name identifying the event type (e.g. `user_signup_attempt`).                                                                    |
| `action_category` | Yes      | Groups similar events for high-level reporting (e.g. `form`, `media`, `ecommerce`, `navigation`).                                            |
| `object_id`       | No       | Identifier for the object related to the event (e.g. a form or video ID).                                                                    |
| `status`          | No       | The outcome of the action — `"success"` or `"failure"`.                                                                                      |
| `message`         | No       | A human-readable description or error message for the event.                                                                                 |
| `additionalData`  | No       | Extra key–value context. Values must be `string`, `number`, `boolean`, `null`, or `undefined` — nested objects and arrays are not supported. |

A more complete example, fired on a button click:

```html
<button
  onclick="window.ucoderInsight.trackCustomEvent({
    event_name: 'cta_clicked',
    action_category: 'navigation',
    status: 'success',
    object_id: 'hero_cta',
    additionalData: { plan_type: 'premium' }
  })"
>
  Get Started
</button>
```

## Page views [#page-views]

Page views are tracked automatically on every full page load — since a plain HTML site navigates by loading a new page each time, no route-change handling (like in a single-page app) is needed here.

See [Configuration](/docs/getting-started/configuration) for supported initialization options.
