Specify docs

Browser SDK

Reference for the Specify Browser SDK.

npm i @specify-sh/publisher-sdk

new Specify(config)

OptionRequiredDescription
publisherKeyyesYour key, which starts with spk_

Throws ValidationError on a malformed key.

serve()

serve(options): Promise<SpecifyAd | null>
serve(addresses, options): Promise<SpecifyAd | null>

Returns an ad, or null when there is nothing to show.

addresses takes one address or an array of them, up to 50 unique. Anything registered through identify() is included either way.

Pass null or undefined in the address position, or omit it entirely, and Specify tries to resolve the visitor from our cookies alone. That needs consent, and returns null without a request if there is neither. A call site with a maybe-connected wallet can therefore stay a single serve(wallet ?? null, options) rather than branching.

OptionRequiredDescription
imageFormatyesSee image formats
adUnitIdnoAn id of your choosing, so you can compare placements in reporting

serve() never throws for a failed request. A no-fill, an outage on our side and a network error all return null, so a bad minute on our infrastructure cannot break your page. It throws only for input it can reject before sending anything. See errors.

identify(addresses)

Registers one or more addresses to include in every later serve().

The client keeps the 50 most recently registered addresses. Throws ValidationError on a malformed address.

Sets and reads the consent signal for Specify's cookie, which recognises returning visitors across every site in our network.

Consent starts false. The SDK never stores it, so your consent platform stays the only source of truth and a withdrawal takes effect on the next serve(). If you have no consent platform, store the visitor's choice yourself and set it on each page load.

Without consent, ads still serve against the addresses you pass.

Image formats

FormatRatioPixelsBest for
LANDSCAPE16:9640 × 360Hero banners, featured placements
LONG_BANNER8.09:11456 × 180Header and footer placements, leaderboards
SHORT_BANNER16:5640 × 200Inline content, sidebars, mobile banners
NO_IMAGEn/atext onlyDense lists, text feeds, places an image would not fit

Preview each format, and how an ad looks under different configurations, in the playground.

SpecifyAd

PropertyTypeDescription
campaignIdstringUnique identifier for the ad campaign
adIdstringUnique identifier for this specific ad
headlinestringAd headline text (plain text, no markdown)
contentstringAd body content. Supports simplified markdown. Max 400 characters
ctaUrlstringCall-to-action URL
ctaLabelstringCall-to-action button text (plain text, no markdown)
imageUrlstring | nullURL to the ad image (null for NO_IMAGE placements)
communityNamestringName of the advertising community (plain text, no markdown)
communityLogostringURL to the community logo
imageFormatstringThe format returned (LANDSCAPE, LONG_BANNER, SHORT_BANNER, or NO_IMAGE)
adUnitIdstringEchoes the adUnitId from the request, when one was sent

Link your call-to-action to ctaUrl exactly as given.

Content formatting

content supports a small subset of markdown. Everything else is plain text.

FormatSyntaxExample
Bold**text****Join today**
Italic*text**Italic*
Underline__text____Out now__
Bullet points* item* Feature 1\n* Feature 2
Line breaks\nFirst line\nSecond line

Errors

ValidationError is thrown for invalid input before making a request:

  • a publisher key that is not spk_ followed by 30 characters
  • an address that is not 0x plus 40 hex characters
  • more than 50 unique addresses in one call

Everything else returns null.

import { ValidationError } from '@specify-sh/publisher-sdk';

try {
  const ad = await specify.serve(addresses, { imageFormat: ImageFormat.LANDSCAPE });
} catch (error) {
  if (error instanceof ValidationError) {
    console.error(error.message);
  }
}

On this page