Documentation

Setting up Bellhop

Everything you need to take Bellhop from a fresh account to live, intent-driven personalization on your website. No code beyond a single script tag — the rest happens in your dashboard and your site editor.

≈ 15 minutes to first personalization For marketers & site owners

Overview

Bellhop rewrites your existing website — in place — to match what each visitor actually came for. When someone arrives from a Google Ads search for “social scheduling for agencies,” Bellhop swaps your generic hero for copy that speaks to agencies, grounded in your own knowledge base so every claim stays true. One site, rewritten per visitor — not a hundred landing pages to build and maintain.

Setting it up is four moving parts:

  1. The script — one line in your site’s <head> that loads the Bellhop runtime.
  2. Zones — the elements you let Bellhop personalize, tagged with a simple attribute.
  3. Intent — where Bellhop learns why a visitor came (your Google Ads account, or rules you define).
  4. Content — the variations Bellhop applies, written by the AI from your knowledge base or by you.
Private beta. Bellhop is invite-only while we tune it for paid-search teams. When you join, the team sets up your workspace and shares your dashboard login and site key — the one value you’ll need below. Not in yet? Request early access.

Before you begin

You’ll move fastest if you have these ready:

  • A live website you can edit. Bellhop works on any site where you can add a script tag and custom attributes — Webflow, WordPress, Framer, Shopify, or hand-coded HTML.
  • Editor access to that site. You’ll add one script tag and a few attributes, then publish.
  • Your Bellhop site key (looks like pub_8s1f3k9a). It’s on your site’s settings page in the dashboard.
  • Optional — a Google Ads account. This is where Bellhop reads visitor intent automatically. You can also define intent manually to start.
  • Optional — a CRM (HubSpot). Lets Bellhop greet known accounts and sync results back.

Everything except the live website and site key is optional — Bellhop degrades gracefully and you can add sources later without touching your site again.

How Bellhop works (60-second version)

It helps to picture the round trip before you wire it up:

  1. A visitor lands on your page. The Bellhop script reads the page’s zones and the URL (including any Google Ads click parameters).
  2. It asks Bellhop’s edge: “Given this visitor’s intent, what should these zones say?” The answer comes back in well under 150 ms, from Cloudflare’s edge, with zero third-party calls.
  3. If a matching variation exists, the script applies it — swapping text or attributes on just the zones you tagged. Everything else on your page is untouched.
  4. The result is recorded so your experiments learn which variation performs best.

Because the runtime is ~3.6 KB and reads from the edge, visitors don’t see a flash or a slowdown. You stay in control of exactly which elements can change.

Step 1

Create your workspace & add your site

Sign in to the dashboard at app.bellhop.marketing with the Google account the team invited. Inside your workspace:

  1. Go to Sites → Add site.
  2. Give it a name (e.g. Marketing site) and enter your primary domain (e.g. www.example.com).
  3. Save. The dashboard generates your site key — a public identifier like pub_8s1f3k9a.
Copy your site key now. You’ll paste it into the script tag in Step 2. It’s safe to expose publicly — it only identifies your site, it grants no access.
Step 2

Install the Bellhop script

Add this single tag to the <head> of every page you want to personalize. Replace the key with your own from Step 1.

<script
  src="https://cdn.bellhop.marketing/runtime.js"
  data-bellhop-key="pub_YOUR_SITE_KEY"
  data-bellhop-api="https://api.bellhop.marketing"
  defer
></script>

Where to paste it, by platform

  • Webflow — Project Settings → Custom Code → Head Code, then republish.
  • WordPress — your theme’s header, or a “header scripts” plugin (e.g. WPCode), in the <head> slot.
  • Framer — Site Settings → General → Custom Code → Start of <head> tag.
  • Shopifytheme.liquid, just before </head>.
  • Hand-coded HTML — paste directly into your <head>.
  • Google Tag Manager — a Custom HTML tag firing on All Pages, set to fire as early as possible.

Script attributes

AttributeRequiredWhat it does
srcYesLoads the Bellhop runtime bundle.
data-bellhop-keyYesYour site key from the dashboard.
data-bellhop-apiYesThe Bellhop edge endpoint. Use the value shown on your site’s settings page.
data-bellhop-debugNoAdd it (no value) to log Bellhop’s decisions to the browser console. Leave it off in production.
deferRecommendedLets the page render first; Bellhop applies as soon as the DOM is ready.

Publish your site after adding the tag. In the next step you’ll tell Bellhop which elements it’s allowed to touch — until you do, the script loads but changes nothing.

Step 3

Mark up your zones

A zone is any element you allow Bellhop to personalize. You opt elements in explicitly by adding a data-bellhop-zone attribute with a name you choose. Nothing without this attribute is ever changed.

<h1 data-bellhop-zone="hero.h1">Greet every visitor by name</h1>
<p  data-bellhop-zone="hero.subhead">One site, rewritten per visitor.</p>
<a  data-bellhop-zone="hero.cta" href="/signup">Get started</a>

Naming your zones

  • Use lowercase, dot-separated names that describe the spot: hero.h1, hero.subhead, hero.cta, pricing.h1, proof.headline.
  • Keep names stable — they’re how your dashboard content maps to the page. Renaming a zone orphans its content.
  • Start small. The hero headline, sub-headline, and primary CTA are usually the highest-impact three.

Adding the attribute in a visual builder

In Webflow, for example:

  1. Select the element in the Designer.
  2. Open Element Settings (the gear icon) and scroll to Custom Attributes.
  3. Click + and add name data-bellhop-zone, value hero.h1 (or your chosen name).
  4. Repeat for each element, then republish.

Most builders (Framer, WordPress block editor, Shopify) have an equivalent “custom attribute” or HTML-attributes field. In hand-coded HTML you just add the attribute inline.

Tip. Register the same zone names in your dashboard under Sites → Zones so the AI knows what each one is (a headline, a button label, a paragraph). That context makes generated copy noticeably better.
Step 4

Connect your intent sources

Intent is why a visitor came. Bellhop reads it primarily from your Google Ads traffic — the campaign, ad group, and keyword behind each click — and clusters those into named intents like agency-scheduling or small-biz-social.

Link Google Ads (recommended)

  1. In the dashboard, go to Integrations → Google Ads and connect your account.
  2. Bellhop reads your campaign and keyword structure and proposes intent clusters. Review, rename, and approve them.
  3. Make sure your Ads final URLs or tracking template pass the standard click parameters (gclid, and ideally campaignid, adgroupid). Bellhop uses these to resolve intent on arrival.

Or define intent manually

No Google Ads, or want to test first? Create intents by hand under Intents → New intent and trigger them with a URL parameter:

https://www.example.com/?_intent=agency-scheduling

This forces a specific intent for that visit — perfect for previewing personalization before your live ad traffic flows. You can also use UTM-based rules to map campaigns to intents.

Step 5

Ground the AI in your knowledge

Bellhop’s copy isn’t made up — it’s retrieval-grounded. Before it writes a single variation, it reads a knowledge base built from your own material, and every claim it generates traces back to a source you provided.

  1. Go to Knowledge → Sources.
  2. Add your website (Bellhop can crawl it), plus any product docs, help center, case studies, or a brand/voice document.
  3. Let it index. From then on, generated copy draws only from these sources — so it stays accurate and on-brand.
Why this matters. The most common objection to AI website copy is “will it invent things?” Grounding is the answer: if a fact isn’t in your knowledge base, Bellhop won’t claim it. Richer sources → stronger, safer copy.
Step 6

Create your first personalization

A variation (internally, a “patch”) is the set of changes Bellhop applies for a given intent — e.g. for agency-scheduling visitors, set hero.h1 to “The scheduling platform agencies rely on.”

Let Bellhop draft them

  1. Open your site and go to Content → Generate.
  2. Pick an intent and the zones to personalize.
  3. Bellhop drafts grounded copy for each zone. Review, edit any wording, and approve.

Or write them yourself

Under Content → Variations → New, choose an intent and add an operation per zone:

OperationUse it for
setTextReplace the visible text of a zone (headlines, sub-heads, button labels).
setAttrChange an attribute — e.g. a CTA’s href to an intent-specific signup link.
Approval flow. Variations go live only once approved. You can enable auto-approve for text-only changes if you’d rather move fast, and keep manual review for anything that changes links or layout.
Step 7

Choose how changes apply

Each page (route) has an apply mode that controls how personalization reaches the visitor. Set it under Sites → Routes.

ModeBehaviorWhen to use
silentApplies instantly, invisibly.Production — the default once you trust your content.
promptShows a small consent popover before applying.When you want explicit visitor opt-in.
manualComputes the change but doesn’t apply it.QA — inspect what would happen without affecting visitors.

Start a new page in manual while you check your zones and content, then switch to silent when you’re happy.

Step 8

Run experiments (optional)

Not sure which headline wins? Let Bellhop test them. Experiments use a multi-armed bandit (Thompson sampling), so traffic shifts toward the best-performing variation automatically — you don’t have to call a winner by hand.

  1. Go to Experiments → New experiment.
  2. Pick a zone (e.g. hero.h1) and, optionally, an intent to scope it to.
  3. Add two or more arms — your control plus one or more variants.
  4. Set it Active. Each visitor is assigned an arm, and the dashboard reports how each is performing.
