Skip to Content
CEC Feedback Docs
Installing

JavaScript SDK

Identify reporters, attach metadata and open the widget from the site's own code.

Once the snippet is on a page, window.CecFeedback lets the site identify who is leaving feedback, attach custom metadata, and open the widget from its own buttons. To read or change feedback from a server or a script, use the REST API instead.

Calling the SDK before the widget loads

The loader is async, so the site's code can run before it does. Put this one-liner above the snippet. It queues every call, and the widget replays the queue in order once it loads:

<script>window.CecFeedback||(function(p){p.q=[];['identify','setMetadata','open','close','hide','show','on'].forEach(function(m){p[m]=function(){p.q.push([m,[].slice.call(arguments)])}});window.CecFeedback=p})({});</script>
<script async src="https://feedback-api.cec.dev/w/loader.js" data-project="pk_…"></script>

While calls are queued they return undefined, so write await CecFeedback.identify(…) rather than .then(). off only exists once the widget has loaded.

TypeScript types are served at https://feedback-api.cec.dev/w/cec-feedback.d.ts. Save the file into your project (inside your tsconfig include) and window.CecFeedback is typed everywhere.

Methods

CallWhat it does
identify({ name, email })Remembers who is leaving feedback on this device, so the widget skips its name and email prompt. name is 1–100 characters and email up to 254. Always resolves; problems are reported with console.warn('[cecfb] …').
setMetadata(record)Merges record into the custom metadata sent with every submission. Up to 50 keys of 1–64 characters; each value is a string of up to 500 characters, a finite number or a boolean. null removes a key.
open(mode?)Opens a mode: 'pin', 'page', 'video' or 'threads'. Without a mode it opens the first one the launcher offers.
close()Closes the feedback form, the mode menu and the feedback panel.
hide() / show()Hides and restores the launcher. Console and network capture keep running.
on(event, callback) / off(event, callback)Subscribes to the events below. A callback that throws never stops the widget.
EventPayloadFires when
submitted{ feedbackId, number, kind }Feedback was created. kind is 'screenshot', 'video' or 'text'.
opened{ mode }A mode starts, from the launcher or from open(mode).
closed{}The mode from the last opened ended: sent, cancelled or closed.

The SDK works in every visibility mode: open() loads the widget even where it's otherwise hidden, so the site's own "Send feedback" button always works.

Examples

A "Send feedback" button

<button id="send-feedback" type="button">Send feedback</button>
document.querySelector('#send-feedback')?.addEventListener('click', () => {
  window.CecFeedback.open('page');
});

Identify the signed-in user

window.CecFeedback.identify({ name: 'Jane Doe', email: 'jane@example.com' });
window.CecFeedback.setMetadata({ plan: 'pro', accountId: 'acc_123' });

On WordPress, the plugin's Identify signed-in users by name and email setting does this without code. See WordPress plugin.

Analytics on submit

window.CecFeedback.on('submitted', ({ feedbackId, number, kind }) => {
  window.dataLayer?.push({ event: 'cecfb_feedback_submitted', feedbackId, number, kind });
});

Privacy

identify says who a reporter claims to be; it is not a sign-in. CEC uses the email to follow up and never treats it as a password or uses it to grant access. Send only the metadata the team needs (a plan or an account ID, not secrets or extra personal data): it's stored with every submission, and the CEC team can see it.

On this page