DomainDirectory
← Domain Directory

Developer & Embed Docs

Embed a widget, or POST your own form into the Domain Directory database.

API v1

Available Form Types

Acquire the domain — collects bid price, phone, contact preference

Partnership inquiry → saves lead, then iPartner login (check submission with their email)

staffingpreview ↗

Join the team — collects team role, resume URL, developer flag

General inquiry — collects phone & contact preference

Lease the domain — name, email, and a 6 / 12 / 24 month term. Only names with no Next.js template and no custom worker.

newsletterpreview ↗

Community invite → Contrib firststep signup (email + role prefilled)

Option 1 — Direct URL (simplest)

Link directly to a hosted form page. No setup required. Works as a full page or in an iframe.

https://www.domaindirectory.com/forms/[type]/[domain]

Examples:

Add a button link in any HTML page:

html
<a href="https://www.domaindirectory.com/forms/offer/agentbank.com"
   target="_blank">
  Make an Offer
</a>

Option 2 — iframe Embed

Drop an iframe anywhere on your page. The form handles submission internally.

html
<iframe
  src="https://www.domaindirectory.com/forms/offer/agentbank.com"
  width="100%"
  height="700"
  style="border:none; border-radius:16px;"
  title="Make an offer for agentbank.com"
></iframe>

Tip: set height to 700–900px depending on form type. The partner and staffing forms are taller.

Option 3 — JS Widget (auto-render)

Load our script and place <div data-dd-form> elements anywhere on your page. The script bootstraps the form inside each matching element. Zero framework dependencies.

Step 1 — Load the script (once per page):

html
<script src="https://www.domaindirectory.com/widget/dd-forms.js" defer></script>

Step 2 — Place a container div:

html
<div
  data-dd-form="offer"
  data-dd-domain="agentbank.com"
></div>

All attributes:

AttributeRequiredValues
data-dd-formYesoffer | partner | staffing | inquire | lease
data-dd-domainYese.g. agentbank.com

Option 4 — Next.js / React Component

If you're in a Next.js or React app, copy src/components/ServiceContactForm.tsx from the domaindirectory-nextjs repo and import it directly.

tsx
import { ServiceContactForm } from "@/components/ServiceContactForm";

// In your page / component:
<ServiceContactForm
  formType="offer"
  domain="agentbank.com"
  displayName="AgentBank.com"
/>

The component posts to https://www.domaindirectory.com/api/domain-contact/ by default. Any lander origin can call that URL from the browser.

Option 5 — Cloudflare Worker Injection

Inject dd-forms.js into any HTML response from a Cloudflare Worker (parked / lander pages). Example below uses partner — after submit, the visitor is sent to iPartner with email prefilled.

javascript
// worker.js — partner embed
export default {
  async fetch(request) {
    const response = await fetch(request);
    const url = new URL(request.url);
    const host = url.hostname.replace(/^www\./, "");
    const html = await response.text();

    const snippet = `
<div data-dd-form="partner" data-dd-domain="${host}"></div>
<script src="https://www.domaindirectory.com/widget/dd-forms.js" defer><\/script>
`;

    // Inject before </body>
    const modified = html.replace("</body>", snippet + "</body>");

    return new Response(modified, {
      headers: { "Content-Type": "text/html" },
    });
  },
};

Partner success tells visitors to check their submission on ipartner.com by logging in with their email, then opens ipartner.com/login?domain=…&email=…. Swap data-dd-form for offer, staffing, or inquire, or lease as needed.

Custom forms — post to the database

Build the form yourself. On submit, POST JSON from the visitor's browser (or from your own server). A 201 means the lead is saved. This API does not redirect — after success, send the visitor wherever you want (iPartner, Contrib, or your own thank-you page).

Offer, partner, staffing, or inquiry

html
<form id="dd-custom">
  <input name="name" placeholder="Name" required />
  <input name="email" type="email" placeholder="Email" required />
  <input name="bid_price" type="number" placeholder="Offer amount" />
  <textarea name="message" placeholder="Message"></textarea>
  <!-- honeypot: leave hidden and empty -->
  <input name="website" tabindex="-1" autocomplete="off" aria-hidden="true"
    style="position:absolute;left:-9999px" />
  <button type="submit">Submit offer</button>
