The SDK never blocks your app. If everydeck cannot be reached, your app works unchanged. If the address, the key or the manifest digest is missing, the SDK switches itself off and says so at start.
Packages
The SDK has no runtime dependencies.
Install
Your agent installs the exact version everydeck names, with your app’s package manager:The three settings every client needs
Where each key goes is on Going live.
Browser
Browser options
Only these options are documented. Leave out the ones you do not need.
The web page also keeps up to 300 rejected events in the browser until the next visit. Turn that off with
persist: false.
What the browser SDK captures without code
- Unhandled errors and rejected promises.
- Errors written with
console.error. - Every failed request made with
fetchorXMLHttpRequest, also outside a flow. To your own hosts: network errors, 4xx and 5xx. A 401 counts only while a person is signed in. To other hosts: only 5xx. - Visits and sign-ins, once you tell the SDK who is signed in.
- Page speed. See Source maps and page speed.
People: setSubject and reset
CallsetSubject where the browser learns who is signed in, and reset where the person signs out.
setSubject(null)while the session is still loading is fine. It is no sign-out.- A reload with the same person is no new sign-in.
- Without
setSubject, every visit stays anonymous and Live shows A visitor. - If your app does not call
resetat sign-out, a new sign-in of the same person on the same device is not reported.
Flows in the browser: actions
Wrap each user action you want to follow inaction. Name it after the flow in your app map.
- The SDK reports start, end and failed requests of the action. It never claims a business success by itself.
- Use
ctx.fetchfor the requests of the action. For a data client like supabase-js, passctx.fetchas itsglobal.fetch. - Non-2xx answers, network errors and timeouts inside an action count as a failure, even if your app catches them.
operationIdandattemptIdlet browser and server share one run. A retry is a new attempt.
Expected answers
Some non-2xx answers are normal, like a 404 before a record exists. Declare them, so they open no case:throw new Error(message, { cause: response }). Then everydeck knows it is the same failure.
A result that ends in the browser
If a flow ends in the browser, with no server and no database write in between, send the result from inside the action:"source": "browser". everydeck accepts it from the public browser key only with this mark. A result from the server for the same run wins. If only the browser confirmed a fix, the case page and the protocol say so.
Requests that never answer
If a request of a flow waits 30 seconds without an answer, the SDK reports it as hung. It never cancels or changes your request. See Flows and journeys.CORS
Inside an action, the SDK adds three headers to captured requests:x-everydeck-operation-id, x-everydeck-attempt-id and x-everydeck-session-id. A request to another origin then sends a CORS preflight. Your API must allow these headers in Access-Control-Allow-Headers. Or exclude the address with correlate: (url) => false: the request is still captured, only without the link to your server. Check this before you go live.
Screens in apps without URL routing
- Expo Router: call
everydeck.screen(pathname)withusePathname()on each change. - Apps without routes: call
everydeck.screen("Checkout")with a fixed screen name. Never put a name, id or input into it.
Server
everydeckFromSupabase(…) reads these settings from your Supabase project instead. Then you set nothing at your host.
Server options
Results of flows: signal
Send a signal after your database committed the change:- The role of the step in your app map decides how a run ends, never the name of the signal.
- Use the same run id as the browser. It comes in the request header
x-everydeck-operation-id. - When a signal names a record, everydeck reads exactly that record again right after.
Errors
Your agent wires the central error path of your server, the place that turns an exception into a 500:- The error class is short, lowercase and stable, like
type_errororhttp_500. - With
exc, the SDK sends the stack and, for up to 5 frames in your own code, the line and 5 lines before and after. Libraries get no code lines. - The message must not contain personal data or secrets. The SDK also removes keys, tokens and e-mail addresses.
The setup does not add these one-line helpers by itself yet. Your agent wires the error path instead. Errors outside a request, like in a background job or at start, need your own
everydeck.error(…).Short-lived runtimes
In Edge Functions and serverless handlers, wait for the SDK before you answer:false means the events were not delivered.
Payments
Send payment events from your server, after your app stored the change. Only a server key may report payments.totalis in the main unit of the currency. Divide cents by 100, except for currencies without decimals like JPY or IDR.currencyis an ISO 4217 code.orderId(orcheckoutId) is required and counts once per event, so a webhook that arrives twice is safe.- Without a person and an organization, the payment counts for nobody, and the SDK warns. In a webhook nobody is signed in: take them from what your app stored with the checkout.
AI calls
Wrap each AI client where your app creates it. The wrapper returns the same client.Heartbeats
Every part of your app that must keep running sends a heartbeat. Without a number, the SDK uses 300 seconds:Messages and usage
everydeck.messageSent({ conversationType, conversationRef, senderRef, text, appHosts })sends only metadata: a checksum of the text and whether it holds a phone number, a foreign link or a payment request. The text never leaves your app. See Moderation.everydeck.usage(kind, type, ref)counts views, saves, contacts, impressions and clicks of a record.kindisview,save,contact,impressionorclick.everydeck.search(group, results)counts searches per group, like an area. Never pass the search text.
Versions: release key “auto”
Let the SDK find the version of your app. UsereleaseKey: "auto" on the server. In the browser, pass the value your server found, or resolve it at build time with resolveReleaseKey() if your app has no server (for example in Vite’s define).
The rule:
EVERYDECK_RELEASE_KEY, if it is set to something other thanauto.- Otherwise the commit of the deploy, from your host or CI (for example
GITHUB_SHA,VERCEL_GIT_COMMIT_SHA,RENDER_GIT_COMMIT,CF_PAGES_COMMIT_SHA,COMMIT_REF,SOURCE_VERSION,CI_COMMIT_SHA), asgit:and the first 12 characters. - Otherwise your local git commit, with
+dirty.and a short hash when there are uncommitted changes.
EVERYDECK_RELEASE_KEY. Keep your app’s runtime files, like logs, ignored by git, or they change the version.