Skip to main content

Embedded Sponsorship SDK

This JavaScript SDK is the recommended integration approach with the Embedded Sponsorship API. It handles sponsorship status checks, button rendering, iframe lifecycle, and event communication.

SDK Versions​

The SDK version is selected by the path in your script src. New integrations should use v1, and existing v0 integrations should upgrade — see Version History for what each version contains.

VersionScript URLStatus
v1https://api.ziprecruiter.com/ats-embed/v1/sdk.jsCurrent. Rolling build — picks up fixes and new features automatically.
v0https://api.ziprecruiter.com/ats-embed/v0/sdk.jsLegacy, still supported. Frozen build — byte-for-byte stable (so it can be pinned with a Subresource Integrity hash), but it receives no fixes or new features.

To upgrade from v0 to v1, change the version segment in your script src. Nothing else in your integration changes: the SDK's JavaScript API, attributes, events, and CSS custom properties are unchanged, and the buttons render identically unless you opt into the ZipRecruiter logo.

note

The version in the SDK URL selects the SDK bundle only. Your server-side token exchange and sponsored status calls are unaffected and need no change — the /ats-embed/v0/api/… paths shown throughout these docs remain supported. The v1 SDK calls the equivalent /ats-embed/v1/api/… routes on your behalf; both behave identically.

Because v1 is a rolling build, do not pin it with an SRI hash — the hash will break the next time the bundle is updated. Pin SRI hashes only against v0.

If your src currently points at /ats-embed/v0.1/sdk.js, that was an interim alias that serves the same bundle as v1. Switch it to v1; no other change is needed.

Script Tag Setup​

Add the SDK script to your ATS pages:

SDK script tag
<script
src="https://api.ziprecruiter.com/ats-embed/v1/sdk.js"
data-partner-token="YOUR_ACCESS_TOKEN"
data-base-url="https://api.ziprecruiter.com"
async
></script>

Mark each job element with its external job ID:

Job element markup
<div class="job-listing" data-zr-job-id="job-001">
<h3>Senior Software Engineer</h3>
<p>San Francisco, CA</p>
</div>

The SDK scans the page for elements with data-zr-job-id attributes, injects a widget button into each one, and keeps the buttons in sync with sponsorship state.

Attributes​

SDK attributes reference
AttributeOnRequiredDescription
data-partner-token<script>YesAccess token from the token exchange endpoint.
data-base-url<script>YesZipRecruiter base URL.
data-zr-container<script> or any ancestor elementNoCSS selector or element that scopes the SDK's DOM scanning and MutationObserver. Defaults to document.body. Use this when your job list lives inside a specific container to avoid unnecessary DOM observation.
data-show-logo<script>NoSet to "true" to prepend the ZipRecruiter logo to the sponsorship button. Off by default. v1 only — see Displaying the ZipRecruiter logo.
data-zr-job-idJob elementYes (per job)External job ID. The SDK injects a widget button into this element.
Example with a scoped container
<script
src="https://api.ziprecruiter.com/ats-embed/v1/sdk.js"
data-partner-token="YOUR_ACCESS_TOKEN"
data-base-url="https://api.ziprecruiter.com"
data-zr-container="#job-list"
async
></script>

<div id="job-list">
<div data-zr-job-id="job-001">...</div>
<div data-zr-job-id="job-002">...</div>
</div>

Programmatic Init​

If you need to initialize the SDK after page load (e.g., in a single-page app), skip the script tag attributes and call init() directly:

Programmatic init example
ZipRecruiter.init({
partnerToken: "YOUR_ACCESS_TOKEN",
baseUrl: "https://api.ziprecruiter.com",
container: document.getElementById("job-list"), // or a CSS selector string
showLogo: true, // optional: show the ZipRecruiter logo on the button (v1 only)
});

All config properties are optional when the corresponding data-* attributes are present on the script tag. When both are provided, the init() config takes precedence.

JavaScript API​

The SDK is exposed as window.ZipRecruiter.

JavaScript API methods
MethodSignatureDescription
initinit(config?)Initialize the SDK. Uses script tag attributes if config is omitted.
setPartnerTokensetPartnerToken(token)Replace the access token without re-initializing the SDK. v1 only — see Updating the access token.
renderrender(jobId, container)Manually render a widget for a job in a given DOM element.
destroydestroy(jobId)Remove the widget for a job.
sponsorsponsor(jobId)Programmatically open the sponsorship modal for a job.
onon(event, callback)Subscribe to an SDK event.
offoff(event, callback)Unsubscribe from an SDK event.
teardownteardown()Stop the SDK: disconnects the MutationObserver, destroys all widgets, and closes the modal.
JavaScript API usage example
const onSponsored = (data) => {
console.log("Jobs sponsored:", data.jobIds);
refreshJobList();
};

ZipRecruiter.on("job:sponsored", onSponsored);

ZipRecruiter.render("job-001", document.getElementById("my-job-container"));
ZipRecruiter.sponsor("job-001");

// Later: clean up a single widget
ZipRecruiter.destroy("job-001");

// Or unsubscribe from an event
ZipRecruiter.off("job:sponsored", onSponsored);

// Or tear down everything
ZipRecruiter.teardown();

Updating the access token​

An access token is issued for one email, externalEmployerId, and facilityId. If any of these changes while the page stays loaded — for example, a single-page app switching users, employers, or facilities — request a new token from the token exchange on your server and pass it to the SDK:

Swap in a new access token
ZipRecruiter.setPartnerToken("NEW_ACCESS_TOKEN");

setPartnerToken closes any sponsorship modal opened under the previous token and refreshes every button's sponsorship state under the new one. Your event subscriptions and any widgets added with render() are kept. Passing the token the SDK already holds does nothing. A full page load picks up the new script tag's token on its own, so no call is needed then.

