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

interactiveform-embedder

v0.1.3

Published

A library for embedding interactive forms and widgets on your website.

Downloads

44

Readme

InteractiveForm Embedder

A library for embedding interactive forms and widgets on your website.

Installation

Recommendation: For better performance, include the script in <head> with the async attribute and place it before elements with data attributes.

Via CDN (unpkg)

UMD (recommended for CDN):

<script async src="https://unpkg.com/interactiveform-embedder@latest/dist/index.js"></script>

ESM:

<script
  type="module"
  src="https://unpkg.com/interactiveform-embedder@latest/dist/index.es.js"
></script>

Dynamic loading via JavaScript:

<script>
  // Load script in head with async
  const script = document.createElement('script');
  script.src = 'https://unpkg.com/interactiveform-embedder@latest/dist/index.js';
  script.async = true;
  document.head.appendChild(script);
</script>

Via npm

npm install interactiveform-embedder

Via pnpm (recommended)

pnpm install interactiveform-embedder

Usage

Automatic initialization via data attributes (CDN)

After loading the script, the library automatically initializes widgets from elements with data attributes. Data attributes are automatically removed after initialization to prevent re-initialization.

<!-- Page body widget - the div itself becomes the container -->
<div data-if-id="my-form" data-if-type="page-body"></div>

<!-- Multiple page-body widgets with the same ID are supported -->
<div data-if-id="my-form" data-if-type="page-body"></div>

<!-- Float button widget -->
<div data-if-id="my-form" data-if-type="float-button"></div>

<!-- Pop-up widget with timeout -->
<div data-if-id="my-form" data-if-type="pop-up" data-if-timeout="10"></div>

<!-- Widget with custom iframe source -->
<div
  data-if-id="my-form"
  data-if-type="page-body"
  data-if-iframe-src="https://custom-domain.com"
></div>

<!-- Custom tags (Wix, etc.) are also supported -->
<form-container data-if-id="my-form" data-if-type="page-body"></form-container>

Automatic initialization via ifLayer (CDN)

The library also automatically processes widgets from window.ifLayer:

<script>
  window.ifLayer = window.ifLayer || [];
  window.ifLayer.push({
    id: 'xxxxxxxxxxxxxxxxxxxxxxxx',
    type: 'page-body',
    container: '#form-container',
  });
  window.ifLayer.push({
    id: 'xxxxxxxxxxxxxxxxxxxxxxxx',
    type: 'float-button',
  });
  window.ifLayer.push({
    id: 'xxxxxxxxxxxxxxxxxxxxxxxx',
    type: 'pop-up',
    timeout: 10,
  });
  window.ifLayer.push({
    id: 'xxxxxxxxxxxxxxxxxxxxxxxx',
    type: 'page-body',
    container: '#form-container',
    iframeSrc: 'https://custom-domain.com',
  });
</script>

Manual initialization (npm/ESM)

import { Embedder } from 'interactiveform-embedder';

// Create instance with configuration
const embedder = new Embedder({
  id: 'my-form',
  type: 'page-body',
  container: '#form-container',
});

// Or create empty instance
const embedder = new Embedder();

// Add widgets
embedder.addWidget({
  id: 'my-form',
  type: 'page-body',
  container: '#form-container',
});

embedder.addWidget({
  id: 'my-form',
  type: 'float-button',
});

embedder.addWidget({
  id: 'my-form',
  type: 'pop-up',
  timeout: 10,
});

embedder.addWidget({
  id: 'my-form',
  type: 'page-body',
  container: '#form-container',
  iframeSrc: 'https://custom-domain.com',
});

// Remove widget
embedder.removeWidget('my-form', 'float-button');

// Reinitialize all widgets
embedder.reinitialize();

// Use singleton
const embedder = Embedder.getInstance();

Inline widget without container

<script>
  Embedder.createInlineWidget('my-form', '800px', '400px');
  // With custom iframe source
  Embedder.createInlineWidget('my-form', '800px', '400px', 'https://custom-domain.com');
</script>

Widget Types

  • page-body — embeds in specified container (can have multiple instances with the same ID)
  • float-button — floating button with dropdown iframe (unique per ID)
  • pop-up — modal window with delay (unique per ID, optional timeout in seconds, shown only once per day)

Data Attributes

  • data-if-id — unique widget identifier (required)
  • data-if-type — widget type: page-body, float-button, pop-up
  • data-if-timeout — delay for pop-up in seconds (optional)
  • data-if-iframe-src — custom iframe source URL (optional, defaults to https://if-form-staging.up.railway.app)

Note: All data attributes are automatically removed after widget initialization to prevent re-initialization. This works with any HTML elements including custom tags like <form-container> (Wix compatibility).

Multiple instances: You can have multiple page-body widgets with the same ID on the same page. Other widget types (float-button, pop-up) remain unique per ID.

Popup behavior: Pop-up widgets are shown only once per day per unique ID. After showing, a cookie if-popup-{id} is set for 1 day to prevent repeated displays.

Widget Configuration

interface WidgetConfig {
  id: string; // Unique identifier
  type: 'page-body' | 'float-button' | 'pop-up';
  timeout?: number; // Delay for pop-up (in seconds)
  container?: string; // CSS selector for page-body
  iframeSrc?: string; // Custom iframe source URL (defaults to https://if-form-staging.up.railway.app)
}

Build Formats

  • UMD — universal module for CDN and direct inclusion via <script> (minified, main file index.js)
  • ES — for modern bundlers and <script type="module"> (minified, file index.es.js)

Usage Examples

Data attributes approach

<!-- Include script in head with async -->
<script async src="https://unpkg.com/interactiveform-embedder@latest/dist/index.js"></script>

<!-- Multiple page-body widgets with the same ID are allowed -->
<div data-if-id="xxxxxxxxxxxxxxxxxxxxxxxx" data-if-type="page-body"></div>
<div data-if-id="xxxxxxxxxxxxxxxxxxxxxxxx" data-if-type="page-body"></div>

<!-- Other widget types remain unique per ID -->
<div data-if-id="xxxxxxxxxxxxxxxxxxxxxxxx" data-if-type="float-button"></div>
<div data-if-id="xxxxxxxxxxxxxxxxxxxxxxxx" data-if-type="pop-up" data-if-timeout="10"></div>

<!-- With custom iframe source -->
<div
  data-if-id="xxxxxxxxxxxxxxxxxxxxxxxx"
  data-if-type="page-body"
  data-if-iframe-src="https://custom-domain.com"
></div>

### GTM-like approach with ifLayer

```html
<!-- Include script in head with async -->
<script async src="https://unpkg.com/interactiveform-embedder@latest/dist/index.js"></script>

<script>
  window.ifLayer = window.ifLayer || [];
  window.ifLayer.push({
    id: 'xxxxxxxxxxxxxxxxxxxxxxxx',
    type: 'page-body',
    container: '#form-container',
  });
</script>

Programmatic creation

import { Embedder } from 'interactiveform-embedder';

const embedder = new Embedder();
embedder.addWidget({
  id: 'xxxxxxxxxxxxxxxxxxxxxxxx',
  type: 'page-body',
  container: '#form-container',
});

Inline insertion

<script>
  Embedder.createInlineWidget('xxxxxxxxxxxxxxxxxxxxxxxx', '800px', '400px');
  // With custom iframe source
  Embedder.createInlineWidget(
    'xxxxxxxxxxxxxxxxxxxxxxxx',
    '800px',
    '400px',
    'https://custom-domain.com',
  );
</script>