</form>
<script>
  document.getElementById("dd-custom").addEventListener("submit", async (e) => {
    e.preventDefault();
    const fd = new FormData(e.currentTarget);
    const res = await fetch("https://www.domaindirectory.com/api/domain-contact/", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        domain: location.hostname.replace(/^www\./, ""),
        type: "offer", // offer | partner | staffing | inquire
        name: fd.get("name"),
        email: fd.get("email"),
        bid_price: fd.get("bid_price") || undefined,
        message: fd.get("message"),
        website: fd.get("website") || "",
      }),
    });
    const data = await res.json();
    if (!res.ok) {
      alert(data.error || "Could not save");
      return;
    }
    e.currentTarget.innerHTML = "<p>Saved. Thanks — we have your submission.</p>";
  });
</script>
  • Keep the trailing slash on /api/domain-contact/. A URL without it redirects, and browsers drop that redirect on the CORS preflight.
  • Call it from the page on the lander. Any Origin is allowed. A server-side POST of the same JSON also saves the row.
  • domain and email are required. type is offer, partner, staffing, or inquire.
  • Leave website empty. If it has a value, the API pretends success and does not save.
  • Optional formStartedAt is a millisecond timestamp from when the form was shown. If you send it, submit must be at least 2.5 seconds later. Omit it if you do not want that timer.
  • Do not send a Turnstile token from a parked domain. That check runs only on domaindirectory.com.

Newsletter

javascript
await fetch("https://www.domaindirectory.com/api/leads/", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    domain_name: "appmd.com",
    email: "[email protected]",
    name: "Jane Smith",
    source: "newsletter",
    website: "",
  }),
});
// { success: true } — then send them to Contrib if you want:
// https://www.contrib.com/signup/firststep?domain=appmd.com&[email protected]&ref=dd-newsletter

API Reference

Offer, partner, staffing, and inquiry forms POST to https://www.domaindirectory.com/api/domain-contact/. Newsletter posts to https://www.domaindirectory.com/api/leads/. The browser call must include the trailing slash.

FieldTypeRequiredNotes
domainstringYese.g. agentbank.com
emailstringYesValid email address
typestringNooffer | partner | staffing | inquire | contact
namestringNoSubmitter's name
phonestringNoPhone with country code
companystringNoCompany name
messagestringNoFree-text message
bid_pricenumberNoOffer amount in dollars
websitestringNoHoneypot. Must be empty or the row is not saved
formStartedAtnumberNoMs timestamp. If set, submit must be ≥ 2.5s later

Example raw POST:

javascript
const res = await fetch("https://www.domaindirectory.com/api/domain-contact/", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    domain: "agentbank.com",
    type: "offer",
    name: "Jane Smith",
    email: "[email protected]",
    bid_price: 50000,
    message: "I'm interested in acquiring this domain for a fintech startup.",
  }),
});

const data = await res.json();
// { success: true, message: "Thank you! Your message has been received." }
CORS: The public form API reflects the caller's Origin so parked landers can post. Use the trailing-slash URL /api/domain-contact/ so the preflight is not redirected.

Newsletter → Contrib Signup

Every newsletter path saves a lead (tagged dd:newsletter), then sends the visitor to Contrib registration:

https://www.contrib.com/signup/firststep?domain=…&email=…&role=…&ref=dd-newsletter
  • JS widget — compact name/email on any site → firststep
  • React — NewsletterForm → firststep
  • Hosted page / iframe — /forms/newsletter/[domain] (role pick + what you get) → firststep with ref=dd-newsletter-community
  • Cloudflare Worker — inject the JS widget on parked pages → firststep

Live demo (JS / React widget):

Join the community

Marketers, social leads, developers & more are building this brand on Contrib. Enter your email to continue.

Option A — Direct URL / iframe (full community page):

