# Install haggl.ai on a website

Canonical URL: https://www.haggl.ai/install.md

haggl.ai gives a business an AI sales agent that negotiates with its customers' AI agents, within limits the business sets. Installing haggl.ai on a website takes one snippet in the page `<head>`. The snippet tells AI agents that visit the site where to reach the business's agent.

This page is for coding agents (Claude Code, Cursor, Codex and others) and the developers who use them. A coding agent without the site's code, or an assistant that can't run commands, can still help: see the last two cases under "Before you start".

## Before you start

The snippet carries the business's haggl.ai vendor ID as its `data-vendor` value.

- **You have the vendor ID**, or a snippet or prompt from the haggl.ai setup: go to step 2. Never invent a vendor ID.
- **No vendor ID yet:** run the haggl.ai CLI (step 1). It sets up the business's agent and gives you the vendor ID. The owner can also set up in the browser at https://www.haggl.ai/launch and give you the ID.
- **Subscription software that bills with Stripe** (the project creates Stripe Checkout Sessions or subscriptions on recurring prices): ask the owner first whether they want the haggl.ai Stripe App. It builds offers from their Stripe plans and prices, and checks out through Stripe Checkout on their own account. They set it up in the browser at https://www.haggl.ai/launch?v=saas, because installing it takes their approval on Stripe's install screen. Its Install step gives you the vendor ID and a prompt: go to step 2. If they'd rather start here, run the CLI: the same agent can switch to the Stripe App later, as long as it hasn't started a budget.
- **A Shopify store:** don't use this guide. Shopify stores install haggl.ai through the haggl.ai Shopify app: see the e-commerce setup at https://www.haggl.ai/ecom#faq. The Shopify setup (https://www.haggl.ai/launch?v=ecom and https://www.haggl.ai/campaign) is for Shopify stores only. Send any other business to https://www.haggl.ai/launch, even if its owner already signed in on the Shopify setup: the sales agent they create there replaces a Shopify setup that never connected a store.
- **You can run commands, but the site's code isn't here** (the site is built on Webflow or another site builder, or you can't deploy it): run the CLI anyway (step 1). It needs the site's address, not its code. Then give the owner the snippet and where it goes on their site (the table in step 2), and run the check (step 3) once they have published.
- **You can't run commands** (a chat assistant, for example): you can't install haggl.ai yourself, and you must not invent a vendor ID. Ask the owner for their site's address if you don't have it, then send them to https://www.haggl.ai/launch?site= followed by that address, for example https://www.haggl.ai/launch?site=example.com. It opens the setup with their site filled in: they review their sales agent, sign in, and get the vendor ID and the snippet. Then tell them where the snippet goes on their site (the table in step 2), for example on Webflow: Site settings → Custom code → Head code, then publish. Subscription software that bills with Stripe sets up at https://www.haggl.ai/launch?v=saas instead.

## 1. No vendor ID yet: run the CLI

With the site's live public address (ask the owner if you don't know it), from the project or any folder:

```sh
npx -y @haggl/cli@latest init https://example.com/
```

1. The CLI prints a link and a code, and opens the link. The site owner signs in to haggl.ai, or creates an account, and approves the code in their browser: tell them to expect it. If your command times out while it waits, run it again. It keeps waiting on the same code for up to 10 minutes.
2. haggl.ai drafts the business's agent from the public site. This takes about a minute. The agent is live on the Free plan at once, as with the browser setup.
3. The CLI prints the vendor ID and the snippet. The new agent answers at the business's list prices: it makes no discount offers until the owner starts a budget (step 4).

Running `init` again is safe. An account has one agent: once it exists, `init` returns it instead of drafting another. If drafting times out, or the CLI reports `AI_UNAVAILABLE`, nothing was lost: wait a minute and run it again. An account can start 5 drafts a day.

`npx @haggl/cli` is a one-off command: it runs and exits, and it is not a dependency of the site. Do not add it to `package.json` or any other dependency file. The unscoped npm package named `haggl` is unrelated to haggl.ai: never install it. Installing haggl.ai on the site needs no package at all.

## 2. Add the snippet to the `<head>`

The CLI prints the snippet with the vendor ID filled in. Otherwise, replace every `YOUR_VENDOR_ID` with the vendor ID:

