# Custom JS

You can add JavaScript to your creatives by using the `Custom JS` tab in the creative editor. This is a powerful feature that allows you to add custom code to your creatives. You can use this feature to add custom tracking, analytics, or any other custom code to your creatives, including third-party APIs.

{% embed url="<https://www.loom.com/share/c77b83cf296c47948ac8a3cbe1c4ee0c>" %}

## Custom JavaScript

Responsive Ads creatives support custom CSS and JavaScript via the Custom Code Editor. JavaScript runs only in the rendered creative (preview page and served creatives) — not inside the editor itself.

### Accessing the editor

Click **Open Custom Code Editor** in the top-left of the creative.

* **Left panel** — CSS applied to all elements in the creative.
* **Right panel** — JavaScript.

You can write directly in the panel or, as many developers prefer, edit in an external editor and paste back. Working externally also makes it easier to keep the code under version control and use AI-assisted edits.

### Workflow

1. Write or paste JS into the JavaScript panel.
2. **Save** the creative.
3. Open the **Preview** page and refresh to see changes.

### Editor vs preview mode

Code runs in two places: inside the editor's own embedded view and on the live preview page. Some code is only safe (or only needed) on the preview side, so the framework exposes a way to check which environment you're in — the walkthrough referred to it as an "in editor" check.

Two common patterns:

* **Preview only.** Wrap the code in the editor check so it doesn't run while editing.
* **Both.** Remove the check (or invert it) so behavior like style injection applies everywhere, including the editor preview.

### Debugging

1. Open the preview in a new tab.
2. Open DevTools → **Sources**.
3. Find your code under `rad.js` — we inject a `//# sourceURL` comment so it surfaces under that filename.
4. Set breakpoints, step through, and inspect locals as usual.

### The Starting Boilerplate JS Code

Every creative starts with boilerplate that initializes two APIs:

* **`rad`** — main API entry point. Use it to update elements, fetch elements by ID, read creative config, and access other options.
* **`container`** — information about the container the creative is rendered into (format, flowline, etc.).

Lifecycle callbacks are registered inside an `if (!inEditor) { ... }` block so they only run on the preview page and on served creatives, never inside the editor.

### Lifecycle callbacks

| Callback                                     | Fires                                                   |
| -------------------------------------------- | ------------------------------------------------------- |
| `onLoad`                                     | Once, when the creative first loads                     |
| `onBeforeRender(elementDefinitions, styles)` | Before every render                                     |
| `onRender`                                   | After every render (i.e. whenever the creative changes) |

#### `onBeforeRender` arguments

* **`elementDefinitions`** — all elements in the creative, keyed by ID, with their settings. IDs match those shown in the editor's element list.
* **`styles`** — per-element styles for the current format size: sizing, visibility, and position. Each layout size has its own style block.

### Working with elements

`rad.getElementById(id)` returns a ResponsiveAds element wrapping the underlying DOM node. Specific element types expose helper methods — for example, **textbox** elements have a method to update their text and a hook into `onRender`.

### Recommended debug loop

1. Edit JS (in-panel or external editor).
2. Paste into the JavaScript panel and save.
3. Refresh the preview.
4. In **Sources**, set breakpoints inside `rad.js`.
5. Step through `onLoad` → `onBeforeRender` → `onRender`, inspecting locals to diagnose issues.

If you want to learn more about the `Radical` object, you can check out the [Radical API reference](broken://pages/uK8ym0mv66ALMmFzAzqD).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.responsiveads.com/developers/custom-js.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
