Adjoin
Sign inMonetize my app
← Documentation

SDK reference

One script, five calls. No cookies, no identifiers, and a failed ad never blocks your page.

Load

Put a container where the ad goes and load the script once. The container id is adjoin- plus the placement id.

<!-- one script per page; data-placement renders that slot automatically -->
<div id="adjoin-plc_ab12" data-format="card"></div>
<script async src="https://cdn.adjoin.dev/v1.js" data-placement="plc_ab12"></script>
data-placement
Renders this placement as soon as the page is ready.
data-format
On the container: banner, card, inline_native, sidebar or newsletter. Default card.
data-tenant
Partner slug, when you came through a partner (see Partner integration).
data-analytics="off"
Turns off the free pageview analytics.

Sizes: banner 728×90 · card 320×250 · inline_native 600×120 · sidebar 300×250 · newsletter 600×200

adjoin.render(options)

Renders a placement into its container. The slot height is reserved first, so there is no layout shift, and the ad lives in a Shadow DOM so your CSS and ours never meet. If nothing fits, the slot collapses to zero height.

adjoin.render({
  placement: 'plc_cd34',        // required — the id from your dashboard
  format: 'sidebar',            // banner | card | inline_native | sidebar | newsletter
  onEmpty: () => showMyOwnPromo()  // optional — called when the slot collapses
});

adjoin.trigger(moment, options?)

Marks a moment in your app — signup_complete, empty_state, quota_hit and so on. It is recorded even without a placement, so your funnel still counts if you turn ads off.

// record a moment; with a placement it also renders an ad there
adjoin.trigger('signup_complete', { placement: 'plc_ab12' });

adjoin.pageview(path?)

Free analytics. Only the first two path segments are sent, and ids in them are replaced with :id.

// sent automatically on load; call it yourself on client-side route changes
adjoin.pageview('/pricing');

<!-- or turn analytics off -->
<script async src="https://cdn.adjoin.dev/v1.js" data-analytics="off"></script>

adjoin.segment(label, on?)

Audience labels. Tag the current session with a word that describes it — plan, role, stage. Advertisers can target or exclude a label, so labelled inventory earns more. The label lives in this tab only (sessionStorage) and is sent only with this site's ad requests and pageviews; it never follows a visitor to another site. Only per-label pageview totals are stored. Format: lowercase letters, digits, _ : -, up to 32 characters, no runs of 6+ digits. Up to 5 per session. A label becomes targetable once it reaches 100 pageviews across the network in 7 days.

// label this visitor's session — plain words, never ids or emails
adjoin.segment('plan:free');
adjoin.segment('role:developer');
adjoin.segment('plan:free', false);   // remove one
adjoin.segment(null);                 // remove all

// suggested labels: plan:free · plan:paid · plan:trial · role:developer · role:designer
//                   role:founder · stage:onboarding · stage:active · intent:upgrade

adjoin.convert(valueUsd?, orderId?)

For advertisers on CPA or affiliate. Call it on your own site after a purchase. The click token from the ad is kept in this tab only (sessionStorage), so it links conversions within the same visit. Pass an order id: the same order is never charged twice, and you can refund it by that id. For conversions days later, use server-to-server (REST API).

// on your own site, after checkout
adjoin.convert(29.00, 'order_1234');   // value in USD, your order id

Privacy

No cookies, no localStorage, no fingerprinting. Visitors are counted with a hash that changes every day, so the same person cannot be linked from one day to the next.

Questions: [email protected]