# Custom JavaScript

URL: https://docs.ablyft.com/developers/application-integration/custom-javascript/

> Where to add your own JavaScript and CSS for projects, experiments and variations, and in which order it runs.



The [Visual Editor](https://docs.ablyft.com/guides/experiments/visual-editor/) covers many changes without code. For everything else you can add your
own JavaScript and CSS. ABlyft offers code fields on three levels, and the snippet runs them in a fixed order.

## Where you can add code

| Level          | Where in ABlyft                                             | Fields                                        |
| -------------- | ----------------------------------------------------------- | --------------------------------------------- |
| **Project**    | **Settings → Project Settings → Project Level Codes**       | **JS code**, **JS helper code**, **CSS code** |
| **Experiment** | Experiment settings (cog icon) → **Experiment Level Codes** | **JS code**, **Reset JS code**, **CSS code**  |
| **Variation**  | Edit the variation → **Code**                               | **JS code**, **CSS code**, **Reset JS code**  |

What each field does:

| Field                               | Description                                                                                                                                 |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| Project **JS code**                 | Runs on every page load, after the project's "General Startup" [prerequisites](https://docs.ablyft.com/developers/consent-and-security/consent-manager/) are met.  |
| Project **JS helper code**          | Runs on every page load without any dependencies, before the prerequisites are checked. Use it for helper functions that must always exist. |
| Project **CSS code**                | Runs on every page load, like the project JS code (depends on the "General Startup" prerequisites).                                         |
| Experiment **JS code**              | Runs before every variation code of this experiment.                                                                                        |
| Experiment **CSS code**             | Applies to every variation of this experiment.                                                                                              |
| Experiment **Reset JS code**        | Runs whenever the experiment is reset. See [SPA navigation](https://docs.ablyft.com/developers/application-integration/spa-navigation/#reset-js).                  |
| Variation **JS code**, **CSS code** | Run for this variation only.                                                                                                                |
| Variation **Reset JS code**         | Runs whenever the experiment is reset. See [SPA navigation](https://docs.ablyft.com/developers/application-integration/spa-navigation/#reset-js).                  |

Use the experiment level fields for code that all variations need, so you do not copy it into every variation.

Variation code fields are shown for the variation types **Code**, **Visual Editor** and **FullStack**. A variation of type
**Code** is the right choice if you want to build the variation completely with your own code. A variation
of type **Unchanged** or **Redirect** does not run code.

> The project and experiment code fields accept up to 32,768 characters each.

## In which order does code run?

When a visitor is in a variation, ABlyft runs the following in this order:

1. Project **JS helper code**
2. Project **CSS code** and project **JS code**
3. Experiment **CSS code** and experiment **JS code**
4. Variation **CSS code** and variation **JS code**
5. Visual Editor changes of the variation (if any)

Code of one level runs on every page load, so write it so that it can safely run again.

## Tools in your code

In experiment, variation, project and page-rule code, `ablyftTools` is available without any set-up. It is the same
object as [`ablyft.getTools()`](https://docs.ablyft.com/developers/reference/javascript-api/tools/). The variation editor shows a **Code
Helper** next to the code fields with the most common calls, which you copy with one click:

```js
// Wait for an element to appear in the DOM
ablyftTools.waitForElement(selector, (elem) => {
  // Handle element
});

// Wait for an element to be in the viewport
ablyftTools.elementIsInView(selector, (elem) => {
  // Handle element
});

// Wait for the DOM to be loaded
ablyftTools.domLoaded(() => {
  // Code after dom is loaded
});

// Redirect to url or query string
ablyftTools.redirect(redirectUrl);
```

Replace `selector` and `redirectUrl` with your values. All functions, such as cookies, URL helpers, waiting and data layer
functions, are listed in the [tools reference](https://docs.ablyft.com/developers/reference/javascript-api/tools/).

## A complete example

Change the headline and the button of a landing page, and make sure the change can be undone.

**Variation JS code**

```js
ablyftTools.waitForElement('.hero h1', (headline) => {
  headline.dataset.originalText = headline.textContent;
  headline.textContent = 'Free shipping on all orders';
});
```

**Variation CSS code**

```css
.hero .cta-button {
  background-color: #e4002b;
}
```

**Variation Reset JS code**

```js
document.querySelectorAll('.hero h1[data-original-text]').forEach((headline) => {
  headline.textContent = headline.dataset.originalText;
  delete headline.dataset.originalText;
});
```

The CSS needs no reset. ABlyft removes it together with the experiment.

## Good to know

* **Errors are caught.** If your code throws an error, ABlyft logs it (in [debug mode](https://docs.ablyft.com/developers/debugging/preview-and-live-log/#debug-mode))
  and continues with the next step. A broken variation does not stop other experiments.
* **Minification.** If **Minify JavaScript** is enabled in the [snippet settings](https://docs.ablyft.com/developers/installation/snippet-settings/#minify-javascript),
  your JavaScript is minified when published. If the code contains a syntax error, ABlyft publishes it unchanged.
* **DOM observers ignore your changes.** While your code runs, DOM changes it makes are not reported to
  [`domChanged`](https://docs.ablyft.com/developers/reference/javascript-api/tools/#domchanged) callbacks.
* **Code runs again on re-runs.** After [`ablyft.reInit()`](https://docs.ablyft.com/developers/application-integration/spa-navigation/) or a page trigger, code can run
  again. Reset JS is run first (only with **Use SPA features**).

## Troubleshooting

* **Nothing changes:** check the browser console in debug mode for errors from your code. Check that your CSS selector
  exists on the page, and that the experiment is on an active page.
* **Code runs on pages where it should not:** project-level code runs on every page load. Move page-specific code to an
  experiment, or wrap it in a condition such as `if (location.pathname.startsWith('/checkout')) { … }`.
* Find more help in [Debugging](https://docs.ablyft.com/developers/debugging/).

## Next steps

- [Dynamic content](https://docs.ablyft.com/developers/application-integration/dynamic-content/): Wait for elements that appear later.
- [Tools](https://docs.ablyft.com/developers/reference/javascript-api/tools/): All helper functions for your code.
- [Custom goals](https://docs.ablyft.com/developers/tracking-and-events/custom-goals/): Trigger goals from your code.

