You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

@topsort/banners

Package Overview
Dependencies
Maintainers
2
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@topsort/banners

A web component for displaying Topsort banner ads.

latest
Source
npmnpm
Version
0.8.1
Version published
Weekly downloads
65
-76.95%
Maintainers
2
Weekly downloads
 
Created
Source

CI codecov npm version npm downloads license GitHub Repo stars

Topsort Banner Ad Web component

banners.js is Topsort's official Web Component SDK for rendering sponsored banner ads on merchant storefronts. It handles auction requests, banner rendering, and telemetry automatically. A Topsort account and API token are required.

Usage

Directly from unpkg.com

<script>
  // Must come first — analytics.js reads window.TS on load
  window.TS = {
    token: "<your topsort api key>",
  };
  // Custom behavior can be configured for each site.
  window.TS_BANNERS = {
    // handle the destination link
    getLink(banner) {
      return `https://example.com/${banner.id}`;
    },
    // handle loading/fetching state
    getLoadingElement() {
      const el = document.createElement("div");
      el.innerText = "Loading...";
      return el;
    },
    // handle errors
    getErrorElement() {
      const el = document.createElement("div");
      el.innerText = "Error loading banner";
      return el;
    },
  };
</script>
<script
  async
  type="module"
  src="https://unpkg.com/@topsort/banners/dist/banners.mjs"
></script>
<script async type="module" src="https://unpkg.com/@topsort/analytics.js"></script>
<body>
  <topsort-banner width="600" height="400" id="<your slot id>"></topsort-banner>
</body>

Legacy Systems (IIFE Bundle)

For environments that don't support ES modules (e.g., Magento), use the IIFE bundle:

<script src="https://unpkg.com/@topsort/banners/dist/banners.iife.js"></script>
BundleSize (gzip)Size (brotli)
banners.mjs (ES module)12.40 kB11.01 kB
banners.iife.js (IIFE)11.18 kB10.08 kB

Rendering multiple banners with one slot ID

You can render multiple banners using the same slot ID and dimensions by setting up a banner context. This is useful when you want to run an auction with multiple results. To do that you have to pass the attribute context="true" to the topsort-banner and use topsort-banner-slot as children elements.

<topsort-banner context="true" width="600" height="400" id="<your slot id>">
  <topsort-banner-slot rank="1"></topsort-banner-slot>
  <topsort-banner-slot rank="2"></topsort-banner-slot>
  <topsort-banner-slot rank="3"></topsort-banner-slot>
</topsort-banner>

Predefined content mode

Instead of replacing a placeholder with Topsort-generated DOM, you can annotate your own markup with data-ts-field attributes and have banners.js mutate only the targeted fields in place. All other markup — classes, ARIA attributes, styles, event listeners — is left untouched. If the auction returns no winners or fails, the predefined content is shown as-is with no changes.

Sizing is your responsibility. banners.js only fills in content fields and telemetry attributes — it never writes width, height, or any other style to your template elements. Set dimensions with your own CSS or HTML attributes (see examples below).

Opt in by adding the predefined attribute to <topsort-banner> (standalone) or to each <topsort-banner-slot> (context mode).

Binding convention

Use data-ts-field to bind content keys from the auction response to element attributes or text.

Use key:target syntax to specify exactly which content key maps to which attribute:

<img data-ts-field="mainImage:src" src="/fallback.jpg" />
<a data-ts-field="target:href" href="/fallback">Click</a>
<span data-ts-field="headline:textContent">Default headline</span>

Use textContent as the target to set the element's text content.

The target attribute must already exist on the element — banners.js only overwrites existing attributes, never creates them. If a binding targets an attribute that doesn't exist, it is skipped and a warning is logged. This catches typos and ensures your template always has fallback values for graceful degradation when the auction fails or returns no winners.

Multiple bindings

Comma-separate multiple key:target pairs to set several attributes on one element:

<img data-ts-field="mainImage:src, altText:alt" src="/fallback.jpg" alt="Fallback" />

If the auction response only includes some keys, only matching bindings are applied — unmatched attributes keep their original values.

Implicit binding (legacy)

A bare key (without :target) infers the target from the element type:

ElementProperty set
<a>href
<img>, <video>, <source>src
All otherstextContent

data-ts-attr="<attributeName>" can override the default target for bare keys.

Implicit binding still works but is deprecated. Prefer explicit key:target syntax for clarity and to avoid tag-based inference surprises.

Click tracking

Add data-ts-clickable to the element that should be the click-tracking surface for analytics.js. If omitted, the first child element is used.

Single winner

<topsort-banner predefined width="600" height="400" id="slot-1">
  <div class="brand-banner" data-ts-clickable>
    <a data-ts-field="target:href" href="/brands/featured" aria-label="Featured Brand">
      <img data-ts-field="mainImage:src, altText:alt" src="/fallbacks/featured.jpg"
           alt="Explore our featured brands" width="600" height="400" loading="lazy" />
    </a>
    <h2 data-ts-field="default-Headline:textContent">Featured Brand</h2>
  </div>
