# Hosted pages and embeds | Waitlyze Docs

> Share your published page or embed it on your website.

Canonical: https://waitlyze.com/docs/embed


Only **published** revisions have a shareable URL or embed. Draft and paused waitlists show no public controls worth sharing.

## Hosted page [#hosted-page]

<Steps>
<Step>
### Publish first [#publish-first]
Complete [Publishing](/docs/publishing). Draft edits must be published before visitors see them.
</Step>
<Step>
### Copy the hosted URL [#copy-the-hosted-url]
In Page → Publish options → **Hosted page**, copy `/w/your-slug`. This is the canonical Waitlyze URL.
</Step>
<Step>
### Optionally connect a domain [#optionally-connect-a-domain]
Add `join.example.com` in Waitlist settings → Custom domain. When status is Ready, it serves the same published revision. See [Custom domains](/docs/domains).
</Step>
</Steps>

Local development uses your local origin; preview and production use their configured environment URLs. Do not hardcode one environment's URL into another.

## Embed on your website [#embed-on-your-website]

Copy the embed code from the builder's Publish options. It carries your **public waitlist ID**, not a secret API key.

```html title="Embed snippet"
<div class="waitlyze-widget" data-key-id="YOUR_WAITLIST_ID"></div>
<script src="https://waitlyze.com/js/embed.js" defer></script>
```

<Callout title="Public embed, private API key">
The embed uses a public waitlist ID and needs no secret. Keep [API keys](/docs/api-keys) on your server only.
</Callout>

- Place the snippet where the form should appear.
- The frame sizes itself to the form, so there is nothing to tune. Set `data-height` only if you want to reserve space before the form loads.
- Referral `?r=CODE` and UTM parameters from your page URL are forwarded into the widget.
- The frame reports its own height to the page that embeds it. Only messages from the Waitlyze origin are accepted.
- For local development, point the script `src` at your local Waitlyze origin instead of production.

<TypeTable
  type={{
    "data-key-id": {
      type: "string",
      required: true,
      description: "Your public waitlist ID. Find it in the builder's Publish options.",
    },
    "data-height": {
      type: "string",
      required: false,
      default: "380px",
      description:
        "Height to start with. The frame resizes itself to the form as soon as it loads, so this is only a placeholder.",
    },
  }}
/>

## Leaderboard & counter widgets [#leaderboard--counter-widgets]

Show social proof on any site - no API key needed. Both widgets serve JSON by default and an embeddable HTML snippet with `?format=html` (iframe it). Emails are always masked server-side (`b***@g***`); raw addresses never leave these endpoints. Responses are public-cacheable for 60 seconds (`s-maxage=60, stale-while-revalidate=300`) and share the `widget` rate-limit budget (`429` carries `Retry-After`).

```html title="Leaderboard widget"
<iframe
  src="https://waitlyze.com/api/widgets/leaderboard?waitlistId=YOUR_WAITLIST_ID&format=html&limit=10"
  width="100%"
  height="420"
  style="border:0"
  loading="lazy"
  title="Waitlist leaderboard"
></iframe>
```

```html title="Live counter widget"
<iframe
  src="https://waitlyze.com/api/widgets/counter?waitlistId=YOUR_WAITLIST_ID&format=html"
  width="100%"
  height="180"
  style="border:0"
  loading="lazy"
  title="Waitlist counter"
></iframe>
```

- Leaderboard needs a **published** waitlist with referrals on (`404` otherwise); the counter needs only a published waitlist. `limit` is 1–50 (default 10).
- Prefer JSON (`?format=json`) when rendering in your own components: `{ "total": 2418, "entries": [{ "position": 1, "maskedEmail": "b***@g***", "referrals": 12 }] }` and `{ "total": 2418 }`.

## Checklist before sharing [#checklist-before-sharing]

- Status is `Published` and Overview says `Published page`, not `Publish your latest changes`.
- You copied the URL or snippet **after** the last publish.
- Your site's Content Security Policy allows the Waitlyze script and frame.
- Custom domain, if used, shows Ready.

If the embed is blank, see [Troubleshooting](/docs/troubleshooting).

Building a fully custom form instead? The [custom frontend guide](/docs/custom-frontend) pairs the Signup API with referrals, your domain, and your sender end-to-end.

## Related Links
- [API Reference](https://waitlyze.com/docs/api/reference) - REST API endpoints
- [Embed Widget](https://waitlyze.com/docs/embed) - Embed instructions
- [Waitlyze Home](https://waitlyze.com/) - Product overview
