OneSignal (with Angular) — a notification service for websites

Anh-Thi Dinh
OneSignal's AI Chatbot is extremely helpful. While the official documentation often contains outdated or incorrect information, the chatbot consistently provides accurate and reliable solutions. I recommend consulting it rather than relying solely on the official documentation.

References

  • The official documentation is inadequate. Following their guides didn't work for me on the first attempt!

Remarks

  • Ensure the integrated file OneSignalSDKWorker.js is accessible via http://localhost:<port>/<subfolder>/OneSignalSDKWorker.js
    • 1importScripts('https://cdn.onesignal.com/sdks/web/v16/OneSignalSDK.sw.js');
      Note that you will only see the above file content (importScripts….). Only the service worker can fetch and load the content of OneSignalSDK.sw.js.
  • After modifying anything on the OneSignal Dashboard or in your code, clear your browser's cache, reset notification permissions, and reload the page.
  • Be aware of caching issues when changing the location of OneSignalSDKWorker.js. The service may continue working due to browser caching even after relocating the file. To verify it's truly working, perform a hard refresh, wait a bit, or test with a fresh browser/profile.
  • Should use Soft Prompt (display an explanation before asking for the notification permission from the browser) ← Soft prompts are recommended by browsers and help maximize opt-in rates while protecting your domain reputation.

Very simple sample

  • With just a HTML file.

With Angular (or Web SDK)

  • Implementation notes:
    • Use http protocol with ng serve
    • Enable "Local Testing" in the OneSignal settings page
  • Firefox: it works like a charm.
  • Brave: Not working because Brave blocks the service worker file from functioning. You'll see errors like
    • 1Uncaught NetworkError: Failed to execute 'importScripts' on 'WorkerGlobalScope': The script at 'https://cdn.onesignal.com/sdks/web/v16/OneSignalSDK.sw.js' failed to load.
      1[Service Worker Installation] Installing service worker failed TypeError: Failed to register a ServiceWorker for scope ('http://localhost:4200/') with script ('http://localhost:4200/OneSignalSDKWorker.js?appId=c9112e5f-f8e4-4831-b803-cd37207e3198&sdkVersion=160508'): ServiceWorker script evaluation failed
  • Chrome: Works well. On MacOS, enable notifications for Chrome in the system settings. Allow both "Google Chrome" and "Google Chrome Helper (Alerts)" permissions. Without these settings, Chrome notifications won't appear (except for the initial Hello notification).
  • Safari: should clear the cache and:
    • Safari → Settings → Websites → Notifications → allow all
    • Safari → Settings for localhost… → make sure
      • We can click the small icon on the left of the address bar to show these options.
      If it's still not working, you can create a new profile (Safari → Manage Profiles…) and test again.

Check the permission

1// No return
2await this.oneSignal.Notifications.requestPermission();
3
4// To know user's action
5const isPermissionGranted = this.oneSignal.Notifications.permission;

Stop receiving notification

  • Note that logout() doesn't prevent users from receiving notifications—it only makes them anonymous (resets the OneSignal ID to a new anonymous user). If you want to stop notifications completely, use optOut() and when needed again, use optIn().
    • Note that, we cannot use login() after using outOut()
  • If you want to stop receiving notification when you are already in

Clear browser data

⚠️
Make sure to clear and reset all your browser data each time you change something in the settings (on the Dashboard or in your code).
  • Safari: Safari menu → Preferences (or Settings) → Privacy tab → "Manage Website Data" → "Remove All”
    • Or: Safari menu → "Clear History..." → choose time range → "Clear History”
    • Enable developer setting: Safari → Preferences (or Settings) → Advanced → tick “Show features for web developers”
    • For developer cache: Develop menu → "Empty Caches" (enable Develop menu in Preferences → Advanced first)
    • Unregister service worker: Safari → Develop menu → Web Inspector → Go to "Storage" tab → Expand "Service Workers" in left sidebar → Select your service worker → Click "Unregister" to remove it completely
  • Chrome:
    • Chrome menu (⋮) → Settings → Privacy and security → "Clear browsing data" / “Delete browsing data” → Advanced → select all → Delete data.
    • Storage section: F12 → Application tab → local storage, session storage, indexedDB, cookies, cache storage → right click → clear / delete.
    • Service workers section: F12 → Application tab → Service workers → See all registrations → Find “OneSignal” and then unregister / stop.
    • Disable caching: F12 → Network → check “Disable cache” to prevent caching during development sessions.
  • Firefox:
    • Firefox menu (☰) → Settings → Privacy & Security → Scroll to "Cookies and Site Data" → "Clear Data..."
    • F12 → Storage → … → right click and Delete All
    • Service worker: F12 → Application → Service Workers → … → Unregister
      • Or type in address bar: about:serviceworkers

Users (Subscription ID, External ID, OneSignal ID)

  • Subscription ID vs OneSignal ID? When a new device connects, both a subscription ID and OneSignal ID are automatically created.
    • If this device includes an External ID, the OneSignal ID will be changed to match the one associated with that External ID.
  • OneSignal ID vs External ID?
    • OneSignal ID: Automatically generated, read-only, and can change based on existing External ID.
    • External ID: Set by developers.
    • When using login(external_id), if the external_id already exists, the SDK switches to that user. Any anonymous data collected before login is discarded, not merged. Ref.
  • Anonymous vs Identified users:
    • Anonymous users (no External ID): Each subscription receives its own OneSignal ID and is treated as a separate user.
    • Identified users (with External ID): All subscriptions merge under a single OneSignal ID.
  • Best practice: Always call OneSignal.login(external_id) to set the user context to the provided external_id. You can call this method anytime to link the user, as the SDK handles this flexibly.
  • Different browsers calling OneSignal.login("user_id_1") will create different subscriptions but use the same external_id "user_id_1".
  • To check the correspondence between External ID and OneSignal ID, go to Dashboard → Audience → Users.
  • Note that logout() doesn't prevent users from receiving notifications—it only makes them anonymous (resets the OneSignal ID to a new anonymous user). If you want to stop notifications completely, use optOut() and when needed again, use optIn().
    • Note that, we cannot use login() after using outOut()

Debugging

Debug the service worker

  1. Open Chrome Developer Tools (F12) and go to the Console tab
  1. Run: OneSignal.User.PushSubscription.id to get your subscription ID
  1. Visit chrome://serviceworker-internals and search for your site's scope
  1. Click "Inspect" on your service worker and run OneSignalWorker.log.trace(); in the console

Check message delivery

  1. Open chrome://gcm-internals and click "Start Recording"
  1. Send a test message and check if you see "Data msg received" in the logs

Check the subscriber ID

1this.oneSignal.User.PushSubscription.addEventListener('change', (event) => {
2  console.log('Push subscription changed:', event);
3  console.log('New subscription ID:', this.oneSignal.User.PushSubscription.id);
4  console.log('Opted in:', this.oneSignal.User.PushSubscription.optedIn);
5});
Then search and use “Add as Test Subscription” in Dashboard.

Send test push via API

In the official doc, in the body of the request, there is "included_segments": [ "Test Users" ], you have to create a segment name “Test Users” (exact name like in the body)
  1. In your dashboard, go to Audience > Subscriptions, find your device, click the Options (three dots) button and select Add to Test Subscriptions.
  1. Create a Test Users segment: Go to Audience > Segments > New Segment, name it Test Users (exact name is important), and add the “Test Users” filter.
  1. Update your API call: Use "included_segments": ["Test Users"] in your API request instead of targeting individual player IDs