</topsort-banner>

Multiple winners (context mode)

<topsort-banner context width="600" height="400" id="slot-1">
  <topsort-banner-slot predefined rank="1">
    <div class="product-card" data-ts-clickable>
      <a data-ts-field="target:href" href="/default-1">
        <img data-ts-field="mainImage:src" src="/default-1.jpg" width="600" height="400" />
      </a>
      <h3 data-ts-field="default-Headline:textContent">Default Product 1</h3>
    </div>
  </topsort-banner-slot>
  <topsort-banner-slot predefined rank="2">
    <div class="product-card" data-ts-clickable>
      <a data-ts-field="target:href" href="/default-2">
        <img data-ts-field="mainImage:src" src="/default-2.jpg" width="600" height="400" />
      </a>
      <h3 data-ts-field="default-Headline:textContent">Default Product 2</h3>
    </div>
  </topsort-banner-slot>
</topsort-banner>

Banner Attributes

NameTypeDescription
widthNumberBanner width
heightNumberBanner height
idStringThe slot ID for this banner
category-id*Optional StringThe category ID of the current page
category-ids*Optional StringComma (,) separated list of category IDs, the item must match all
category-disjunctions*Optional StringComma (,) separated list of category IDs, the item must match any
search-queryOptional StringThe search query of the current page
locationOptional StringThe location for geotargeting
new-tabOptional BooleanOpens the banner's link in a new tab (defaults to false)
contextOptional BooleanUses the element as a context provider to render multiple banners
predefinedOptional BooleanMutates annotated child elements in place instead of replacing them

* Only one of [category-id, category-ids, category-disjunctions] must be set. If multiple are set, only the first will be considered, in that order.

Styling

The banner component exposes --ts-banner-width and --ts-banner-height CSS custom properties on the <topsort-banner> element. These reflect the width and height attributes set on the element and are useful for sizing child elements to match the configured dimensions.

The inner container uses the class ts-banner, making it easy to target with standard CSS selectors.

/* Style the inner container */
.ts-banner {
  padding: 10px;
  border-radius: 8px;
  overflow: hidden;
}

/* Size child elements to match the configured banner dimensions */
.ts-banner img {
  width: var(--ts-banner-width);
  height: var(--ts-banner-height);
  object-fit: cover;
}

For responsive layouts, use standard CSS on the host element and its children rather than trying to override the custom properties:

/* Make the banner fill its container */
topsort-banner {
  display: block;
  width: 100%;
}

.ts-banner img {
  width: 100%;
  height: auto;
}

Banner Slot Attributes

NameTypeDescription
rankNumberThe ranking of the slot. Ranks should be sorted the same as the winning bids. The lower the rank, the higher the bid
predefinedOptional BooleanMutates annotated child elements in place instead of replacing them

Banner Behaviors

Function NameArg typeReturn TypeDescription
getLinkBannerstringGenerates a URL from a banner response
getLoadingElementHTMLElementA custom element to be shown when the banner is loading.
getErrorElementErrorHTMLElementA custom element to be shown when the banner errors.
getNoWinnersElementHTMLElementA custom element to be shown when the auction returns no banner.
getBannerElementBannerHTMLElementA custom clement to be shown when a banner is loaded.

Banner Interface

NameTypeDescription
type"product" | "vendor" | "brand" | "url"The type of the winning entity, represented by the banner.
slotIdstringThe ID of the winning entity. If the entity is of type URL, this is the URL.
resolvedBidIdstringThe corresponding auction ID of the winning entity.
asset[{ url: string; content?: Record<string, string> }]An array of assets. content is a key-value map used in predefined content mode.

Custom User ID (Optional)

If you want to use your own user identification system instead of the automatic opaque user ID, you can override the getUserId function in the window.TS configuration.

Your custom getUserId function should return the user's ID as a string. You are responsible for generating and persisting the ID (e.g., in a cookie or local storage).

window.TS = {
  token: "<your topsort api key>",
  getUserId() {
    // Return your custom user ID
    // This will be used for both auction requests and event reporting
    return globalUserId ?? generateAndStoreUserId();
  },
};

This configuration needs to be set before analytics.js is loaded or imported.

Listening to events

The banner component emits an event when the state changes. You can listen to this event to write custom logic. The various states are loading, ready, error, and nowinners.

document.querySelector('#my-slot-id').addEventListener('statechange', (event) => {
  console.log(event.detail); // { status: 'ready', banner: { ... } }
});

Playground

Try the library instantly — no setup required — at the live demo:

topsort.github.io/banners.js

Enter your API token and a slot ID to render a real banner and copy the resulting HTML snippet.

Running locally

git clone https://github.com/Topsort/banners.js.git
cd banners.js
pnpm install
pnpm run dev

You can find your API token and slot IDs at app.topsort.com.

Keywords

banners

FAQs

Package last updated on 02 Mar 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts