npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@leadmetrics-ai/landing-sdk

v1.0.49

Published

Leadmetrics SDK for creating landing pages

Readme

Landing Page SDK

Overview

This SDK provides reusable form validation and FAQ fetching features that can be easily incorporated into your landing pages. It is written in TypeScript and offers the following functionalities:

  • FAQ Fetching: Dynamically retrieves FAQ data from an API endpoint based on a provided slug for seamless integration.
  • Form Validation: Dynamically validates forms using custom data attributes.
  • Form Redirection: Redirects the user to a specified URL after a successful form submission.
  • Spam Prevention: Built-in bot detection including fill-time analysis, rate limiting, and human interaction checks.

Installation

<script src="https://cdn.jsdelivr.net/npm/@leadmetrics-ai/[email protected]/dist/landing.min.js"></script>

Setup

Add the following meta tags inside the <head> of your HTML page:

<meta name="api-key" content="YOUR_API_KEY" />

<!-- Optional: override the default API base URL -->
<meta name="base-url" content="https://your-api-base-url.com/api/form/v1/forms/" />

Methods

1. initializeForm(appendToMessage?)

Initialises form submission handling for all <form> elements on the page that have the data-lm-form attribute.

| Parameter | Type | Default | Description | |---|---|---|---| | appendToMessage | boolean | false | When true, any extra fields not in the base field list (name, email, company, mobile, whatsapp, message) are appended to the message field as key: value pairs instead of being sent as separate fields. |

Form Data Attributes

Add these attributes to <input>, <textarea>, or <select> elements to control validation:

| Attribute | Values | Description | |---|---|---| | data-lm-required | "true" | Makes the field required. | | data-lm-min | number | Minimum character length. | | data-lm-max | number | Maximum character length. | | data-lm-country | "in" | "us" | Validates mobile/whatsapp number format for India or US. | | data-lm-company-email | "true" | Rejects submissions from public email domains (Gmail, Yahoo, Outlook, etc.). |

Form Attributes

| Attribute | Description | |---|---| | data-lm-form="<form-id>" | Uniquely identifies the form. Used to route submissions to the correct API endpoint. Required. | | data-lm-form-redirect="<url>" | Redirects the user to this URL after a successful submission. Defaults to "/". |

Error Elements

For each form field with name="fieldName", add a corresponding error element with id="fieldNameError" and the class error:

<div class="error" id="fieldNameError"></div>

The SDK clears all .error elements on each submission attempt and writes validation messages into the matching #fieldNameError element.

The submit button must have id="submitBtn":

<button type="submit" id="submitBtn">Submit</button>

Examples

Text / Textarea Field

<div class="w-full">
  <textarea
    name="message"
    placeholder="Submit your requirements"
    data-lm-required="true"
    rows="3"
  ></textarea>
  <div class="mt-1 text-sm text-[#dc3545] error" id="messageError"></div>
</div>

Phone Number Field (India)

<div class="w-full">
  <input
    type="text"
    name="whatsapp"
    placeholder="WhatsApp Number"
    data-lm-required="true"
    data-lm-country="in"
    data-lm-min="10"
    data-lm-max="10"
  />
  <div class="mt-1 text-sm text-[#dc3545] error" id="whatsappError"></div>
</div>

Company Email Field

<div class="w-full">
  <input
    type="email"
    name="email"
    placeholder="Work Email"
    data-lm-required="true"
    data-lm-company-email="true"
  />
  <div class="mt-1 text-sm text-[#dc3545] error" id="emailError"></div>
</div>

Full Form Example

<form
  data-lm-form="form-teaminfra-campaign"
  data-lm-form-redirect="https://thankyoupage.com"
>
  <div class="w-full">
    <input
      type="text"
      name="name"
      placeholder="Full Name"
      data-lm-required="true"
    />
    <div class="mt-1 text-sm text-[#dc3545] error" id="nameError"></div>
  </div>

  <div class="w-full">
    <input
      type="email"
      name="email"
      placeholder="Work Email"
      data-lm-required="true"
      data-lm-company-email="true"
    />
    <div class="mt-1 text-sm text-[#dc3545] error" id="emailError"></div>
  </div>

  <div class="w-full">
    <input
      type="text"
      name="whatsapp"
      placeholder="WhatsApp Number"
      data-lm-required="true"
      data-lm-country="in"
      data-lm-min="10"
      data-lm-max="10"
    />
    <div class="mt-1 text-sm text-[#dc3545] error" id="whatsappError"></div>
  </div>

  <div class="w-full">
    <textarea
      name="message"
      placeholder="Your requirements"
      data-lm-required="true"
      rows="3"
    ></textarea>
    <div class="mt-1 text-sm text-[#dc3545] error" id="messageError"></div>
  </div>

  <button type="submit" id="submitBtn">Submit</button>
</form>
lm.formService.initializeForm();

// With appendToMessage enabled
lm.formService.initializeForm(true);

Spam Prevention

The SDK includes several built-in bot and spam prevention mechanisms that require no additional configuration:

| Mechanism | Description | |---|---| | Minimum fill time | Rejects submissions completed in under 3 seconds (bots fill forms instantly). | | Human interaction check | Requires at least one mousemove, touchstart, or keydown event before allowing submission. | | Rate limiting | Allows a maximum of 3 successful submissions per form per 5-minute window, tracked via localStorage. | | Double-submission guard | Disables the submit button and blocks re-entry while a submission is in flight. | | Script injection detection | Scans all field values for <script>, javascript:, event handlers, and other injection patterns. | | Input sanitisation | Strips <>, javascript: protocols, and inline event handlers from all field values on blur. |


2. getFaq(slug)

Fetches FAQ data from the API for the given slug. The API key is read automatically from the <meta name="api-key"> tag.

| Parameter | Type | Description | |---|---|---| | slug | string | The FAQ slug to fetch. |

Returns a Promise<FAQData | undefined>.

const slug = "your-slug";

async function fetchFaq() {
  const data = await lm.getFaq(slug);
  return data;
}