Landed
Feedback widget

Widget configuration

Customize widget copy, theme, placement, and allowed origins.

Configure the widget from Settings → Widget in your Landed workspace.

Admin settings

Enable / disable

The widget is enabled by default. Use the on/off switch in settings to turn it off if you are not ready to accept submissions yet. While disabled, public config and submission endpoints reject traffic even with a valid key.

Publishable key

Each workspace has one publishable key, created automatically when the workspace is created. It is safe to embed in your client-side install code — like a UserJot project ID, it only identifies which workspace receives submissions. Restrict access with allowed origins if needed.

Install steps

Widget settings shows three separate copyable steps (Load SDK → Initialize → Identify):

1. Load the SDK

<script src="https://landed.so/sdk/loader.js" async></script>

2. Initialize the widget

<script>
  // Queue calls until the loader finishes.
  window.$ldq = window.$ldq || [];
  window.ld = window.ld || new Proxy({}, {
    get: (_, method) => (...args) => window.$ldq.push([method, ...args]),
  });
  window.ld.init('wk_pub_...', {
    position: 'right',
    theme: 'auto'
  });
</script>

The queue lines hold window.ld calls until the async loader finishes, so initialization works while loader.js is still downloading.

3. Identify signed-in users (optional)

<script>
  window.ld.identify({
    id: 'user_123',
    email: 'user@example.com',
    firstName: 'Jane',
    lastName: 'Doe'
  });
</script>

Use your Landed URL from NEXT_PUBLIC_APP_URL (for example https://landed.so). The SDK, embed page, and API all run on that host — not on your app's domain.

Agent prompt

Use Copy prompt in widget settings to copy instructions for Cursor, Codex, or other coding agents.

Allowed origins

Add one origin per line, for example:

https://app.example.com
https://staging.example.com

When this list is empty, Landed allows all origins during setup. For production, restrict the list to your real app origins.

Widget copy

Customize:

  • Title
  • Placeholder
  • Submit button label
  • Success message

SDK options

window.ld.init(widgetKey, options) supports:

OptionValuesDefault
positionright, leftright
themeauto, light, darkauto
offsetXnumber16
offsetYnumber16
baseUrlstringSDK host origin

Example:

<script>
  window.ld.init('wk_pub_...', {
    position: 'left',
    theme: 'dark',
    offsetX: 24,
    offsetY: 24
  });
</script>

SDK methods

MethodPurpose
ld.init(key, options)Boot the widget
ld.identify(user | null)Attach or clear signed-in user context (id, email, name, …)
ld.showWidget()Open the feedback panel programmatically
ld.hideWidget()Close the feedback panel
ld.getWidgetState()Read open/closed state
ld.destroy()Remove the widget from the page

Public API used by the widget

The hosted widget UI calls these endpoints with your publishable key. The same endpoints are used by @landedso/sdk for custom UI integrations.

  • GET /api/v1/widget/config
  • POST /api/v1/widget/session
  • POST /api/v1/feedback/submissions
  • POST /api/v1/uploads

Authentication header:

Authorization: Bearer wk_pub_...

Alternate header:

X-Landed-Widget-Key: wk_pub_...

Next step