# Hugo and Jekyll

Add ProductLense to a Hugo or Jekyll static site by placing the script in the head partial or include that every page uses.

Static site generators build every page from shared templates. Put the ProductLense script in the template that renders the `<head>`, and every generated page carries it. Neither generator needs a plugin.

## Add the script

Replace `SITE_ID` with the id from Settings → Sites in the ProductLense dashboard.

### Hugo

Most themes include a head partial. Override it in your own `layouts/partials` folder, or add a new partial and call it from `baseof.html`:

```html title="layouts/partials/productlense.html" {1-2}
<script>window.productlense=window.productlense||function(){(window.productlense.q=window.productlense.q||[]).push(arguments)}</script>
<script defer data-site="SITE_ID" src="https://api.productlense.app/a.js"></script>
```

```html title="layouts/_default/baseof.html" {4}
<!doctype html>
<html lang="{{ .Site.Language.Lang }}">
  <head>
    {{ partial "productlense.html" . }}
  </head>
  <body>
    {{ block "main" . }}{{ end }}
  </body>
</html>
```

To skip tracking while you run `hugo server`, wrap the call in `{{ if hugo.IsProduction }} … {{ end }}`.

### Jekyll

Add the tags to the head include of your theme. If the theme ships it from a gem, copy `_includes/head.html` into your site first, then edit the copy:

```html title="_includes/head.html" {3-4}
<meta charset="utf-8">
<title>{{ page.title }}</title>
<script>window.productlense=window.productlense||function(){(window.productlense.q=window.productlense.q||[]).push(arguments)}</script>
<script defer data-site="SITE_ID" src="https://api.productlense.app/a.js"></script>
```

To skip tracking during `jekyll serve`, wrap the tags in `{% if jekyll.environment == "production" %} … {% endif %}` and build with `JEKYLL_ENV=production`.

## Custom events

Static sites usually have no signed-in users, so `identify` is not needed. To record a click, add a small script after the ProductLense tags:

```html
<script>
  document.querySelector('#download')?.addEventListener('click', () => {
    window.productlense('event', 'Download clicked', { file: 'guide.pdf' });
  });
</script>
```

Links to PDF and other files are already recorded as downloads; see [outbound links and downloads](/docs/track/outbound-links-and-downloads). See [custom events](/docs/track/custom-events) for naming rules.

## Verify your installation

1. Build the site for production, deploy it, then open it in a normal browser window.
2. Open the Live page in the ProductLense dashboard. Your visit appears within a few seconds.
3. In the browser's developer tools, the Network tab shows a `POST` to `https://api.productlense.app/api/e` with status `204`. View the page source: both ProductLense tags are in the `<head>`.

`hugo server` and `jekyll serve` run on `localhost`, where nothing is sent unless you add `data-dev="true"` to the tag. Ad blockers in your own browser may block the request. If the visit does not appear, follow [Verify your installation](/docs/install/verify).