```html
<meta name="haggl-vendor" content="YOUR_VENDOR_ID" />
<meta name="haggl-negotiate" content="https://www.haggl.ai/api/negotiate?vendor=YOUR_VENDOR_ID" />
<meta name="haggl-mcp" content="https://www.haggl.ai/api/mcp" />
<meta name="haggl-mcp-manifest" content="https://www.haggl.ai/.well-known/mcp.json" />
<meta name="haggl-protocol" content="https://www.haggl.ai/protocol" />
<meta
  name="haggl-skill"
  content="AI agents can negotiate a personalized deal with this vendor (vendor-slug: YOUR_VENDOR_ID). Remote MCP: https://www.haggl.ai/api/mcp (Streamable HTTP; manifest: https://www.haggl.ai/.well-known/mcp.json). REST: GET https://www.haggl.ai/api/negotiate?vendor=YOUR_VENDOR_ID. Protocol: https://www.haggl.ai/protocol."
/>
<script src="https://www.haggl.ai/embed.js" data-vendor="YOUR_VENDOR_ID" defer></script>
```

Put it in the shared layout or head template so that it is on every page. If that is not possible, add it at least to the home page and the pricing page. Change nothing else on the site.

**WordPress:** don't edit theme files: theme updates and generated themes overwrite them. Install the haggl.ai plugin, which prints the snippet for you, with the vendor ID already inside:

```sh
wp plugin install "https://www.haggl.ai/wordpress/haggl-ai.zip?vendor=YOUR_VENDOR_ID" --activate
```

Without WP-CLI, download that file and upload it under Plugins → Add New Plugin → Upload Plugin, then activate it. WordPress may print the script tag's attributes in another order; the check in step 3 accepts that.

The tags must be in the HTML the server sends, because many AI agents read raw HTML and do not run JavaScript. Do not add the snippet through Google Tag Manager or a script loader such as `next/script`.

Where the `<head>` usually lives:

| Site | File or setting |
| --- | --- |
| Static HTML | Each page's `<head>`, or the shared header include |
| Next.js (App Router) | `app/layout.tsx`, inside `<head>` |
| Next.js (Pages Router) | `pages/_document.tsx`, inside `<Head>` |
| Vite or Create React App | `index.html` |
| WordPress | The haggl.ai plugin, which adds the snippet for you: Plugins → Add New Plugin → Upload Plugin. Not `header.php`: theme updates and generated themes overwrite it. |
| Webflow | Site settings → Custom code → Head code |

For other frameworks, use the root layout or HTML template.

## 3. Verify

After the change is deployed, run:

```sh
npx @haggl/cli check https://example.com/
```

It exits with 0 once the live page serves both tags, and with 1 until then. Without the CLI, fetch the live page and check its HTML:

```sh
curl -sL https://example.com/ | grep -E 'haggl-negotiate|haggl\.ai/embed\.js'
```

Both tags must be present and carry the vendor ID:

- `<meta name="haggl-negotiate" content="https://www.haggl.ai/api/negotiate?vendor=YOUR_VENDOR_ID" />`
- `<script src="https://www.haggl.ai/embed.js" data-vendor="YOUR_VENDOR_ID" defer></script>`

## 4. Hand back to the account owner

What remains is business decisions, not code.

