# How to add a waitlist to Bubble > Put a LaunchList signup form in a Bubble app with an HTML element, capture signups from your own Bubble form through the API Connector, or link to your hosted page. Source: https://getlaunchlist.com/help/docs/integrations/bubble --- Bubble gives you three ways in. Pick by how much of the form you want to own. | You want | Use | Code | | ----------------------------------------- | ----------------------------------------------------------- | ------------ | | Our form, in the design you pick | [An HTML element](#add-the-form-with-an-html-element) | 2 lines | | Your own Bubble inputs and button | [The API Connector](#use-your-own-bubble-form-with-the-api) | One API call | | No form in the app at all | [A link to your hosted page](#link-to-your-hosted-page) | None | > [!NOTE] Bubble's Free plan cannot go live > Bubble needs a paid plan to deploy a live version of your app > ([Bubble pricing](https://bubble.io/pricing)). On Free you can build and test everything below in > Preview, but visitors cannot reach it. Until you deploy, share your LaunchList hosted page instead. ## Add the form with an HTML element 1. In LaunchList, open **Embed & API → Your website**, choose **Bubble** under **What is your site built with?**, pick your form if you have more than one, and copy the **Inline** snippet it shows. 2. In the Bubble editor, drag an **HTML** element onto the page where the form should appear. 3. Paste the snippet into the element.  ```html
``` 4. Leave **Display as an iFrame** unchecked, and check **Stretch to fit content** so the element grows with the form and pushes what sits below it down. 5. Click **Preview** and submit a test signup. It appears in **Audience** in LaunchList. > [!WARNING] The editor will not render the form > Bubble runs script tags in an HTML element only in run mode, never in the editor > ([Bubble manual: HTML element](https://manual.bubble.io/core-resources/elements/visual-elements)). > An empty box in the editor is expected. Use Preview or the live app. The form renders inside a **shadow root**, so your Bubble styles cannot break it and its styles cannot leak into your app. Change the form's fields in LaunchList later and the live form updates itself, with nothing to re-paste. ### Why not "Display as an iFrame" That option runs the HTML as if it were an independent web page. Our form then reads the address of that frame rather than your app's page, so the `?ref=` on a referral link never reaches it and the referral does not credit. Without the option the form sits in your page and picks the code up itself. ### Forms on several pages, or inside groups that appear later Load the script once for the whole app instead of in every HTML element. Go to **Settings → SEO / metatags** and paste it into **Script/meta tags in header**, which Bubble adds to the head of every page: ```html ``` Every HTML element after that only needs the target: ```html ``` The script watches the page, so a form inside a group or popup that Bubble shows later, or on a page reached without a reload, mounts the moment it appears. > [!NOTE] Check the header field on your plan > Bubble's manual does not say which plans run scripts from the header field. If the form appears > with the script in the HTML element but not with it in the header, put the script back in the > element. ## Use your own Bubble form with the API Keep your own inputs and button, and send each signup to LaunchList from a workflow. It runs the same pipeline as our form: deduplication, referral credit, trust scoring, the verification email, webhooks and automations. > [!WARNING] Never put your API key anywhere visitors can read it > An `llk_live_` key is a secret. It goes only in the API Connector's private header below, never in > an HTML element, a page workflow's text, an option set, a custom state or the call's body. Bubble > sends a call's body to the browser > ([Bubble manual: adding calls](https://manual.bubble.io/core-resources/api/the-api-connector/adding-calls)). ### 1. Create a key In LaunchList, open **Embed & API → Developers → API keys**, press **New API key**, choose **Full access**, pin it to the project this waitlist belongs to, and press **Create key**. Copy the key now: it is shown once. Copy the project's `prj_` handle too. Details: [authentication](/help/docs/api/authentication).  ### 2. Add LaunchList to the API Connector 1. In Bubble, install the **API Connector** plugin if it is not already in your app, and add a new API. 2. Name it `LaunchList` and set **Authentication** to **Private key in header**. 3. Set **Key name** to `Authorization` and **Private key** to `Bearer` followed by a space and your key ([Bubble manual: authentication](https://manual.bubble.io/core-resources/api/the-api-connector/authentication)). 4. Add a call named `Create contact`, set **Use as** to **Action**, the method to **POST** and the URL to: ```text https://api.getlaunchlist.com/v1/contacts ``` 5. Add a header `Content-Type` with the value `application/json`, and set the body to: ```json { "project": "prj_7Qk2mN4pR8", "email": "