Step 9

Verify it’s working

Add ?bellhop_debug=1 to any page URL to watch Bellhop work in your browser console — no site changes required.

https://www.example.com/?_intent=agency-scheduling&bellhop_debug=1

Open DevTools → Console and you’ll see entries like:

[Bellhop] initialized {siteKey: "pub_xxx"}
[Bellhop] discovered 3 zones ["hero.h1","hero.subhead","hero.cta"]
[Bellhop] personalize responded in 87ms
[Bellhop] applied setText to zone hero.h1

You can also confirm the round trip in DevTools → Network:

  • runtime.js loads with status 200.
  • A personalize request fires on page load and returns your variation.
  • An events request follows once a change is applied.
What good looks like. The console shows your zones discovered and a variation applied; the page text changes to match the intent you’re testing. If a zone says “not found,” its data-bellhop-zone attribute is missing or misspelled.
Step 10

Connect analytics

Bellhop pushes events to your window.dataLayer on every personalized view, so you can measure impact in Google Analytics 4 through your existing Google Tag Manager setup.

  • bellhop_personalization — fired when a variation is applied (includes the intent and zones).
  • bellhop_experiment — fired when a visitor is assigned an experiment arm.

To surface these in GA4:

  1. In GTM, add a Custom Event trigger matching bellhop_personalization (and one for bellhop_experiment).
  2. Add a GA4 event tag firing on those triggers.
  3. Publish your container — the events now appear in GA4 reports alongside conversions.

Prefer to check quickly? Run window.dataLayer.filter(e => e.event?.startsWith('bellhop')) in the console to see the events directly.

Step 11

Go live

When your zones, content, and tests check out:

  1. Switch each page’s apply mode from manual to silent.
  2. Make sure the script tag is live on your published site (re-publish if you changed anything).
  3. Remove data-bellhop-debug from your script tag if you added it — debug logging is for development only.
  4. Watch the dashboard. Personalized views, experiment results, and conversions start flowing in real time.
You’re live. From here it’s iteration: add zones, refine intents, let experiments find the winners, and feed the knowledge base as your product evolves.

Optional integrations

Each of these adds capability and is safe to skip — Bellhop works without them and you can connect them any time under Integrations.

IntegrationWhat it unlocks
Google AdsAutomatic intent from real ad traffic (campaign, ad group, keyword).
HubSpotRecognize known accounts and sync personalization results back to your CRM.
Google Analytics 4Measure personalization and experiment impact next to your other metrics.
Company identificationGreet visitors by company where it can be resolved from network signals.

Troubleshooting

The page doesn’t change

  • Add ?bellhop_debug=1 and check the console. No [Bellhop] initialized line means the script isn’t loading — confirm the tag is in <head> and you re-published.
  • If it initializes but says 0 zones, your data-bellhop-zone attributes are missing — re-check Step 3.
  • If zones are found but no variation applies, no approved content exists for that intent + zone yet — create one in Step 6.

Console: “no site key found”

The data-bellhop-key attribute is empty or missing. Paste your pub_… key from the dashboard.

Console: “zone not found: hero.h1”

The named element doesn’t carry that attribute. Re-open the element’s settings and confirm data-bellhop-zone is present, lowercase, and spelled exactly as in your dashboard. Also check the element isn’t hidden by a visibility rule.

Personalization is slow or times out

Confirm data-bellhop-api matches the endpoint on your site’s settings page. If it’s correct and still slow, contact support — it shouldn’t exceed ~150 ms in normal operation.

GA4 events aren’t showing

  • Run window.dataLayer.filter(e => e.event?.startsWith('bellhop')) — if entries appear here but not in GA4, your GTM container is missing a trigger for the bellhop_* events (Step 10).
  • If dataLayer has no Bellhop entries, no variation was applied on that view — verify with debug mode first.

Reference

Debug URL parameters

ParameterEffect
?bellhop_debug=1Verbose [Bellhop] logging in the browser console.
?_intent=NAMEForce a specific intent for this visit (great for previewing).
?gclid=…Real Google Ads click ID — intent resolved from your linked account.

Glossary

TermMeaning
Site keyYour site’s public identifier (pub_…), used in the script tag.
ZoneAn element you’ve opted in to personalization with data-bellhop-zone.
IntentThe reason a visitor came, resolved from Google Ads or your rules.
VariationThe set of changes applied for an intent (a “patch”).
Apply modeHow a variation reaches the visitor: silent, prompt, or manual.
Knowledge baseYour sources the AI is grounded in, so copy stays accurate.

Get help

Stuck on a step, or want us to walk through your first setup live? We’re hands-on with every early-access team.