# Install a widget

> Copy the code from a widget's Install tab to put the widget on your page and check its token on your server, and preview the widget before it goes live.

Source: https://www.coritan.com/docs/wicket/install-a-widget/

In the dashboard:

- /dashboard/security/wicket/…/install: https://www.coritan.com/dashboard/security/wicket

Installing a widget has two parts. A page shows the widget, and the widget puts a token in the form. Your server then sends the token to Wicket with your secret key before it accepts the form. The **Install** tab of the widget has the code for both, with your site key already in it.

## Before you begin

- [Add a widget](/docs/wicket/add-a-widget/) first. Open it from **Security**, then **Open Wicket**, and select its **Install** tab.
- The hostname of the page that shows the widget must be one of the widget's hostnames ([Change a widget's settings](/docs/wicket/widget-settings/#hostnames)). A page on another hostname gets no challenge.
- Have the widget's secret key ready. The tab never shows it, because we show it once, when you add the widget and when you rotate it. If you do not have it, [rotate the secret key](/docs/wicket/widget-settings/#rotate-the-secret-key).

## Add the widget to your page

1. Under **Add the widget to your page**, select the copy button on the **HTML** block.
2. Paste the `<script>` line once in the page. It loads the widget with `async defer`, so it does not hold the page up.
3. Paste the `<div>` with the class `wicket-widget` inside the form, where the check should appear. Its `data-sitekey` is the widget's site key.

For a Managed or Non-interactive widget the `<div>` carries `style="min-height: 65px"`, or `140px` when the widget's size is **Compact**. It keeps room for the widget so the page does not jump when it loads. For an Invisible widget the `<div>` carries `data-appearance="interaction-only"` and no `min-height`, so it takes no room on the page ([Invisible widgets](/docs/wicket/add-wicket-to-your-site/#invisible-widgets)).

When your Content-Security-Policy forbids inline styles, move the `min-height` into a stylesheet and leave the `style` attribute off ([Reserve the widget's height](/docs/wicket/add-wicket-to-your-site/#reserve-the-widgets-height)).

The widget fills a hidden field named `wicket-response` with a token when the visitor passes, and the browser sends it with the form like any other field.

## Check the token on your server {#check-the-token-on-your-server}

Never trust the form on the strength of the widget alone, because a script can send a form without loading the widget. Your server asks Wicket whether the token is real.

1. Under **Check the token on your server**, choose your language: **curl**, **Node**, **Python**, **PHP** or **Go**.
2. Copy the code into the handler that receives the form. It reads the `wicket-response` field, sends it to the verify address with your secret key, and reads the answer.
3. Keep the secret key in an environment variable named `WICKET_SECRET_KEY` on your server, never in a page or a repository.
4. Refuse the form when the answer's `success` is `false`.

The answer is JSON. `success` is `true` or `false`, and when it is `false` the `error-codes` list says why ([Error codes](/docs/wicket/verify-tokens/#error-codes)). A token works once and for 300 seconds. When a visitor takes longer, the widget gets a new one by itself.

Until your server makes this call, the widget's **Analytics** tab says **Your server is not verifying tokens**, and the list marks the widget as needing attention once at least 20 checks passed in 24 hours without one ([Read a widget's analytics](/docs/wicket/widget-analytics/#tokens-verified)).

## Draw the widget with JavaScript

To draw the widget from your own script, use **Or draw it with JavaScript** instead of the **HTML** block. The script address ends in `?render=explicit&onload=onWicketLoad`, and the callback you pass to `wicket.render` receives the token, for a page that builds its forms in JavaScript. The `<div>` carries the same `min-height` as the HTML block.

[Add Wicket to your site](/docs/wicket/add-wicket-to-your-site/) covers explicit rendering, several widgets on one page and single-page apps, and [Widget options](/docs/wicket/widget-options/) lists every option the widget takes.

## Try the test keys

The **Test keys** card lists site keys and secret keys that work on any hostname, are never counted and never touch a widget of yours. Use them in development, and in automated tests that submit a form. [Test keys](/docs/wicket/test-keys/) says what each one does.

## Allow the widget in a Content Security Policy

If your site sets a Content Security Policy, add the two lines under **Content Security Policy** to it. They allow the widget's script and the frame it draws. The tab shows the addresses your widget uses, so copy them from there ([Allow Wicket in a Content Security Policy](/docs/wicket/add-wicket-to-your-site/#allow-wicket-in-a-content-security-policy)).

## Preview the widget

The **Preview** card draws the widget as a visitor sees it, with the test site key that passes, so you can look at it before your page has one. It loads the same script your page will. When a browser extension or a policy of your own blocks the script, the card says `The preview could not load`.

## Result

The page shows the widget, a visitor passes it, and your server's check answers `success: true`. The widget's **Analytics** tab then counts the challenge and the verified token.

## Troubleshooting

The widget shows an error about the site key or the hostname
: The browser's console names the cause. Either the site key is not a widget's, or the page's hostname is not one of the widget's hostnames. Add it on the **Settings** tab.

The verify call answers `invalid-input-secret`
: The server sends a secret key that no widget has, or that you rotated with **Stop the old key now**. Put the current secret key in `WICKET_SECRET_KEY`.

The verify call answers `invalid-input-response`
: The token is another widget's, or it is `WICKET.DUMMY.TOKEN` from a test site key. Use the widget's own site key on the page.

The verify call answers `timeout-or-duplicate`
: The server verified the same token twice, or took more than 300 seconds. Verify once for each submission.

[Troubleshoot Wicket](/docs/wicket/troubleshooting/) lists what each message in the widget means.

## Related

- [Add a widget](/docs/wicket/add-a-widget/)
- [Change a widget's settings](/docs/wicket/widget-settings/)
- [Verify a token on your server](/docs/wicket/verify-tokens/)
- [Manage widgets with the API](/docs/wicket/manage-widgets-with-the-api/)

## Next steps

- [Read a widget's analytics](/docs/wicket/widget-analytics/) to see that challenges and verified tokens arrive.
- [Test keys](/docs/wicket/test-keys/) to test a failing check and a spent token.
- [Move from Cloudflare Turnstile to Wicket](/docs/wicket/migrate-from-turnstile/) if the page uses Turnstile now.