html
<!-- Full page -->
<a href="https://www.domaindirectory.com/forms/newsletter/agentbank.com"
   target="_blank">Join the community</a>

<!-- Or iframe -->
<iframe
  src="https://www.domaindirectory.com/forms/newsletter/agentbank.com"
  width="100%"
  height="900"
  style="border:none; border-radius:16px;"
  title="Join agentbank.com on Contrib"
></iframe>

Option B — JS widget (compact embed):

html
<script src="https://www.domaindirectory.com/widget/dd-newsletter.js" defer></script>
<div
  data-dd-newsletter
  data-dd-domain="agentbank.com"
  data-dd-role="social"
></div>

Widget attributes (all optional):

AttributeDefaultNotes
data-dd-domaincurrent hostnameDomain passed to Contrib firststep
data-dd-role(none)Optional: marketer | social | developer | designer | writer | founder
data-dd-title"Join the community"Heading text
data-dd-subtitle"Marketers, social leads…"Subheading text
data-dd-button"Join on Contrib"Submit button label

Option C — Next.js / React:

tsx
import { NewsletterForm } from "@/components/NewsletterForm";

<NewsletterForm
  domain="agentbank.com"
  role="developer"
  title="Help build AgentBank"
  subtitle="Contribute your skills. Earn as the brand grows."
  buttonLabel="Join on Contrib"
/>

Posts to https://www.domaindirectory.com/api/leads/ by default, then redirects to Contrib firststep. Override with apiEndpoint="/api/leads" for same-origin.

Option D — Cloudflare Worker injection:

javascript
// worker.js
export default {
  async fetch(request) {
    const response = await fetch(request);
    const url = new URL(request.url);
    const host = url.hostname.replace(/^www\./, "");
    const html = await response.text();

    const snippet = `
<div data-dd-newsletter data-dd-domain="${host}"></div>
<script src="https://www.domaindirectory.com/widget/dd-newsletter.js" defer><\/script>
`;

    const modified = html.replace("</body>", snippet + "</body>");
    return new Response(modified, {
      headers: { "Content-Type": "text/html" },
    });
  },
};

After submit: lead saved, then browser goes to Contrib firststep with that domain + email.

Customizing the look:

css
[data-dd-newsletter] {
  --ddn-accent: #2563eb;
  --ddn-accent-hover: #1d4ed8;
  --ddn-radius: 8px;
  --ddn-bg: #ffffff;
  --ddn-border: #e5e7eb;
  --ddn-text: #111827;
  --ddn-muted: #6b7280;
  --ddn-font: inherit;
  --ddn-shadow: none;
}

Stable classes: .ddn-card, .ddn-input, .ddn-btn. Or skip defaults:

html
<div data-dd-newsletter data-dd-unstyled data-dd-class="my-form"></div>

<script>window.DD_NEWSLETTER_NO_CSS = true;</script>
<script src="https://www.domaindirectory.com/widget/dd-newsletter.js" defer></script>

React styling:

tsx
<NewsletterForm
  domain="agentbank.com"
  className="rounded-none border-2 border-black bg-zinc-50 p-8"
  inputClassName="border-black"
  buttonClassName="bg-black hover:bg-zinc-800"
/>

Or POST directly, then redirect:

javascript
const email = "[email protected]";
const domain = "agentbank.com";
const role = "social";

await fetch("https://www.domaindirectory.com/api/leads/", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    email,
    name: "Jane Smith",
    domain_name: domain,
    source: "newsletter",
  }),
});

// Same destination as the widget / React form / hosted page:
window.location.href =
  "https://www.contrib.com/signup/firststep"
  + "?domain=" + encodeURIComponent(domain)
  + "&email=" + encodeURIComponent(email)
  + "&role=" + encodeURIComponent(role)
  + "&ref=dd-newsletter";

CORS is open on /api/leads. Duplicate email + domain pairs are de-duplicated automatically.

Contact Us

Building a custom form, embedding a widget, or sending visitors to iPartner or Contrib? Send us a message and we'll get back to you.