Creating a Simple Custom Gadget

6 minute read time.

In this article I am going to explain how to create a simple Custom Gadget for the Interactive Dashboard.

The Gadget will show how it can listen to an event in another Interactive Dashboard Gadget, then carry out a task and display the information.

The example I will use will be a very simple Gadget to display a feed from Twitter based on a TwitterName passed to it from a List Gadget.

Note: If you want real Twitter and Social Networking integration then please go to the Apps & Extras area where you can find components to download. This is only a training example!

What Can a Custom Gadget Do?

  • A Custom Gadget can listen to an event in another Gadget and recieve data in JSON format.
  • It can store and retrieve parameters that can control how the Custom Gadget Works.
  • It can Publish data in JSON format to another Gadget when an event occurs.

What Makes a Custom Gadget?

There are normally one or two files that contain the HTML and Javascript for the Custom Gadget.

I normally separate the Javascript into an include file. This is the technique I use in the example below.

A Custom Gadget is called using a WebSite Gadget that calls the URL of the Custom Gadget within an iframe. So the processing is Client Side as the Gadget uses AJAX techniques.

The address of the called Gadget is very simple. The URL can exist on any accessible server, it does have to reside on the same machine as Sage CRM. It can exist anywhere on the web.

The URL of the Custom Gadget is then called by an iframe within the WebSite Gadget and all the contextual information that the Gadget needs resides in the parental frame of the WebSite Gadget.

The article "An Example Custom Gadget for the Interactive Dashboard" introduces the new API functions

  • SageCRM.scrmGetSageCrmOwner()
  • SageCRM.scrmRegisterEvent()
  • SageCRM.scrmPublishEvent()
  • SageCRM.scrmGetGadgetProperty()
  • SageCRM.scrmSetGadgetProperty()
  • SageCRM.scrmSaveGadgetProperties()

The article provides a link to an example Gadget that can be downloaded.

For more background information about contextual information available to a Custom Gadget please see the article :"What Traditional Context Information is Passed to a Custom Gadget by the Interactive Dashboard?".

Scope of this Example

This first example will create a Custom Gadget that just listens and reacts to a Gadget event

It will use the following core API calls

  • SageCRM.scrmGetSageCrmOwner()
  • SageCRM.scrmRegisterEvent()


  • onSageCrmEvent

Create the HTML Page

The Gadget consists of an HTML page that includes a JScript file.

<html xmlns="">
<title>Sage CRM Custom Gadget</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<script type="text/javascript" src="simpletwittergadget.js"></script>
<span id="target">

Note: The important elements are the inclusion of the JScript file (simpletwittergadget.js) and the creation of a span element with a clear ID. The Javascript needs the span element to have an id to allow it to easily write the output into the page.

Create the JScript file

The JScript file (simpletwittergadget.js) is has a simple structure. I've listed the code below and divided it into 4 sections. I have described the sections below the code.

