How to Build a Web Component That Converts Customers

Let’s make this practical. We’ll build a conversion form that captures leads, perfect for landing pages, product signups, or email subscriptions.

This Web Component will:
Display a compelling offer (e.g., “Get 20% off your first order”)
Include a form to capture name and email
Handle form submissions dynamically
Be fully encapsulated and reusable anywhere

But here’s the twist: rather than hardcoding the template in JavaScript, we’re going to base our Web Component on an external HTML file. This makes it even easier to update and maintain your UI without digging into your JavaScript code.

Step 1: Create an External HTML File

Create a file named conversion-form.html with the following content:

<div id="conversion-form-template">
  <style>
    .form-container {
      font-family: Arial, sans-serif;
      background: #fff;
      border: 1px solid #ddd;
      padding: 20px;
      border-radius: 8px;
      text-align: center;
      box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.1);
      max-width: 350px;
      margin: auto;
    }
    h2 {
      color: #333;
    }
    p {
      color: #666;
      font-size: 14px;
    }
    input {
      width: 100%;
      padding: 10px;
      margin: 8px 0;
      border: 1px solid #ccc;
      border-radius: 4px;
      font-size: 16px;
    }
    button {
      background: #007bff;
      color: white;
      padding: 10px 15px;
      border: none;
      border-radius: 4px;
      font-size: 16px;
      cursor: pointer;
      width: 100%;
      transition: background 0.3s;
    }
    button:hover {
      background: #0056b3;
    }
    .success-message {
      display: none;
      color: green;
      margin-top: 10px;
      font-weight: bold;
    }
  </style>

  <div class="form-container">
    <h2>Get 20% Off Your First Order!</h2>
    <p>Sign up now and receive an exclusive discount.</p>
    <input type="text" id="name" placeholder="Your Name" required />
    <input type="email" id="email" placeholder="Your Email" required />
    <button id="submit-btn">Get My Discount</button>
    <p class="success-message">Thanks! Your discount code is on its way. 🎉</p>
  </div>
</div>

Step 2: Create the Web Component JavaScript File

Now, create a file named conversion-form.js. This script will load the external HTML template, attach it to the component’s Shadow DOM, and set up the conversion form’s functionality:

class ConversionForm extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: "open" });
  }

  async connectedCallback() {
    // Fetch the external HTML file
    try {
      const response = await fetch("conversion-form.html");
      if (!response.ok) {
        throw new Error("Network response was not ok");
      }
      const htmlText = await response.text();

      // Create a temporary container to parse the HTML
      const tempContainer = document.createElement("div");
      tempContainer.innerHTML = htmlText;

      // Grab the template by its id
      const template = tempContainer.querySelector("#conversion-form-template");
      if (template) {
        // Clone the template content and append it to the shadow DOM
        this.shadowRoot.appendChild(template.cloneNode(true));
        // Once the template is in place, set up event listeners
        this.setupForm();
      } else {
        console.error("Template not found in conversion-form.html");
      }
    } catch (error) {
      console.error("Error fetching the template:", error);
    }
  }

  setupForm() {
    this.nameInput = this.shadowRoot.querySelector("#name");
    this.emailInput = this.shadowRoot.querySelector("#email");
    this.submitButton = this.shadowRoot.querySelector("#submit-btn");
    this.successMessage = this.shadowRoot.querySelector(".success-message");

    this.submitButton.addEventListener("click", this.handleSubmit.bind(this));
  }

  handleSubmit() {
    const name = this.nameInput.value.trim();
    const email = this.emailInput.value.trim();

    if (!name || !email) {
      alert("Please fill out both fields.");
      return;
    }

    // Simulate sending data to a backend
    console.log("Customer Data Sent:", { name, email });

    // Show success message
    this.successMessage.style.display = "block";

    // Clear form fields
    this.nameInput.value = "";
    this.emailInput.value = "";
  }
}

// Define the conversion-form tag so it can be referenced
customElements.define("conversion-form", ConversionForm);

Note: connectedCallback() is one of the lifecycle callbacks in a Web Component, which is automatically called when the component is added to the DOM. When you mark it as async, you're able to use await inside the function to handle asynchronous operations (such as fetching data or templates) in a cleaner and more readable way.

Step 3: Use the Web Component on Your Website

Finally, integrate the component into your landing page. Create a main HTML file (e.g., index.html) that includes the component’s JavaScript:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>Exclusive Offer - Get 20% Off Your First Order</title>
  <style>
    body {
      margin: 0;
      padding: 0;
      background: #f4f4f4;
      font-family: Arial, sans-serif;
      color: #333;
      text-align: center;
    }
    header {
      background: #007bff;
      color: #fff;
      padding: 20px;
    }
    header h1 {
      margin: 0;
      font-size: 2em;
    }
    .hero {
      padding: 40px 20px;
      background: #e9f3ff;
    }
    .hero h1 {
      font-size: 2.5em;
      margin-bottom: 10px;
    }
    .hero p {
      font-size: 1.2em;
      margin-bottom: 20px;
    }
    .container {
      padding: 20px;
      max-width: 800px;
      margin: 0 auto;
    }
    footer {
      background: #007bff;
      color: #fff;
      padding: 10px;
      position: fixed;
      bottom: 0;
      width: 100%;
      font-size: 0.9em;
    }
  </style>
</head>
<body>
  <header>
    <h1>Exclusive Offer</h1>
  </header>

  <section class="hero">
    <h1>Unlock Your 20% Discount Today!</h1>
    <p>Join our community and enjoy exclusive savings on your first purchase.</p>
  </section>

  <section class="container">
    <!-- Our conversion form web component -->
    <conversion-form></conversion-form>
  </section>

  <footer>
    <p>&copy; 2025 Your Company. All Rights Reserved.</p>
  </footer>

  <!-- Include the component's JavaScript -->
  <script src="conversion-form.js"></script>
</body>
</html>

That’s it! You’ve built a conversion page using a reusable Web Component that leverages an external HTML template for its UI. This approach keeps your code bloat-free and maintainable.

Step 4: Deploying with GitHub Pages

One of the best parts of this approach is its simplicity. With no build tools or additional dependencies, deploying your landing page is as easy as 1-2-3. Here’s how to do it with GitHub Pages:

  1. Create a Repository:
    Create a new repository on GitHub and commit your project files (index.html, conversion-form.html, and conversion-form.js).
  2. Configure GitHub Pages:
    In your repository’s settings, scroll down to the Pages section under Code and Automation. Choose the branch you want to deploy (typically main or master) and set the source to the root folder.
  3. Deploy:
    GitHub Pages will automatically build and deploy your static site. In just a few minutes, your landing page with the Web Component will be live! The url for your page will be http://<username>.github.io/<repository-name>
  4. Update with Ease:
    With no build tools required, updates are as simple as committing changes and pushing them to your GitHub repository. GitHub Pages takes care of the rest.

Here is my deployed version. Check it out!

https://agalin920.github.io/web-components-demo/

What’s Next? Managing Web Components at Scale with Zesty

While this Web Component is great for a single landing page, imagine managing dozens of different conversion forms dynamically. That’s where a CMS like Zesty comes in.

In Part 2, we’ll show you how Zesty CMS helps you:
✅ Create, edit, and manage Web Components
✅ Dynamically render Web Components in a headless or traditional way
Host your Web Components centrally—ensuring they’re available and consistent across all your projects

By leveraging Zesty’s robust hosting and management capabilities, you can focus on building amazing UIs while Zesty takes care of the heavy lifting, from content updates to secure, scalable hosting of your Web Components.