Add the Pixboard rail to your site

The Pixboard rail is a slim, first-party ad column you run on your own site. Because the ads are served from your domain -- not a third-party script -- they render even for readers using an ad blocker, and you earn a share of the revenue they generate.

There are two ways in. Almost everyone should use the SDK (two lines). If your site isn't Node, the same SDK runs at the edge on your own domain. A fully manual, build-it-yourself path also exists for anyone who wants it.


What you get, in one minute

You'll need three values from your Pixboard dashboard (pixboard.ad/publishers/keys): your publisher id (pub), your API key, and your path prefix. The key is server-side only -- it never goes in a browser.


The fastest path: the SDK (Node / Express)

npm i pixboard-rail
import { pixboardRail } from 'pixboard-rail';

app.use(pixboardRail({
  pub:  'yoursite',
  key:  process.env.PIXBOARD_KEY,   // server-side only -- keep it in the environment
  path: 'YOUR_PATH',                // your blocker-safe path prefix
}));

That mounts the whole rail -- the ad feed, the image/click/video proxy, the badge, and the web-component script -- under /YOUR_PATH/, all same-origin and first-party.

Then on your page, paste the exact snippet from your dashboard (see the warning below):

<script src="/YOUR_PATH/<hash>.js"></script>
<px-YOUR_PATH></px-YOUR_PATH>

That's it. The component fetches the first-party feed, paints the tiles, and owns the hover card.

⚠️ Never hand-write the snippet. The script filename is hashed and the element tag is px-<your path> -- there is no /YOUR_PATH/rail.js and no <pixboard-rail>. Copy the snippet exactly as your dashboard (or railSnippet()) gives it. A stale or hand-typed snippet 404s the script and the rail silently never appears. If you upgrade the package, re-paste the snippet -- the derived names can change between versions.


Not a Node site? Run the SDK at the edge (PHP, .NET, Rails, static, WordPress)

The same hardened SDK ships a framework-neutral core that runs in a Cloudflare Worker / Deno / Vercel Edge / Netlify Edge function on your own domain. Your app is untouched -- you just route /YOUR_PATH/* to the function. The browser still only talks to your domain, so it's fully first-party.

import { createRailCore } from 'pixboard-rail/core';
import clientSrc from 'pixboard-rail/client-src';

let core;
export default {
  async fetch(request, env, ctx) {
    core ??= createRailCore({ pub: env.PIXBOARD_PUB, key: env.PIXBOARD_KEY, path: env.PIXBOARD_PATH, clientSrc });
    const res = await core.handle(request, { waitUntil: ctx.waitUntil.bind(ctx) });
    return res ?? fetch(request);   // a rail path is handled; everything else goes to your origin
  },
};

Route yoursite.com/YOUR_PATH/* at the function, keep your key in the platform's secrets, and paste the same page snippet. A static/Jamstack site works the same way -- the edge function is the backend for the rail path, so no server is required.


Make the ads match the page (optional, recommended)

Give the rail a coarse topic for the current page -- a section or genre, not per-article keywords -- and Pixboard biases the ads toward it. It's the page, never the reader: no cookies, no profile.

<px-YOUR_PATH context="webdev,javascript,hosting"></px-YOUR_PATH>

Use a small, fixed set of topic words per section (e.g. finance, webdev, gaming). A matching ad rises sharply; unmatched ads still rotate in, so the rail never goes empty. Leaving context off just gives the normal rotation -- it never hurts to send it.


Placement and appearance


What gets counted, and how you're paid

An impression is a deliberate look -- counted only once a reader has held a tile's hover card open for about one second (once per ad per page load), never on a passing mouse-over and never just on render. A tile nobody dwells on is not a look. This is metering for attention, not raw renders.

You don't implement any of this, and you can't inflate it: every look is booked against a tamper-proof token that Pixboard issues and verifies -- the SDK only relays it. You earn 65% of the revenue your looks generate; payouts run once you're owed $25. Your live earnings and payout status are always on your publisher dashboard.

If your key is domain-bound: pass domain: 'yoursite.com' to pixboardRail(...) (or set PIXBOARD_DOMAIN for the edge core) so your server-to-server calls are recognized and your looks are counted. If nothing is counting and you have a bound key, this is almost always why.


Upgrading the SDK

When you bump the package version, re-paste the page snippet from your dashboard or railSnippet(). The element tag, script filename, and CSS classes are derived per-publisher and can change between versions -- keeping an old snippet leaves the rail silently absent with no error. If a page ever requests an old-style path, your server logs one line telling you to re-paste.


Advanced: the manual path (no SDK)

You can integrate without the SDK by calling the JSON API from your server, rendering the tiles yourself, and reporting looks back -- but you then own the first-party proxy, the SSRF safety, the hover card's CSS containing-block handling, and the metering. The SDK exists so you don't have to. If you want the full manual walkthrough, sign in and see pixboard.ad/publishers/implement.

Quick API reference (both calls are server-to-server, with your x-pixboard-key):


Quick troubleshooting