> For the complete documentation index, see [llms.txt](https://docs.limecall.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.limecall.com/callback/install-with-javascript.md).

# Install with JavaScript

Add the widget to any website you can edit the HTML of.

This is the universal method. It works on any site where you can add a script tag.

Once it is in, visitors see a launcher in the corner of every page it loads on:

## Get your snippet

1. Open **Widget** in the dashboard.
2. Go to the **Embed** tab.
3. Copy the snippet shown. It contains your account's widget key — it is specific to you, not a generic tag.

## Add it to your site

Paste the snippet immediately before the closing `</body>` tag. It looks like this:

```html
<body>
  <!-- your page content -->

  <!-- LimeCall widget -->
  <script src="https://dashboard.limephone.io/callback-widget.js"
          data-key="YOUR_WIDGET_KEY"
          data-api="https://dashboard.limephone.io"></script>
</body>
```

{% hint style="info" %}
Copy the real snippet from the **Embed** tab rather than retyping the example above. Yours carries your own widget key, and the Embed tab is always the current, correct form.
{% endhint %}

If you chose the **Inline** display style, the snippet also includes a mount point. Put it where the widget should appear:

```html
<div id="limephone-callback"></div>
```

## Do not add your own `data-` attributes

The snippet deliberately carries only `data-key` and `data-api`. Every other setting travels in the configuration the widget fetches at load time, which is why changes you make on the Widget page take effect on your live site without you touching the code again.

Attributes **override** that configuration. Adding, say, `data-mode="bubble"` freezes the display style at the moment you pasted it — after which changing Display style in the dashboard updates the preview, saves fine, and does nothing at all to your site.

{% hint style="warning" %}
This is the most confusing failure the widget has, because nothing appears broken. If a setting refuses to take effect on your site but works in the preview, view your page source and check for a `data-` attribute pinning it.
{% endhint %}

## Put it on every page

The widget must be on every page where you want it to appear. Adding it to your homepage alone is the single most common installation mistake.

Nearly every site has a shared template that renders on all pages — a footer include, a layout file, a base template. Add the snippet there once, rather than page by page:

| Stack           | Where to put it                                     |
| --------------- | --------------------------------------------------- |
| Static HTML     | The shared footer include, if you have one.         |
| Next.js         | `app/layout.tsx`, or `pages/_document.js`.          |
| Nuxt / Vue      | `app.vue` or `nuxt.config` under `app.head.script`. |
| Laravel / Rails | The base layout template.                           |
| Django          | Your `base.html`.                                   |

If you want it on *some* pages only, install it everywhere and then restrict it with [Display rules](/callback/display-rules.md). That is far easier to maintain than editing templates.

## Verify it worked

1. Open your site in a private/incognito window — this avoids cached copies and any earlier dismissal of the widget.
2. Wait two or three seconds. The widget loads after your page content, so it appears last.
3. Open your browser's developer console and check for errors mentioning `limecall`.

If nothing appears, see [The widget is not showing](/troubleshooting/widget-not-showing.md).

## Content Security Policy

If your site sets a CSP header, allow the host in your snippet — the same value appears in both `src` and `data-api`, and the widget needs to load from it *and* call it:

```
script-src  https://dashboard.limephone.io
connect-src https://dashboard.limephone.io
```

Without this the browser blocks the script silently. The only sign is a CSP violation in the console.

## Next

Once it is installed, the widget can be driven from your own JavaScript — opened on a button click, or fired from a form you already have:

* [JavaScript API](/callback/javascript-api.md)
* [Connect your own form](/callback/connect-your-own-form.md)
