Why am I not seeing ads?
Follow this decision tree in order. The fastest first check is to switch your server integration to a sandbox test key. sk_test_... always returns a mock creative, never touches live SSP traffic, and never generates billable revenue.
1. Check your API key
- Confirm the key exists in the dashboard and still shows status
active. - Use a secret key on the server and a publishable key only in the browser activation flow.
- Confirm the environment matches your expectation:
sk_test_...for sandbox,sk_live_...for production.
2. Check your request
job_typeis required.slots_requestedmust be at least1.- Confirm
getDecision()returns a response and inspectdecision.fill.
3. Check the no-fill reason
When decision.fill === false, inspect decision.no_fill_reason.
no_demand
No SSP responded. Normal during early testing. Use a sandbox test key to force a mock ad.
frequency_cap_exceeded
The project-level or session-level ad cap was hit. Wait and retry.
policy_block
The firewall or policy layer blocked the slot.
format_mismatch
No creative matched the allowed formats or slot dimensions.
timeout
The SSP did not respond before the partner timeout.
risk_suppressed
wavebird suppressed the request because the traffic pattern looked unusual.
content_safety
The prompt topic matched a high-risk category and the firewall suppressed the ad before any bid request was sent.
4. Check your widget
- Confirm
<WavebirdAd />receives the same decision object you fetched. - Confirm
sendBeaconis connected. - Confirm the component is mounted and visible in the DOM.
5. Check your console
SDK failures are fail-silent by default so your app keeps working. Add an onError observer while you integrate so failed requests and contract mismatches land in your own logs:
observability.ts
typescript
new CslClient({
baseUrl: "https://api.wavebird.ai",
getApiKey: () => "sk_test_...",
options: {
onError: (error) => {
console.error(error.code, error.message, error.cause);
},
},
});6. Still stuck?
Email support@wavebird.ai with your support reference ID and the last five request IDs from your dashboard logs.
API first, Script Tag second, SDK third
These pages are the advanced package layer for teams that intentionally choose @csl/wrapper-sdk. Primary onboarding still lives in the API docs, and browser-first installs should start with the Script Tag. Use contact only when you want rollout review, enterprise coordination, or help with non-standard integration constraints. Beacon billing rules live in SDK Concepts.