// Section 1////////////
var SageCRM = parent;
gadget = null;
try {
    gadget = SageCRM.scrmGetSageCrmOwner(;
    SageCRM.scrmRegisterEvent(gadget, "TwitterName", "5", null, "BOTH");
catch (err) {
// Section 2////////////
lastEntityRecordId = null;
function onSageCrmEvent(publisherGadgetId, publisherFieldName, publisherFieldType, publisherEntityId, publishedData) {
    var publishedObject = eval('(' + publishedData + ')');
    entityRecordId = publishedObject.entityRecordId;
    if (entityRecordId != lastEntityRecordId) {
        lastEntityRecordId = entityRecordId;
        logIncomingEvent(publishedObject, publishedData);
// Section 3////////////
function logIncomingEvent(publishedObject, publishedData) {
    var comp_twittername = publishedObject.comp_twittername;
    var resultData = getTwitterData(comp_twittername);
    var resultObject = eval('(' + resultData + ')');
    var strOutPut = "";
    var x = 0;
    var itemData;
    for (x in resultObject.value.items) {
        itemData = resultObject.value.items[x];
        strOutPut += "<h4><a href="" target =_new>" + itemData.title + "</a></h4>";
        strOutPut += "<p>" + itemData.description + "</p>";
    var target = document.getElementById('target');
    target.innerHTML = strOutPut;
// Section 4////////////
function getTwitterData(comp_twittername) {
    var xmlHttp = null;
    if (window.XMLHttpRequest) {// code for IE7, Firefox, Opera, etc.
        xmlHttp = new XMLHttpRequest();
    else if (window.ActiveXObject) {// code for IE6, IE5
        xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
    if (xmlHttp != null) {
        var strURL = "" + comp_twittername;"GET", strURL, 0);
        var resultJSON = xmlHttp.responseText;
        return resultJSON;
    else {
        alert("Your browser does not support XMLHTTP.");

Section 1

The Custom Gadget is called in an iframe and the code in section 1 create a global variables (SageCRM and gadget) to allow the easy reference to the parent object (and the Custom Gadget API calls that have been exposed) and the custom Gadget itself.

The identification of the current Gadget is done using the function scrmGetSageCrmOwner() in the parental frame. It takes one parameter, the id of the iframe element.

The section then registers the gadget to work with the events that can happen. For what table is the Gadget to work with? And do we want the Gadget to both listen for data and try and push (publish) data to other gadgets.

SageCRM.scrmRegisterEvent(gadget, "TwitterName", "5", null, "BOTH");

The parameters are

  • gadget
    • This is the gadget identified earlier. The parameter must not be null.
  • fieldName
    • This is the field that the gadget creates its links by. The parameter must not be null.
  • entityId.
    • This is the primary key value that identifies the table in the Meta Data table custom_tables. E.g. Company = 5.
  • fieldType
    • This is the data type of the field. May be null.
  • direction
    • This has to be one of 3 values "PUBLISH", "LISTEN" or "BOTH" and says whether the Custom Gadget will either just publish data, just listen for data or can do both. In my example I have left it to do both and I will continue to work on this so that the Gadget will publish data.

The way the Gadget has been registered controls how you can then set up the interaction between the Custom Gadget and any other Gadget.

Section 2

This is perhaps the most interesting section. When a user clicks on a row in the List gadget and event will happen. This is because the List Gadget is registered to Publish that event in the same way section 1 of the code above registered the events. That Gadget passes the event to the Custom Gadget and calls the onSageCrmEvent() function.

The onSageCrmEvent event function has to be defined in your code.

It needs the following parameters

publisherGadgetId, publisherFieldName, publisherFieldType, publisherEntityId, publishedData

which are all passed automatically to the function.

  • publisherGadgetId
    • Id of publisher gadget
  • publisherFieldName
    • Name of field in publisher gadget
  • publisherFieldType
    • Type of field in publisher gadget
  • publisherEntityId
    • ID of entity that is being published (as above, so 5 = Company table)
  • publishedData
    • JSON string where the first value is called "entityRecordId" and contains ID of record

The fact that JSON is used to pass the data means that it is very easy to handle.

The line

var publishedObject = eval('(' + publishedData + ')');

converts the JSON into a JScript object that can then be easily used.

The statement of the section calls a function that will then do the main task of the Custom Gadget.

Section 3

This defines the function logIncomingEvent(). But the function could be called anything that you like and it can do what ever you need it to do. In my example I have it access the twittername that is passed by the list Gadget.

Note: It is important to realise that you can only access data if the data has been passed by the other Gadget. Please see the article "Controlling the Data Passed to Custom Gadgets in the Interactive Dashboard".

The code then calls another function called getTwitterData() which I pass the TwitterName.

The getTwitterData() function is described below in Section 4, but it does return its data in JSON format which I can then easily turn into an object so I can process the returned results.

The code then builds an output string which I then write into the span element defined in the HTML page.

Section 4

This is the getTwitterData() function.

An XMLHttpRequest has been used to request a call to an RSS feed. The call is a URL which can be modified to change the parameter of the search in Twitter and return the result in JSON format. The TwitterName is passed as a variable so is easy to append to the URL.

Following articles will discuss creating and saving parameters and publishing data to other Gadgets.