Until you swap the token, the SDK keeps acting for the previous user, employer, and facility: buttons can show the wrong sponsorship state, and anything the user does in the widget is attributed to the previous context.

note

setPartnerToken requires v1. The v0 bundle does not include it — see SDK Versions. On v0, call teardown() and then init() with the new token instead. That discards your event subscriptions and any render()ed widgets, so register them again afterwards.

SDK Events​

Subscribe with ZipRecruiter.on(event, callback) and unsubscribe with ZipRecruiter.off(event, callback).

SDK events reference
EventPayloadWhen
job:sponsored{ jobId, jobIds }User completes the sponsorship flow (payment processed, jobs activated).
job:unsponsored{ jobId }A job's sponsorship has been stopped.
modal:open{ jobId }The sponsorship or manage modal opens.
modal:close{}The modal closes (user closes it or a flow completes).

Styling​

SDK widget buttons are rendered inside a closed shadow DOM, so your page styles do not affect them. To customize button appearance, set CSS custom properties on an ancestor of the data-zr-job-id element (custom properties inherit across shadow boundaries):

CSS custom properties reference
PropertyDefaultControls
--zr-sponsor-btn-bg#00706C"Sponsor" button background color.
--zr-sponsor-btn-color#fff"Sponsor" button text color.
--zr-manage-btn-bg#9CDCD6"Manage" button background color.
--zr-manage-btn-color#1a1a1a"Manage" button text color.
.job-listing {
--zr-sponsor-btn-bg: #1a73e8;
--zr-sponsor-btn-color: #ffffff;
--zr-manage-btn-bg: #e8f0fe;
--zr-manage-btn-color: #1a73e8;
}

By default the sponsorship button is text only. You can prepend the ZipRecruiter logo to the button by opting in — set data-show-logo="true" on the script tag, or pass showLogo: true to init(). It is off by default, so leaving it unset keeps the text-only button.

note

This option requires v1. The v0 bundle does not include it — see SDK Versions.

Enable the logo via the script tag
<script
src="https://api.ziprecruiter.com/ats-embed/v1/sdk.js"
data-partner-token="YOUR_ACCESS_TOKEN"
data-base-url="https://api.ziprecruiter.com"
data-show-logo="true"
async
></script>
Enable the logo via init()
ZipRecruiter.init({
partnerToken: "YOUR_ACCESS_TOKEN",
baseUrl: "https://api.ziprecruiter.com",
showLogo: true,
});

The logo is the ZipRecruiter mark, rendered in the ZipRecruiter brand green (#57DE70). It uses a fixed color, so it stays on-brand and is not affected by your --zr-sponsor-btn-color / --zr-manage-btn-color customizations. You cannot substitute your own image through this option. To use a fully custom button, render your own element and call ZipRecruiter.sponsor(jobId) when it is clicked.

Version History​

This section covers the SDK bundle only. See SDK Versions for the script URL of each version.

v1 — current​

https://api.ziprecruiter.com/ats-embed/v1/sdk.js (June 2026)

v1 is a rolling build: the entries below arrived on the same URL without any change on your side. Everything documented on this page works in v1.

Added in v1

setPartnerToken() for in-place token swaps (August 2026)

Replaces the access token without re-initializing the SDK, for pages where the user, employer, or facility changes without a page load. See Updating the access token.

Opt-in ZipRecruiter logo on the sponsorship button (July 2026)

data-show-logo="true" on the script tag, or showLogo: true in init(), prepends the ZipRecruiter mark to the button in brand green. Off by default, so buttons are unchanged unless you opt in. See Displaying the ZipRecruiter logo.

Button impression and click reporting

The SDK reports two events to ZipRecruiter — one when it renders sponsorship buttons, one when a button is clicked — so sponsorship performance can be measured end to end. This needs no configuration and adds no partner-side work. The requests are fire-and-forget: they never block button rendering and never surface errors on your page. No end-user or applicant data is sent — only the job identifiers you already supply via data-zr-job-id, the button state, and a count of buttons rendered.

Fixed in v1

render() now re-mounts a widget that was detached from the DOM

Previously, if your page rebuilt the markup around a button (for example, a single-page app re-rendering a job list), calling render(jobId, container) again was a silent no-op because the SDK still considered that job rendered — so the button disappeared permanently. render() now detects the detached widget and re-mounts it. Only affects integrations that call render() directly; script-tag auto-initialization was never affected.

Calling init() a second time now tears down the previous instance

Previously a repeat init() — for example, to swap in a refreshed access token — left the prior instance's DOM observer and message listener alive. That instance kept running, which duplicated sponsored-status requests on every DOM change and fired SDK events twice per action. The prior instance is now shut down before the new one starts.

v0 — legacy​

https://api.ziprecruiter.com/ats-embed/v0/sdk.js (frozen June 2026)

The initial public SDK, frozen as a byte-stable bundle so partners who pin an SRI hash are not broken by later releases. It remains supported, but receives no fixes or new features — including the v1 entries above.

What v0 includes
  • Automatic sponsorship button injection into every data-zr-job-id element, rendered in a closed shadow DOM and themeable through the CSS custom properties
  • Batched sponsorship status lookup, so one request covers every job on the page
  • Sponsorship and manage flows in a hosted iframe modal
  • The init / render / destroy / sponsor / on / off / teardown JavaScript API and the four SDK events
  • data-zr-container to scope DOM scanning to a specific container
  • A distinct state for jobs ZipRecruiter has not ingested yet, so no button is offered for a job that cannot be sponsored
  • Origin validation on all messages between the SDK and the ZipRecruiter iframe, in both directions