[{"data":1,"prerenderedAt":392},["ShallowReactive",2],{"blog-how-to/waitlist-carrd":3},{"id":4,"title":5,"body":6,"category":364,"date":365,"dateModified":366,"description":367,"draft":368,"extension":369,"faq":370,"featured":368,"keywords":378,"meta":379,"navigation":380,"ogDescription":381,"ogTitle":5,"path":382,"readTime":383,"schemaOrg":384,"schemaType":385,"seo":386,"sitemap":387,"stem":388,"tags":389,"twitterCard":390,"__hash__":391},"blog/blog/how-to/waitlist-carrd.md","Carrd Waitlist: Add Email Signup With One HTML Embed",{"type":7,"value":8,"toc":356},"minimark",[9,13,16,22,27,49,53,63,85,94,107,129,135,144,153,157,160,181,188,194,209,217,227,235,252,261,265,268,271,280,284,291,294,300,303,331],[10,11,12],"p",{},"Carrd is the fastest no-code landing page builder for indie founders. You can ship a one-pager in an afternoon with no coding required. But adding a waitlist to Carrd requires knowing one platform quirk: each custom HTML block renders inside its own iframe, which changes how you embed external scripts.",[10,14,15],{},"Get this right and you have a working waitlist with referral tracking in under five minutes.",[17,18,19],"tldr",{},[10,20,21],{},"Paste both the OperatorStack script tag and the widget div into the same Carrd HTML element. They must share the same iframe context. Carrd Pro Standard ($19/year) is required to use HTML embeds.",[23,24,26],"h2",{"id":25},"what-you-need-before-you-start","What You Need Before You Start",[28,29,30,38],"ul",{},[31,32,33,37],"li",{},[34,35,36],"strong",{},"Carrd Pro Standard ($19/year)."," The free plan does not allow custom HTML embeds. Pro Standard is the minimum plan that unlocks the HTML/CSS/JS element type in the editor.",[31,39,40,43,44,48],{},[34,41,42],{},"An OperatorStack account."," Free to start. You need your project key (the ",[45,46,47],"code",{},"pk_"," value from your embed snippet).",[23,50,52],{"id":51},"step-by-step-setup","Step-by-Step Setup",[54,55,57],"step",{"number":56},"1",[10,58,59,62],{},[34,60,61],{},"Create an OperatorStack project."," Go to your OperatorStack dashboard and create a new project. Name it after your product and enter your Carrd site URL so CORS is configured correctly for your domain.",[54,64,66,72,82],{"number":65},"2",[10,67,68,71],{},[34,69,70],{},"Copy your embed snippet."," From the project settings page, copy your script tag. It looks like this:",[73,74,80],"pre",{"className":75,"code":77,"language":78,"meta":79},[76],"language-html","\u003Cscript src=\"https://operatorstack.dev/os.js\" data-project=\"pk_abc123\">\u003C/script>\n","html","",[45,81,77],{"__ignoreMap":79},[10,83,84],{},"Keep this handy. You will paste it in the next step.",[54,86,88],{"number":87},"3",[10,89,90,93],{},[34,91,92],{},"Open your Carrd site in the editor."," Log in to Carrd and click Edit on your site to open the visual editor.",[54,95,97],{"number":96},"4",[10,98,99,102,103,106],{},[34,100,101],{},"Add an HTML element."," Click the + button to add a new element. From the element type menu, select ",[34,104,105],{},"HTML/CSS/JS",". Carrd opens a code input panel.",[54,108,110,120,126],{"number":109},"5",[10,111,112,115,116,119],{},[34,113,114],{},"Paste both the script tag and the widget div."," In the HTML input, enter this code -- replacing ",[45,117,118],{},"pk_abc123"," with your actual project key:",[73,121,124],{"className":122,"code":123,"language":78,"meta":79},[76],"\u003Cscript src=\"https://operatorstack.dev/os.js\" data-project=\"pk_abc123\">\u003C/script>\n\u003Cdiv data-os-widget=\"waitlist\">\u003C/div>\n",[45,125,123],{"__ignoreMap":79},[10,127,128],{},"Both lines go in the same element. This is the key Carrd-specific requirement.",[130,131,132],"warning-box",{},[10,133,134],{},"Do not put the script tag and the widget div in separate Carrd HTML elements. Carrd sandboxes each HTML block inside its own iframe. A script in one iframe cannot find a div in a different iframe. Both must be in the same element.",[54,136,138],{"number":137},"6",[10,139,140,143],{},[34,141,142],{},"Adjust the element height."," In Carrd's editor, drag the bottom edge of your HTML element to set its height. The OperatorStack waitlist form fits comfortably at around 280-320px tall. If the form appears clipped, increase the height.",[54,145,147],{"number":146},"7",[10,148,149,152],{},[34,150,151],{},"Save and publish."," Click Save, then Publish in the Carrd editor. Your site goes live with the waitlist form. Visit your URL, submit a test email, and confirm the signup appears in your OperatorStack dashboard under Contacts.",[23,154,156],{"id":155},"when-the-form-renders-but-the-dashboard-stays-empty","When the Form Renders but the Dashboard Stays Empty",[10,158,159],{},"This is the failure the iframe produces, and it does not throw an error. The form paints, the submit\nbutton works, and Contacts stays at zero. Two commands tell you which half broke.",[10,161,162,165,166,169,170,173,174,177,178,180],{},[45,163,164],{},"os.js"," resolves both of its inputs against ",[45,167,168],{},"document",". The project key comes from\n",[45,171,172],{},"document.querySelector(\"script[data-project]\")"," and the widget containers come from\n",[45,175,176],{},"document.querySelectorAll(\"[data-os-widget]\")",". Inside a Carrd HTML element, ",[45,179,168],{}," is the\niframe's document, not the page's. Same element means same document, so both queries hit. Split\nacross two elements means the script's document holds no widget div and the div's document holds no\nscript tag, and neither half reports a problem.",[10,182,183,184,187],{},"First, turn on logging by adding ",[45,185,186],{},"data-dev=\"true\""," to the script tag:",[73,189,192],{"className":190,"code":191,"language":78,"meta":79},[76],"\u003Cscript src=\"https://operatorstack.dev/os.js\" data-project=\"pk_abc123\" data-dev=\"true\">\u003C/script>\n\u003Cdiv data-os-widget=\"waitlist\">\u003C/div>\n",[45,193,191],{"__ignoreMap":79},[10,195,196,197,200,201,204,205,208],{},"Every ",[45,198,199],{},"[OperatorStack]"," line now prints to the console, and the 5-minute config cache is bypassed so\ndashboard changes show up on reload instead of five minutes later. If you mistyped the attribute\nname, you get this warning even without ",[45,202,203],{},"data-dev",", because it is a ",[45,206,207],{},"console.warn"," rather than a\ndebug log:",[73,210,215],{"className":211,"code":213,"language":214},[212],"language-text","[OperatorStack] No data-project attribute found on script tag\n","text",[45,216,213],{"__ignoreMap":79},[10,218,219,220,223,224,226],{},"Second, point the console at the right frame. In Chrome DevTools the console has a context dropdown\nnext to the filter box, and it reads ",[45,221,222],{},"top"," by default. ",[45,225,222],{}," is the Carrd page, not your embed. Switch\nit to the iframe entry, then run:",[73,228,233],{"className":229,"code":231,"language":232,"meta":79},[230],"language-js","await window.OperatorStack.ready;\nwindow.OperatorStack.projectKey; // \"pk_abc123\"\nwindow.OperatorStack.isSignedUp(); // true after a test signup\n","js",[45,234,231],{"__ignoreMap":79},[10,236,237,240,241,243,244,247,248,251],{},[45,238,239],{},"window.OperatorStack"," being undefined on ",[45,242,222],{}," while defined in the iframe is the expected result\nfor the Step 5 approach, not a bug. If it is undefined in both, the script tag never loaded. If\n",[45,245,246],{},"projectKey"," is ",[45,249,250],{},"null",", the script loaded but the key did not come through, which almost always means\nthe script tag and the div ended up in different Carrd elements.",[253,254,255],"tip-box",{},[10,256,257,258,260],{},"Take ",[45,259,186],{}," off before you publish. It is only a logging flag, but leaving it on keeps the\n5-minute config cache disabled, so every visitor's browser refetches your project config instead of\nreusing it.",[23,262,264],{"id":263},"what-your-visitors-see","What Your Visitors See",[10,266,267],{},"After someone submits the waitlist form, OperatorStack shows a confirmation message and displays their unique referral link. Share buttons for Twitter, LinkedIn, WhatsApp, and email appear automatically. When a referred visitor signs up through that link, the attribution is recorded and visible on your referral leaderboard.",[10,269,270],{},"The embed also collects cookie-free analytics in the background: total page views, referral sources (which sites send you traffic), and estimated unique visitors. No extra configuration, no cookie banner required.",[253,272,273],{},[10,274,275,276,279],{},"When sharing your Carrd site on social media, add UTM parameters to your URL: ",[45,277,278],{},"https://yoursite.carrd.co?utm_source=twitter&utm_medium=social",". OperatorStack tracks these automatically so you can see which channels drive the most signups in your analytics dashboard.",[23,281,283],{"id":282},"alternative-header-code-injection","Alternative: Header Code Injection",[10,285,286,287,290],{},"If you are on Carrd Pro Plus, you can also add the script tag via ",[34,288,289],{},"Site Settings > Code Injection > Header"," instead of embedding it in an HTML element. This loads the script in the main page context rather than inside an iframe.",[10,292,293],{},"With this approach, add a separate HTML element to your page containing only:",[73,295,298],{"className":296,"code":297,"language":78,"meta":79},[76],"\u003Cdiv data-os-widget=\"waitlist\">\u003C/div>\n",[45,299,297],{"__ignoreMap":79},[10,301,302],{},"A header-injected script runs in the page's main document, so it renders only the widget divs that live in that same document. If Carrd puts your div inside an iframe, the header script will not see it. Run the frame check above before you rely on this route. The single-element approach from Step 5 keeps the script and the div in the same document by construction and works on all paid Carrd plans, so use that unless you have a specific reason to separate them.",[304,305,306,313,319,325],"faq-section",{},[307,308,310],"faq-item",{"question":309},"What Carrd plan do I need to add a waitlist?",[10,311,312],{},"Carrd Pro Standard ($19/year). The free plan does not allow HTML embeds. Pro Standard is the cheapest plan that unlocks the HTML/CSS/JS element type.",[307,314,316],{"question":315},"Why do I need both the script and div in the same Carrd element?",[10,317,318],{},"Carrd renders each custom HTML element inside its own iframe for sandboxing. The script and widget div need to share the same iframe context. If you split them into separate Carrd elements, the script cannot find the div.",[307,320,322],{"question":321},"Will the waitlist widget show referral links after signup?",[10,323,324],{},"Yes. After someone submits the form, OperatorStack displays their unique referral link with share buttons for Twitter, LinkedIn, WhatsApp, and email. Everything renders inside the same embed block.",[307,326,328],{"question":327},"Can I track page views on Carrd with OperatorStack too?",[10,329,330],{},"Yes. The same script that powers the waitlist widget also collects cookie-free analytics: page views, referral sources, and unique visitor counts. No consent banner needed.",[332,333,334,335],"content-related-articles",{},"\n  ",[336,337,334,341],"contentrelatedcard",{"href":338,"title":339,"description":340},"/blog/how-to/operatorstack-framer","How to Add a Waitlist to a Framer Site (Custom Code or Code Component)","The other no-code one-pager builder, using site-wide Custom Code plus a small Code Component.",[336,342,334,346],{"href":343,"title":344,"description":345},"/blog/how-to/waitlist-wordpress","WordPress Waitlist: Add a Signup Form Without a Plugin","Add a waitlist with referral tracking to any WordPress site using the functions.php method, no plugin required.",[336,347,351],{"href":348,"title":349,"description":350},"/blog/how-to/ghost-waitlist","Ghost Waitlist: Add Signups Without a Plugin","Code injection with no plan gate at all, on a platform whose own Portal signups carry no referral code.",[352,353],"cta-box",{"href":354,"label":355},"/","Get Started Free",{"title":79,"searchDepth":357,"depth":357,"links":358},2,[359,360,361,362,363],{"id":25,"depth":357,"text":26},{"id":51,"depth":357,"text":52},{"id":155,"depth":357,"text":156},{"id":263,"depth":357,"text":264},{"id":282,"depth":357,"text":283},"how-to","2026-06-23","2026-09-29","Add a waitlist with referral tracking to a Carrd site in 5 minutes. The script and widget div must share one HTML element, because Carrd iframes each block.",false,"md",[371,373,376,377],{"question":309,"answer":372},"Carrd Pro Standard ($19/year). The free plan does not allow HTML embeds or custom code. Pro Standard is the cheapest plan that unlocks the HTML/CSS/JS element type.",{"question":374,"answer":375},"Why do I need both the script and the div in the same Carrd element?","Carrd renders each custom HTML element inside its own iframe for sandboxing. The script and the widget div need to share the same iframe context to communicate. If you split them into separate Carrd elements, the script cannot find the div.",{"question":321,"answer":324},{"question":327,"answer":330},"carrd waitlist,add waitlist to carrd,carrd email signup,carrd custom html,carrd lead capture,carrd pre-launch",{},true,"Add a waitlist to Carrd with one HTML embed. The script and the widget div must share the same element.","/blog/how-to/waitlist-carrd","6 min","[object Object]","HowTo",{"title":5,"description":367},{"loc":382},"blog/how-to/waitlist-carrd",[],"summary_large_image","1AFVPjgT6A6HgavHvNraFeVhIj5SI-8RxBFXMrp1DJs",1790937871132]