Notification Indicator


To customize the look and feel of the notification indicator, use Viafoura’s JavaScript API and event system. Below is a sample implementation that will provide a template for a full custom integration of the notification indicator.



This is intended to provide a path for a custom notification indicator on your page. Please note that you cannot replace the Viafoura Notification Indicator inside the commenting tool or other tools. They can only be hidden, or customized via the documented Javascript and CSS APIs.


Below are the steps to implement a custom user avatar with a notification count, the user’s name, and an action to open the Notification Tray.


HTML Markup

Create some placeholders to contain the various values to be displayed to the user:

<button id="custom-trigger" class="trigger-button">
   <span id="custom-trigger__avatar" class="trigger-button__avatar"></span>
   <span id="custom-trigger__count" class="trigger-button__count">?</span>
   <span id="custom-trigger__name" class="trigger-button__name">?</span>

JavaScript Integration

Then, you will need to add hooks that run (a) immediately to set the initial view state, and (b) when events are detected to keep information up to date.


Use the Viafoura vf.context.get() method to get the initial data needed to set up theview. It will call vf.context.get(‘notifications’) to receive a promise which will resolve to a VfNotifications object which will be used to set the initial notification count.

Similarly, a call to vf.context.get(‘user’) to receive a promise will resolve to a VfUser object which will get the current user’s login state, name, and avatar information.


The Viafoura event bus will provide you with a simple way to keep your information up to date. Use vf.$subscribe() subscribe to the 'user-notifications', 'new-count-changed' event with a callback function receiving the latest notification count, and use that to update your notification indicator:

window.vf.$subscribe('user-notifications', 'new-count-changed', (new_count) => {
    // Do something here

Similarly, you can subscribe to changes in the current user state, by subscribing to the 'user', 'loaded' event with a callback that receives a VfUser object:

window.vf.$subscribe('user', 'loaded', (user) => {
    // Do something here

Full Sample Code

           // Bind the DOM elements to variables for easy reference
           const theButton = document.getElementById('custom-trigger');
           const theCount = document.getElementById('custom-trigger__count');
           const theName = document.getElementById('custom-trigger__name');
           const theAvatar = document.getElementById('custom-trigger__avatar');
           // Use the vfQ object to ensure code only runs once Viafoura is ready
           window.vfQ = window.vfQ || [];

           function initCustomTrigger() {
               // Get initial values and set the view immediately

               // Set up listeners for changes
               window.vf.$subscribe('user-notifications', 'new-count-changed', (new_count) => setCount({ counts: { new: new_count } }));
               window.vf.$subscribe('user', 'loaded', setUser);

               // Handle the click event and open the tray
               theButton.addEventListener('click', () => {
                   window.vfQ.push(() => window.vf.$publish('tray', 'open', theButton, 'vf-profile'));

           // See
           const setUser = ({ name, user_privilege, avatar, pic_large, pic_small }) => {
               if (user_privilege === 'guest') {
                   theName.textContent = 'Log In';
          = '';
               else {
                   theName.textContent = name;
          = `url(${pic_small || pic_large})`;

           // See
           const setCount = ({ counts }) => {
               theCount.textContent =;


           .trigger-button {
               position: relative;
               background: none;
               border: none;

               display: flex;
               justify-content: center;
               align-items: center;
           .trigger-button__avatar {
               display: inline-block;
               width: 3em;
               height: 3em;
               margin-right: 0.5rem;

               border-radius: 50%;
               border: 3px solid transparent;

               background-color: #ddd;
               background-size: cover;

               transition: border-color 0.2s;
           .trigger-button:hover .trigger-button__avatar,
           .trigger-button:focus .trigger-button__avatar {
               border-color: blue;

           .trigger-button__name {
               text-decoration: underline;
           .trigger-button:hover .trigger-button__name,
           .trigger-button:focus .trigger-button__name {
               text-decoration: none;

           .trigger-button__count {
               position: absolute;
               top: 0;
               left: 0;

               display: inline-flex;
               width: 1.5em;
               height: 1.5em;
               justify-content: center;
               align-items: center;

               background-color: red;
               border-radius: 50%;
               line-height: 1;

               color: white;

What’s Next