Browser SDK
Reference for the Specify Browser SDK.
npm i @specify-sh/publisher-sdknew Specify(config)
| Option | Required | Description |
|---|---|---|
publisherKey | yes | Your 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.
| Option | Required | Description |
|---|---|---|
imageFormat | yes | See image formats |
adUnitId | no | An 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.
Consent
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
| Format | Ratio | Pixels | Best for |
|---|---|---|---|
LANDSCAPE | 16:9 | 640 × 360 | Hero banners, featured placements |
LONG_BANNER | 8.09:1 | 1456 × 180 | Header and footer placements, leaderboards |
SHORT_BANNER | 16:5 | 640 × 200 | Inline content, sidebars, mobile banners |
NO_IMAGE | n/a | text only | Dense lists, text feeds, places an image would not fit |
Preview each format, and how an ad looks under different configurations, in the playground.
SpecifyAd
| Property | Type | Description |
|---|---|---|
campaignId | string | Unique identifier for the ad campaign |
adId | string | Unique identifier for this specific ad |
headline | string | Ad headline text (plain text, no markdown) |
content | string | Ad body content. Supports simplified markdown. Max 400 characters |
ctaUrl | string | Call-to-action URL |
ctaLabel | string | Call-to-action button text (plain text, no markdown) |
imageUrl | string | null | URL to the ad image (null for NO_IMAGE placements) |
communityName | string | Name of the advertising community (plain text, no markdown) |
communityLogo | string | URL to the community logo |
imageFormat | string | The format returned (LANDSCAPE, LONG_BANNER, SHORT_BANNER, or NO_IMAGE) |
adUnitId | string | Echoes 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.
| Format | Syntax | Example |
|---|---|---|
| Bold | **text** | **Join today** |
| Italic | *text* | *Italic* |
| Underline | __text__ | __Out now__ |
| Bullet points | * item | * Feature 1\n* Feature 2 |
| Line breaks | \n | First 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
0xplus 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);
}
}