Init in a root standalone component. No zone.js patching, no Angular wrapper.
There is no @usero/sdk/angular package, and there does not need to be. The vanilla SDK is plain DOM code, so you boot it from your root component ngOnInit and tear it down in ngOnDestroy. It renders outside Angular, so change detection never sees it.
npm install @usero/sdkimport { Component, OnDestroy, OnInit } from '@angular/core'
import { initUseroFeedbackWidget } from '@usero/sdk'
@Component({
selector: 'app-root',
standalone: true,
template: '<router-outlet />',
})
export class AppComponent implements OnInit, OnDestroy {
private widget?: ReturnType<typeof initUseroFeedbackWidget>
ngOnInit() {
this.widget = initUseroFeedbackWidget({ clientId: 'YOUR_CLIENT_ID' })
}
ngOnDestroy() {
this.widget?.destroy()
}
}Replace YOUR_CLIENT_ID with the id from your Usero dashboard.
Built for Angular
There is no first-class @usero/sdk/angular binding. You call the vanilla init directly, which is honestly cleaner than a thin NgModule wrapper would be.
The widget mounts onto document.body, not into an Angular template. Its DOM listeners never trigger a change-detection cycle, so you skip the runOutsideAngular dance entirely.
Works the same in a standalone bootstrapApplication app and a classic NgModule app. The init call lives in your root component either way.
Guard the init with isPlatformBrowser if you prerender. The vanilla SDK touches window, so server-side it should not run.
Canny ships a 200kb iframe and its own auth bridge. The vanilla SDK is one ~12kb script you init from a lifecycle hook, no iframe.
FAQ
No, and that is deliberate. The vanilla SDK is framework-free, so a one-line init in ngOnInit is the idiomatic install. A wrapper component would add maintenance for no real ergonomics.
No. The widget never lives in an Angular template, so its events do not enter the zone. There is no need to wrap the init in runOutsideAngular, though you can if you want to be explicit.
Wrap the init in an isPlatformBrowser(this.platformId) check. The SDK reads window, so it must only run on the client.
In the root AppComponent, so the widget stays mounted across every route change. A child component would tear it down when you navigate away from that route.
Free tier. No credit card. Two-minute install. Cancel by deleting two lines of code.
Install guides