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

@gravity-ai/embed

v0.1.1

Published

Drop-in ad rendering widget — one script tag, no React required

Readme

@gravity-ai/embed

Drop-in ad rendering widget — one <script> tag, no React required. ~4KB gzipped.

Publishers load a single JS file and get fully rendered, themed, viewability-tracked ads with zero framework dependencies.

Quick Start

<script src="https://cdn.jsdelivr.net/npm/@gravity-ai/embed/dist/gravity-ad.js"></script>

<div data-gravity-ad
     data-api-key="pub_xxxxx"
     data-placement="below_response"
     data-placement-id="my-slot"
     data-variant="card"
     data-query="I need running shoes">
</div>

That's it. The widget auto-initialises on page load, calls the Gravity API, renders the ad, and fires an impression when the ad enters the viewport.

Pin a version for production (@gravity-ai/[email protected]), or bundle it yourself:

npm install @gravity-ai/embed

Variants

Six built-in templates optimised for AI surfaces:

| Variant | Best for | |---------|----------| | card (default) | Sidebar widgets, standalone placements | | inline | Horizontal banner-style, between content | | minimal | Minimal left-border style, blends into text content | | bubble | Chat-style bubble, conversational UIs | | suggestion | Pill-style "you might also want to try", below input bars | | text-link | Inline hyperlink within paragraph text |

Theming

Override CSS custom properties on the container (or any ancestor) to match your platform:

[data-gravity-ad] {
  --gravity-bg: #1a1a2e;
  --gravity-text: #eaeaea;
  --gravity-text-muted: #a0a0b0;
  --gravity-accent: #7c6ff7;
  --gravity-border: #3a3a4e;
  --gravity-radius: 12px;
  --gravity-font: "IBM Plex Sans", sans-serif;
}

Data Attributes

| Attribute | Required | Description | |-----------|----------|-------------| | data-gravity-ad | Yes | Marks the element as a Gravity ad slot | | data-api-key | Yes | Publisher API key | | data-placement | Yes | Placement position (e.g. below_response) | | data-placement-id | Yes | Unique slot ID for tracking | | data-query | Yes | User's query for contextual matching | | data-variant | No | Template variant (default: card) | | data-session-id | No | Session ID for consistent bucketing | | data-user-id | No | User ID for personalisation | | data-api-url | No | Custom API endpoint | | data-show-label | No | Show "Sponsored" label (default: true) | | data-label-text | No | Custom label text (default: Sponsored) | | data-theme | No | auto (default) matches the page's light/dark surface; light/dark pin the palette. Publisher-defined --gravity-* variables always win | | data-test-ad | No | Use test ads (true/false; omit for server default) | | data-relevancy | No | Minimum relevancy threshold (0-1) |

Programmatic API

For SPAs or dynamic content, mount ads programmatically:

GravityAd.mount({
  container: document.getElementById('my-ad'),
  apiKey: 'pub_xxxxx',
  placement: 'below_response',
  placementId: 'my-slot',
  query: 'I need running shoes',
  variant: 'card',
  onAd: (ad) => console.log('Ad loaded:', ad),
});

Variant auto-selection

The widget resolves which template to use in this priority order:

  1. data-variant attribute on the element (explicit publisher choice)
  2. composition.rendererKey from the ad response (experiment arm)
  3. ad.renderer_key from the ad response (placement default)
  4. ad.variant from the ad response
  5. Falls back to card

This means A/B tests that swap renderer_key via experiments work automatically — the widget renders whatever template the engine assigns.

Impression Tracking

Impressions fire on viewability (50% of the ad visible in the viewport via IntersectionObserver), not on API response. This matches IAB viewability standards and prevents billing for ads that are never seen.

SPA Support

The widget uses a MutationObserver to detect dynamically added [data-gravity-ad] elements. In a SPA, just append the element to the DOM and the widget handles the rest — no manual mount() call needed.