Custom Trigger
Open the ProductBridge widget from any element on your page — your own button, nav item, or menu link. Initialize with customTrigger and call ProductBridge.toggle() from your element's click handler.
Where to find it
Open Custom Trigger setup
Sidebar → Settings → Connect → Widget & Embeds → Custom Trigger
Direct link: https://app.productbridge.io/dashboard/settings/widget-embeds?embed=trigger
In-app path: Sidebar → Settings → Connect → Widget & Embeds → Custom Trigger in the left rail
Requires: organization:manage to view the embed code and manage widget API keys.
The Widget & Embeds page has four tabs, each deep-linkable:
| Tab | Direct link |
|---|---|
| Embed Code | ?tab=embed |
| Configuration | ?tab=config |
| API Keys | ?tab=keys |
| Preview | ?tab=preview |
Overview
The custom trigger embed hides the default floating button and lets you open the widget from your own UI. Initialize the SDK with customTrigger: true, then call ProductBridge.toggle() (or ProductBridge.open()) from any click handler — a nav link, a help button, a keyboard shortcut. The widget opens as a full-height sidebar panel.
Use this when you already have a feedback entry point in your UI and don't want two buttons on screen.
How It Works
- Add any clickable element to your page
- Load the SDK and call
ProductBridge.init()withcustomTrigger: true— this hides the floating button - Wire your element's click event to
ProductBridge.toggle()
Installation
<!-- 1. Your custom trigger element — can be any HTML element -->
<button id="feedback-btn">Share Feedback</button>
<!-- 2. Paste before </body> -->
<script>
(function () {
var s = document.createElement('script');
s.src = 'https://app.productbridge.io/sdk/pb-widget.js';
s.async = true;
s.onload = function () {
ProductBridge.init({
organizationId: 'YOUR_ORGANIZATION_ID',
customTrigger: true, // hides the floating button
theme: 'auto',
defaultTab: 'feedback',
});
// 3. Wire your element to the widget
document.getElementById('feedback-btn')
.addEventListener('click', function () {
ProductBridge.toggle();
});
};
document.head.appendChild(s);
})();
</script>
// This component renders your trigger button and wires up the SDK.
// Place it wherever you want the trigger to appear.
import { useEffect, useRef } from 'react';
export default function ProductBridgeCustomTrigger({
organizationId = 'YOUR_ORGANIZATION_ID',
theme = 'auto',
defaultTab = 'feedback',
userToken = null,
children = 'Share Feedback',
}) {
const initialized = useRef(false);
useEffect(() => {
if (initialized.current) return;
initialized.current = true;
const script = document.createElement('script');
script.src = 'https://app.productbridge.io/sdk/pb-widget.js';
script.async = true;
script.onload = () => {
window.ProductBridge.init({
organizationId,
customTrigger: true,
theme,
defaultTab,
...(userToken && { userToken }),
});
};
document.head.appendChild(script);
return () => {
window.ProductBridge?.destroy();
};
}, [organizationId, userToken]);
return (
<button onClick={() => window.ProductBridge?.toggle()}>
{children}
</button>
);
}
// Usage:
// <ProductBridgeCustomTrigger organizationId="YOUR_ID">
// Share Feedback
// </ProductBridgeCustomTrigger>
<!-- Place this component wherever you want the trigger button.
Style the button however you like. -->
<script setup>
import { onMounted, onUnmounted } from 'vue';
const props = defineProps({
organizationId: { type: String, default: 'YOUR_ORGANIZATION_ID' },
theme: { type: String, default: 'auto' },
defaultTab: { type: String, default: 'feedback' },
userToken: { type: String, default: null },
});
onMounted(() => {
const script = document.createElement('script');
script.src = 'https://app.productbridge.io/sdk/pb-widget.js';
script.async = true;
script.onload = () => {
window.ProductBridge.init({
organizationId: props.organizationId,
customTrigger: true,
theme: props.theme,
defaultTab: props.defaultTab,
...(props.userToken && { userToken: props.userToken }),
});
};
document.head.appendChild(script);
});
onUnmounted(() => {
window.ProductBridge?.destroy();
});
function toggleWidget() {
window.ProductBridge?.toggle();
}
</script>
<template>
<button @click="toggleWidget">
<slot>Share Feedback</slot>
</button>
</template>
// Place <app-productbridge-trigger>Share Feedback</app-productbridge-trigger>
// wherever you want the trigger button in your templates.
import { Component, Input, OnInit, OnDestroy } from '@angular/core';
@Component({
selector: 'app-productbridge-trigger',
template: `<button (click)="toggleWidget()"><ng-content></ng-content></button>`,
standalone: true,
})
export class ProductBridgeTriggerComponent implements OnInit, OnDestroy {
@Input() organizationId = 'YOUR_ORGANIZATION_ID';
@Input() theme = 'auto';
@Input() defaultTab = 'feedback';
@Input() userToken?: string;
ngOnInit(): void {
const script = document.createElement('script');
script.src = 'https://app.productbridge.io/sdk/pb-widget.js';
script.async = true;
script.onload = () => {
(window as any).ProductBridge.init({
organizationId: this.organizationId,
customTrigger: true,
theme: this.theme,
defaultTab: this.defaultTab,
...(this.userToken && { userToken: this.userToken }),
});
};
document.head.appendChild(script);
}
toggleWidget(): void {
(window as any).ProductBridge?.toggle();
}
ngOnDestroy(): void {
(window as any).ProductBridge?.destroy();
}
}
Trigger Any Element
You can wire the widget to any existing element on the page — you don't need to render a new button:
<!-- Trigger an existing nav link -->
<a id="nav-feedback-link" href="#">Feedback</a>
<script>
ProductBridge.init({
organizationId: 'YOUR_ORGANIZATION_ID',
customTrigger: true,
});
document.getElementById('nav-feedback-link')
.addEventListener('click', function (e) {
e.preventDefault();
ProductBridge.toggle();
});
</script>
// Or open and close explicitly instead of toggling
document.getElementById('my-help-menu-item')
.addEventListener('click', () => ProductBridge.open());
Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
organizationId | string | — | Required. Your organization ID |
customTrigger | boolean | false | Required for this embed type. Set to true to hide the floating button; you open the widget yourself with ProductBridge.toggle() or ProductBridge.open() |
theme | string | auto | auto, light, or dark |
defaultTab | string | feedback | feedback, roadmap, or changelog |
userToken | string | — | JWT for automatic user identification — see Identity Verification |
With customTrigger: true, the SDK hides the floating button entirely and the widget opens as a sidebar panel. It opens only when you call ProductBridge.toggle() or ProductBridge.open() from your own code.
Identify Your Users
To link feedback to your logged-in users, generate a JWT on your backend and pass it as userToken. See Identity Verification for server-side code in Node.js, Python, PHP, Ruby, and Go.