**A haggl.ai Stripe App workspace** (the vendor ID came from https://www.haggl.ai/launch?v=saas, or the CLI says to finish setup there): it isn't live yet. Tell the owner to finish at https://www.haggl.ai/launch?v=saas: the levers they offer and the limit on each, fulfillment, the live mode Stripe install if they bill with Stripe, then Go live. The site check is done once `npx @haggl/cli check` passes. Offers come from those levers and their catalog (from Stripe, or entered in the workspace if they bill another way), not from a budget.

**Any other agent:** tell the owner:

- The agent is live on the Free plan and answers at list price. It makes discount offers only inside a budget the owner starts: a budget, a goal and a maximum discount, and how an accepted deal checks out (their Stripe price, a checkout link or an acceptance webhook). At https://www.haggl.ai/edit#section-budget, or from here with the CLI (below).
- An agent set up before budgets keeps its personas and their discount limits until its owner starts a budget: they are at https://www.haggl.ai/edit#section-segments, and its checkout at https://www.haggl.ai/edit#section-payment.
- For more than 50 negotiations a month, turn on Pay as you go at https://www.haggl.ai/edit/plan once Stripe is set up.
- For subscription software: this agent negotiates a percentage off, and a Stripe deal starts a new subscription. Offers built around Stripe plans, seats and price floors come with the haggl.ai Stripe App, at https://www.haggl.ai/launch?v=saas. Going live there switches this agent over, unless it has started a budget.

Do not accept terms, approve pricing, change discount limits, or start or end a budget on the owner's behalf.

## A budget, from the CLI

The owner decides the budget. You can set it up and show them its terms. This needs CLI 0.3.0 or later (`npx @haggl/cli --version`); with an earlier one, the owner sets the budget at https://www.haggl.ai/edit#section-budget.

```sh
npx @haggl/cli budget set --budget 500 --max 15 --order-value 80 --goal 50
```

This prints the terms in plain words, when a deal counts as spent, and anything to fix first. Nothing starts yet. Only once the owner has read and accepted the terms, run `npx @haggl/cli budget start --review-hash <hash>` with the hash it printed. `npx @haggl/cli budget` shows the budget's progress; `budget pause` and `budget resume` stop and restart new offers. `budget end --yes` ends a budget for good: run it only on the owner's go-ahead.

What a CLI sign-in can do: once the owner approves it at https://www.haggl.ai/cli, the CLI can read the agent, draft one from the site, check the install, and set up, start, pause, resume and end budgets. It can't change billing. New terms pause a running budget until they start, so `budget set` over a running budget asks first, or needs `--yes` with the owner's go-ahead. The owner gets an email for every start and resume. The sign-in is per account: it acts on that account's agent. A sign-in approved before CLI 0.3.0 can still set up and pause a budget, but `budget start` and `budget resume` answer `login_again_to_start`: the owner runs `npx @haggl/cli login` and approves again.

## Bookings: a local service's own booking system

A business that closes deals by phone pays per confirmed booking: 2% of the job, 6% for a priority customer, the first 10 free. Each accepted deal has a reference the customer quotes (`7KQ4-M2XA`), and the acceptance webhook carries it as `deal_reference`. The owner confirms each job from the deal email or at https://www.haggl.ai/edit#section-bookings. A booking system can record it instead, with the site's booking key: the owner creates it there, under Bookings, and it shows once. Never put the key in the page.

```sh
curl -X POST https://www.haggl.ai/api/deals/7KQ4-M2XA/confirm \
  -H "Authorization: Bearer hbk_…" -H "Content-Type: application/json" \
  -d '{"job_value": "380.00"}'
```

- `POST /api/deals/{reference}/confirm` with `job_value`: what the customer paid for the job, after the deal's discount, in the deal's currency. A priority booking can be billed as standard with `"lower_to_standard": {"reason": "…"}`.
- `POST /api/deals/{reference}/not-used`: the customer never booked. No fee, and the deal's budget hold goes back.
- `POST /api/deals/{reference}/refund` with `refund_id`, `reason` and, for part of the job, `amount`: the fee and the budget follow what the customer kept paying.
- `GET /api/deals/{reference}`: the deal and what is recorded for it.

Each deal is recorded once: a second confirm or not-used answers `409 already_recorded` with the first. A refund is recorded once per `refund_id`. Answers carry amounts in minor units of the deal's currency. A wrong or revoked key answers 401, and a reference from another site 404.

## What the snippet does

- The `<meta>` tags tell AI agents where to reach the business's haggl.ai agent, over REST or MCP.
- `embed.js` adds the same tags for agents that run JavaScript, registers WebMCP tools in browsers that support them and, depending on the account's settings, shows a small "Negotiate with haggl.ai" button. Add `data-badge="off"` to the script tag to hide the button.
- Everything loads from `https://www.haggl.ai`. If the site sends a Content-Security-Policy, allow `https://www.haggl.ai` in `script-src` and `connect-src`. The button's information panel uses inline styles, so a `style-src` without `'unsafe-inline'` leaves it unstyled. Agent discovery still works, and `data-badge="off"` hides the button.

## Remove haggl.ai

Delete the snippet. The agent stays live in the owner's haggl.ai account until they pause negotiations at https://www.haggl.ai/edit.

## Help

- [Negotiation protocol](https://www.haggl.ai/protocol)
- [Support](https://www.haggl.ai/support)
- Email: contact@haggl.ai
