# Add search to any site

> One script tag adds Findlane search to your site's own search box: products as visitors type, with photos and prices, and a results view with filters.

The Findlane search widget answers your site's own search box, on any site: WordPress, a static site, or a store on another platform. It's the widget the [Shopify app](/docs/shopify.md) uses, loaded with one script tag. It searches one index of products, filled by a [product feed](/docs/feeds.md) or by the [API](/docs/records.md).

## Set it up

1. **Allow your site.** On the index's **Public access** page, add your site's origin, such as `https://www.example.com`, and copy the public ID. See [Public IDs and allowed origins](/docs/security.md#public-ids-and-allowed-origins).
2. **Add the script tag** to every page with a search box:

```html
<script
  src="https://cdn.findlane.dev/widget/1.0.0/findlane-search.js"
  integrity="sha384-OSAGPC+6pkAmjCXQqeS+ntZIcnnoNA1cEHYv646ZHY9T0GhZQt0EqqXGolloyD/K"
  crossorigin="anonymous"
  defer
  data-public-id="pub_your_public_id"
></script>
```

3. **Try it.** Type in your site's search box. Products appear as you type, and a misspelled word still finds them.

The `integrity` hash makes the browser check the file before it runs it. A released version never changes; a new one has a new address and hash. [`widget/versions.json`](https://cdn.findlane.dev/widget/versions.json) lists every release with its hash.

## On your site

- **As you type,** a list shows the best matches with photos, brands, and prices, and above them searches to pick. Arrow keys move through it, and Enter opens the selected product or runs the selected search.
- **In an empty search box,** the visitor's recent searches and your index's popular searches show. Recent searches stay in the visitor's browser and are never sent to Findlane.
- **Pressing Enter, or choosing See all results,** opens Findlane's results over the page: every match, filters by brand and product type, sorting by price, and more results. The browser's back button closes it.
- **Your rules' banners** show among the results, and a search a rule [redirects](/docs/settings.md#what-rules-do) goes to its page.

The widget's styles are kept apart from your site's, so neither changes the other. It uses your site's font.

### Which search box

The widget answers an input that matches `input[name="q"]`, `input[name="s"]` (WordPress), or `input[type="search"]`. If your search box is none of these, name it with a CSS selector:

```html
data-input="#header-search"
```

Enter in a search box outside a form runs the search too, unless `data-replace` is `false`: then your own code handles it.

## Settings

Settings are data attributes on the script tag.

| Attribute                                        | What it does                                                                                                                              |
| ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `data-public-id`                                 | The index's public ID. Required.                                                                                                          |
| `data-currency`                                  | The prices' currency, such as `EUR`. Without it, each record's `currency`, or US dollars.                                                 |
| `data-input`                                     | A CSS selector for your search box.                                                                                                       |
| `data-limit`                                     | Products shown as you type: 3 to 10. Default 6.                                                                                           |
| `data-accent`                                    | The color of matched words, links, and checkboxes, as a hex color such as `#0a7d4f`.                                                      |
| `data-placeholder`                               | Text shown in the empty search box. Leave it out to keep yours.                                                                           |
| `data-results`                                   | `false`: searches go to your own search page instead of Findlane's results. A search form goes to its own address; See all results, a picked search, and a box outside a form go to `data-search-url`. |
| `data-search-url`                                | Your search page. Default `/search`, with the search added as `?q=`. Write `{query}` where the search goes, such as `/?s={query}` on WordPress. |
| `data-replace`                                   | `false`: your site's own suggestions also run.                                                                                            |
| `data-suggestions`, `data-popular`, `data-recent` | `false` turns off searches suggested as visitors type, popular searches, or recent searches.                                             |
| `data-product`                                   | On a product page, the product's `objectID`. The page sends a view of it.                                                                 |
| `data-consent`                                   | `granted` when the visitor allows analytics. See [Consent](#consent).                                                                    |
| `data-visitor-ids`                               | `true` to send [visitor IDs](#visitor-ids) with events.                                                                                   |

## What it shows

Each product in the list and the results shows these fields of its record:

| Field                | Shown as                                                                                              |
| -------------------- | ----------------------------------------------------------------------------------------------------- |
| `title`              | The product's name, with the matched words highlighted.                                               |
| `url`                | The product's page. A full address, such as `https://www.example.com/p/trail-jacket`, or a path on your site, such as `/p/trail-jacket`. |
| `image`              | The photo, as it is at its address.                                                                   |
| `price`              | The price, as a number. With a higher `price_max`, it reads "From" the price.                         |
| `compare_at_price`   | The price before a sale, struck through.                                                              |
| `currency`           | The prices' currency, such as `EUR`, unless `data-currency` says otherwise.                           |
| `brand` or `vendor`  | The brand, under the name. `vendor` comes first when a record has both.                              |

Other fields aren't shown, and `available` isn't used: a sold-out product shows like any other. A field that isn't shown still finds products if the index's [settings](/docs/settings.md#searchable-fields) search it, such as a `description`.

The results' filters are the `brand`, `vendor`, and `product_type` fields that are [facets](/docs/settings.md#facets-and-filters) in the index's settings. Sorting by price uses the index's sorts with the IDs `price_asc` and `price_desc`, which the [suggested settings](/docs/settings.md#suggested-settings) for products add.

## Consent

The widget sends no events until your site says the visitor allows analytics. Events are clicks on products, on suggested searches, and on banners, and product page views; they show on the index's **Events** and **Analytics** pages. Searches are sent as visitors type, with no cookie or ID.

If the page knows as it loads, because the visitor answered your banner on an earlier page or your site needs no banner, add `data-consent="granted"` to the script tag.

When the visitor answers your cookie banner, call `findlane.consent` from its callback:

```js
// They allow analytics.
window.findlane?.consent(true)

// They don't, or they withdraw it.
window.findlane?.consent(false)
```

`window.findlane` is there once the widget's script has run. With `defer`, that's just before the page's `DOMContentLoaded` event, so an inline script after the tag is too early: call it from your banner's callback, or after that event. A product page's view waits, and is sent when they allow analytics. `consent(false)` stops events and deletes the visitor IDs from the browser. The answer lasts for the page; on the next page, the script tag or your banner says it again.

### Visitor IDs

With `data-visitor-ids="true"`, and **Link each shopper's events** on the index's **Events** page, events carry random IDs for the browser and the visit, which link one visitor's views and clicks. They're made only once the visitor allows analytics. Getting consent is up to your site: turn them on only if your banner covers analytics, or your visitors don't need one. See [Visitor IDs](/docs/events.md#visitor-ids).
