How to set up Kite contacts page on a website

How to set up Kite contacts page on a website

This Guide explains how to set up x-bees/ Collaboration 7/ x-hoppers Kite contacts page using a script, with an example available at https://www.wildix.com/contacts/.

Created: September 2024

Updated: January 2026

Permalink: https://wildix.atlassian.net/wiki/x/VAbOAQ

Requirements

  • jQuery library connected to the page

  • Web skills: Basic knowledge of HTML, CSS and JavaScript to implement and customize the contact cardsย 

Setup steps

Step 1. Insert the script

  • Insert the below script globally on your website or on a specific page where you want to display contact cards.

Note: Depending on the product (x-bees, Collaboration 7, x-hoppers), enter the necessary link in the "var RNA_URL" variable:

  • for x-bees: var RNA_URL = 'https://app.x-bees.com';

  • for Collaboration 7: var RNA_URL = 'https://app.wildix.com/';

  • for x-hoppers: var RNA_URL = 'https://app.x-hoppers.com/';

<script> (function ($) { var KITE_URL = 'https://kite.wildix.com'; var RNA_URL = 'https://app.x-bees.com'; var DEFAULT_STATUS_IMAGES = { 'online': 'presences/online.webp', 'offline': 'presences/offline.webp', 'talking': 'presences/talking.webp', 'ringing': 'presences/ringing-now.webp', 'away': 'presences/away.webp', 'away-offline': 'presences/awayoffline.webp', 'dnd': 'presences/dnd.webp', 'dnd-offline': 'presences/dndoffline.webp' }; var DEFAULT_UPDATE_INTERVAL = 1000 * 10; var DEFAULT_POPUP_WIDTH = 600; var DEFAULT_POPUP_HEIGHT = 500; jQuery.fn.kiteContact = function (options) { var _extensions = {}; var settings = { statusImages: $.extend({}, DEFAULT_STATUS_IMAGES), updateInterval: DEFAULT_UPDATE_INTERVAL }; if (options) { if (options.statusImages) { $.extend(true, settings.statusImages, options.statusImages); } if (typeof options.updateInterval === 'number') { settings.updateInterval = options.updateInterval; } } var methods = { _timeout: {}, _timeoutCounter: {}, _updatePresence: function (serial) { if (this._timeoutCounter[serial] == undefined) { this._timeoutCounter[serial] = 0; } if (!this._timeoutCounter[serial]) { $.ajax({ url: KITE_URL + '/' + serial + '/' + _extensions[serial] + '/api/presence', type: 'GET', cache: false, dataType: 'jsonp', timeout: 10 * 1000, success: jQuery.proxy(this._onAjaxSuccess, this, serial), error: jQuery.proxy(this._onAjaxError, this, serial), complete: jQuery.proxy(this._onAjaxComplete, this, serial) }); } }, _popitup: function (mypage, w, h, pos, myname, infocus) { if (w != parseInt(w) || w <= 0) w = DEFAULT_POPUP_WIDTH; if (h != parseInt(h) || h <= 0) h = DEFAULT_POPUP_HEIGHT; if (myname == null) { myname = "swin" } ; var myleft = 0; var mytop = 0; if (myleft == 0 && mytop == 0 && pos != "random") { pos = "center" } ; if (pos == "random") { myleft = (screen.width) ? Math.floor(Math.random() * (screen.width - w)) : 100; mytop = (screen.height) ? Math.floor(Math.random() * ((screen.height - h) - 75)) : 100; } if (pos == "center") { myleft = (screen.width) ? (screen.width - w) / 2 : 100; mytop = (screen.height) ? (screen.height - h) / 2 : 100; } var windowFeatures = "width=" + w + ",height=" + h + ",top=" + mytop + ",left=" + myleft + ",scrollbars=no,location=yes,directories=no,status=no,menubar=no,toolbar=no,resizable=no"; var swin = window.open(mypage, myname, windowFeatures); if (infocus == null || infocus == "front") { swin.focus() } ; return false; }, _onAjaxSuccess: function (serial, data, textStatus, jqXHR) { var self = this; if (data.type == "result") { $.each(_extensions[serial], function (index, extension) { var presence = {}; var file = 'offline.jpeg'; if (data && data.result) { if (data.result.hasOwnProperty(extension)) { // multiple presences file = self._getPresenceImage(data.result[extension]); } else if (data.result.hasOwnProperty('online')) { // one presence file = self._getPresenceImage(data.result); } } $('.contact[serial="' + serial + '"][extension="' + extension + '"] .presence').attr('src', file); }); } else { console.log('Error (' + serial + '): ' + data.reason); this._resetPresence(serial); } this._timeoutCounter[serial] = 0; }, _onAjaxError: function (serial, jqXHR, textStatus, errorThrown) { console.log("Error: " + textStatus + ' ' + errorThrown, serial); if (textStatus == 'timeout') { if (this._timeoutCounter[serial] == 2) { this._resetPresence(serial); } this._timeoutCounter[serial]++; } else { this._timeoutCounter[serial] = 0; this._resetPresence(serial); } }, _onAjaxComplete: function (serial, jqXHR, textStatus) { if (this._timeout && this._timeout[serial]) { clearTimeout(this._timeout[serial]); } this._timeout[serial] = setTimeout(this._updatePresence.bind(this, serial), settings.updateInterval); }, _getPresenceImage: function (presence) { var status = 'offline'; if (presence) { var online = presence['online']; var show = presence['show']; var deviceShow = presence['device_show']; if (deviceShow == 'talking' || deviceShow == 'tr') { status = 'talking'; } else if (deviceShow == 'ringing') { status = 'ringing'; } else if (show == 'away') { status = online ? 'away' : 'away-offline'; } else if (show == 'dnd') { status = online ? 'dnd' : 'dnd-offline'; } else { status = online ? 'online' : 'offline'; } } return settings.statusImages[status]; }, _resetPresence: function (serial) { $.each(_extensions[serial], function (index, extension) { $('.contact[serial="' + serial + '"][extension="' + extension + '"] .presence').attr('src', settings.statusImages['offline']); }); }, _onOpenKite: function (e) { var contact = $(e.currentTarget).closest('.contact'); var serial = contact.attr('serial'); var extension = contact.attr('extension'); var email = contact.attr('email'); var kiteid = contact.attr('kiteid'); if (typeof kiteid !== 'undefined') { var url = RNA_URL + '/kite/' + kiteid; } else { var url = RNA_URL + '/kite/' + email; } this._popitup(url, 600, 500, 'center', 'Kite', 'front'); } }; this.each(function () { if (this.used) { return; } var extension = $(this).attr('extension'); var serial = $(this).attr('serial'); //Serial can be both serial or subdomain for pbx if (extension && extension != '' && serial) { $(this).find('.avatar img').attr('src', KITE_URL + '/' + serial + '/' + extension + '/api/avatar'); if (_extensions[serial] == undefined) { _extensions[serial] = []; } _extensions[serial].push(extension); this.used = true; } $(this).find('.call a').click(jQuery.proxy(methods._onOpenKite, methods)); $(this).find('.avatar a').click(jQuery.proxy(methods._onOpenKite, methods)); }); $.each(_extensions, function (serial, extensions) { methods._updatePresence(serial); }); }; })(jQuery); jQuery(window).on('load', function () { jQuery('.contact').kiteContact(); }); </script>

Step 2. Customize contact cards

  • To create a custom contact card design, use contact, avatar, call, presence classes:

    <div class="contact" extension="0001" serial="pbx_domail" email="user1@email.com"> <div class="avatar"> <a href="javascript:void(0)"><img alt="avatar" src="default-avatar.png" /></a> </div> <div class="contact-me"><a href="javascript:void(0)">Contact me</a></div> <img class="presence" src="presences/offline.webp" align="middle" /> </div>
  • Set the appropriate values to show contact details:ย 

    extension="0000" serial="pbxname" email="test@email.com"

Step 3. Link your local presence images

To display the contact's presence (online/ offline etc):

  • Make sure to download the folder with presence icons and the default avatar: Media resources

  • The name of the folder containing your local presence files must match the path to the presence icons specified in the script (e.g., 'online': 'presences/online.webp').