Mashing up CRM and Twitter, Part 2

The Truth is Out There (in 140 Characters or less!)

If you didn’t read the first part of this “series”, here’s a link to Mashing up CRM and Twitter, Part 1. That article provides a high-level overview of three topics:

  1. What the heck Twitter is, in case you’re new to it
  2. Why you might want to integrate it with Dynamics CRM
  3. Some basics of Twitter Search

To follow up on part 1, I want to cover two main topics here:

  1. How you can implement a managed Twitter search from a Dynamics CRM record
  2. Discuss some of the interesting extensions of the simple example I’ll show, and argue a little more why Twitter search is so important

Implementing a Managed Twitter Search from Dynamics CRM

What I’ll show here is some of the mechanics of doing a contextual Twitter search from a CRM record. These will be similar no matter what entity you’re searching from, so I’m going to show how to customize the Dynamics CRM “Competitor” entity. (In the example I show it will be not for my competitors, but for a group of companies that compete against each other. Same techniques, either way.)

The general technique is to use an IFRAME control on a customized CRM form, and dynamically update the “src” property of the IFRAME with information from the current record. Here’s what the user experience looks like, starting with the Competitor form opened to a specific record, in this case my favorite food company, Kraft:

"Competitor" form open with record selected

Figure 1: Competitor form open with a record selected

This shows a standard Dynamics CRM form, in this case having double-clicked on the “Kraft” record from the Competitors grid. When a user clicks on the Twitter Search tab, what they see is an IFRAME that exposes the results of a Twitter search. What that might look like is shown here:

comp_form2

 

Figure 2: Twitter search results based on CRM data

How to Build it

That’s the user experience. What I’ll show you next is how to build a customization like this — essentially, how to update the “src” property of an IFRAME like that with information from the current record. The idea here is to provide a managed search experience from within CRM, so my brand managers or whoever else might be using this don’t need to worry about Twitter search syntax. To save a little time, I’ll give you a “heuristic” step by step. I’ll post a video shortly where you can see all of the detailed steps, but for now…

…follow these steps:

  1. Customize the Competitors entity, by adding a tab, a section, and an IFRAME; call them all Twitter Search or something like that.
  2. To start out, set the IFRAME’s URL property to http://search.twitter.com . Turn off the “prevent cross-frame scripting” property by unchecking it.
  3. Navigate to the form’s OnLoad event, and add the following  jscript code:

code starts here:

var CRM_FORM_TYPE_CREATE = 1;
var CRM_FORM_TYPE_UPDATE = 2;

var twittersearchURL = “”;

switch (crmForm.FormType)
{
 case CRM_FORM_TYPE_CREATE:
    twittersearchURL = “http://search.twitter.com“;  
   break;

 case CRM_FORM_TYPE_UPDATE:
       // Use Twitter search with this account’s name when updating account
  twittersearchURL = “http://search.twitter.com/search.atom?q=”;
  // Encode the account name and add it to the search string
  twittersearchURL += encodeURIComponent(crmForm.all.name.DataValue)+”&rpp=100&lang=en&tude=:)”; 
  break;
}

// Set the respective IFRAME’s URL
//alert (twittersearchURL);

crmForm.all.IFRAME_twittersearch.src = twittersearchURL; 

end of code

Let me make a couple of comments about this code, in case you want to try it or some variation on it:

  • Notice that the twitter search url uses the “atom” qualifier. This is the way twitter search lets you return results in an RSS format. This is a lot more convenient in many ways than search results returned to an HTML page. In part 1 of this article I discussed Twitter search basics, and included a link to the Twitter search API, which I highly recommend you read if you want to do things like this.
  • Notice the encodeURIComponent function call. In this example, I pass  “crmForm.all.name.DataValue” into that function — this is the value of the “name” field on the Competitor form. If you were doing this for the Account or most other entities, it would be identical, but you might need to change the field name depending on what you want to do. EncodeURIComponent does things like replace spaces with the “%20″ strings you see in URLs; it basically takes text strings and formats them properly as URLs, so get used to this function if you want to do things like this.
  • Also: notice the “&tude=:)” and the other strings I tacked on to the end of the url. If I hadn’t commented out the alert, I’d see a URL like this just before the last line of this OnLoad event code gets run: http://search.twitter.com/search.atom?q=Kraft&rpp=100&lang=en&tude=:) This search query looks for Kraft, then tells Twitter to return up to 100 results per page, then says to only look for English results, and finally says to look for “results with a positive attitude”. Obviously, if I’m a Kraft brand manager and I’m looking at search results for “Oreo Cakesters”, or “mac ‘n cheese”, I’d probably want to look at both “tude=:)” and “tude =:(” results, if you know what I mean!

Refer back to Figure 2 for a second and notice the “Results mood” pulldown list. With very little additional effort (similar jscript to the above, only behind the Change event of the picklist attribute that gets selected) you can build in some flexibility along these lines.

Extensions and the Importance of Twitter Search

Here are some of the more obvious ways this could be extended. (You can probably think of a lot more — let me know if you have some good ones!)

  • If I’m a Kraft brand manager, I’d want to use the Product entity, and add a bunch of my products (see above), and search on them with both :) and :( tude qualifiers, and maybe stack up how I’m doing against my competition.
  • If I really did want to keep track of my competitors, the Competitor entity would work well, but you might want to do this for their products as opposed to just the company name.
  • I think where it really starts to get cool is to store the results and start doing some analysis over time on the search results. You could store off these RSS data, say to a database, and really start to crunch some interesting numbers. For example, suppose you’re launching a new ad campaign for an existing product, and you want to see how it impacts the buzz about your product over time. Or suppose you’re watching to see how your competitors’ campaigns are doing over time. Or suppose you’re managing a product recall or something along those lines and how that impacts discussion of your product over time…

I could go on and on, but you probably get the point by now (if you’ve read this far! in which case, thank you very much). People who dismiss Twitter as a narcissistic time-suck are missing the point. If you’ve got 6 million+ people out there tweeting away about almost any topic you can think of, the chances are good they’re talking about things that matter to you. And if you can aggregate up all those tweets, you can actually learn some interesting things you might not already know.

The Truth is Out There…in the form of millions and millions of 140 character tweets.    

Cheers –

Richard

richardk@imginc.com

Leave a Comment

Making Mashups with Dynamics CRM

Of Wikipedia’s five definitions of the term “mashup”, my favorite is for what they refer to as a web application hybrid: “a web application that combines data and/or functionality from more than one source”. Here’s the link: http://en.wikipedia.org/wiki/Mashup_(web_application_hybrid).

Dynamics CRM, with its relational database platform and easy customization features, is pretty good for mashups…if what you want to mash up are data stored within Dynamics CRM. In an earlier blog post I discussed how you can integrate Dynamics CRM with SharePoint. There are lots of ways of doing that, but the one I wrote about treated SharePoint content as meta-data associated with a CRM record, and I showed an example of constructing a MOSS search dynamically, and exposing the search results on a CRM Account record’s form using an IFRAME. In a different post I showed a different example of a “CRM mashup”, where you could display, again for a CRM Account record, all of the Linkedin profiles of people associated with that Account.

I wasn’t thinking of those as mashups at the time, but after reading the above definition, they fit the term pretty well! The possibilities are limitless, and since a wide class of them use the same basic CRM customization techniques, you can pound them out pretty quickly after a little practice.

Here’s another CRM mashup, having to do with a web site I’ve been using lately called www.Compete.com. One of the things you can do on Compete.com is enter one or more domain names, and Compete will display a chart with various data about their site traffic. For example, here’s a comparison of live.com and google.com:

 

compete_gvl2 

(It might be hard to tell from the picture, but Live closed the gap a little bit in January, according to these numbers.) You can do this for up to 5 domains at a time, and this is in the free version. They have a professional version you pay for that does more stuff; I haven’t taken the plunge with that one yet.

From the mashup standpoint, the most interesting thing about this is the URL: http://siteanalytics.compete.com/google.com+live.com/?metric=uv

Since you can access the free version of Compete anonymously, as long as you can construct a URL like this, you can display views like this in any web application where you can expose a page. In SharePoint you can use the Page Viewer Web Part to do it, in Dynamics CRM it’s going to be an IFRAME.

At the same time I was figuring this out I was doing a little research into different CRM blogs and web sites. I was interested in comparing some of the top sites, and seeing things like how much traffic they got, which if any were ad supported, and things like that. So of course, as any self-respecting CRM customizer would do, I whipped up a little custom entity in my CRM Online organization, called it CRMBlogsandSites, and added some custom attributes for the data I wanted to track. Here’s a view of the data grid:

 

crmblogsandsites

Since I’ve got the URL, I can do my mashup pretty easily. Here’s what one of the forms looks like – I’ll pick on Sonoma Partners in my example:

 

Notice that I’ve got attributes both for the URL and for the “traffic URL”. I created custom tabs on the form to display the web site, and the traffic chart from compete.com. The Site Traffic tab has an IFRAME on it I called “sitetraffic”. (CRM puts a prefix in front of the name, so in my code I’ll refer to it as “img_sitetraffic”. When a user’s on the form and clicks on the tab, it looks like this:

sonomatraffic

To create this little mashup, here’s what I did:

1.       Created the custom entity I needed, crmblogsandsites, display name “CRM Blogs and Sites”.

2.       Added a custom attribute, img_trafficurl (“img” being the customization prefix, so that will most likely be different in your organization, although feel free to use img if you like), display name “Traffic URL”, type nvarchar, length 250, format URL.

3.       Opened up the entity’s form in customization mode and added a tab, called it Site Traffic, then added a section to the tab with the same name, but don’t display it. Also, you have to add the trafficurl attribute as a field on the form, don’t forget that!

4.       On that section, added an IFRAME. I called it “sitetraffic”, and CRM puts the text IFRAME in front of it, so in code you’ll refer to it as IFRAME_sitetraffic. Notice in the following picture that I’ve unchecked “Restrict cross-frame scripting”. Experiment with it both ways and I believe you’ll find it needs to be unchecked. Also notice the default url I’ve entered. As you’ll see this gets updated in code so it’s not critically important, but using this approach always reminds me of what it’s for, so I’ll often use it.

 

iframeproperties1 

 

5.       Added this little jscript snippet to the change event of the trafficurl field (remember that one from above?). Remember to check in the box that says “Event is enabled”, otherwise nothing will happen.

 

crmForm.all.IFRAME_sitetraffic.src = crmForm.all.img_trafficurl.DataValue;

 

 

6.       Finally, navigate to the Form’s load event (click Form Properties, select OnLoad and click Edit), and add this code:

 

var CRM_FORM_TYPE_CREATE = 1;
var CRM_FORM_TYPE_UPDATE = 2;
var sitetrafficurl="";
   switch (crmForm.FormType)
   {
      case CRM_FORM_TYPE_CREATE:
     
         // don't need to do anything 
         break;
 
      case CRM_FORM_TYPE_UPDATE:
        if (crmForm.all.img_trafficurl.DataValue != null)
          { 
         // if it's filled in, put value of img_trafficurl field into sitetrafficurl variable
         sitetrafficurl = crmForm.all.img_trafficurl.DataValue;
           }
         break;
   }
// Set the IFRAME's URL
crmForm.all.IFRAME_sitetraffic.src = sitetrafficurl;

 

Make sure the Event is Enabled checkbox is checked, save all your changes and publish your entity and see if it works. This fundamental technique comes up in lots of different contexts, so it might look familiar. The key is to figure out what kind of interesting information is out there on the web, related to an entity you have or can create in Dynamics CRM; then all you need to do is figure out how to construct the URL. And just remember: for any entity you have in Dynamics CRM, there’s probably meta-data for it out there somewhere!

And if you’ve created any good CRM mashups or have an idea for one, let me know.

Cheers — Richard

 

Leave a Comment

Search SharePoint for Stuff for a Dynamics CRM Record

Question
I’ve heard you can search SharePoint from external applications. I want to search it from a Dynamics CRM account form, so I can see all of the documents stored in our MOSS site related to an Account record in CRM. Is this possible?
Answer
Excellent question. (Meaning, I think it’s interesting AND I can answer it.) Here’s what I did — you can of course modify this to meet your specific requirements. Probably most important is the url I’m searching in the example, which is our firm’s intranet site. If you’re searching a SharePoint site that you navigate to by typing ‘http://foo.acme.com‘, sub that in for the ‘http://wss.imginc.com‘ references you see below and this will work fine.   1. Add a tab to the Account form. I called mine ‘MOSS Search’. Add a section to it, and onto that section add an IFRAME. I called mine ‘moss_search’, so the full name of the IFRAME is IFRAME_moss_search.2. Add the following code to the onLoad event of the Account form:

// JScript source code
var CRM_FORM_TYPE_CREATE = 1;
var CRM_FORM_TYPE_UPDATE = 2;

var sLiveSearchURL = ”;

if(IsOnline())
{
 switch (crmForm.FormType)
 {
  case CRM_FORM_TYPE_CREATE:
  
   // Point to the IMG wss Intranet site when creating an account
   imgSearchURL = ‘
http://wss.imginc.com‘;  
   break;

  case CRM_FORM_TYPE_UPDATE:
    
   // Use MOSS search with this account’s name when updating account
   imgSearchURL = ‘
http://wss.imginc.com/search/pages/Results.aspx?k=’;
   
   // Encode the account name and add it to the search string
   imgSearchURL += encodeURIComponent(crmForm.all.name.DataValue);
   
   break;
 }
}

// Set the IFRAME’s URL
crmForm.all.IFRAME_moss_search.src = imgSearchURL;

 

One more point about the code snippet above: the imgSearchURL variable will need to be replaced by whatever the url is for your SharePoint search results page. Just do a search with no parameters to see what it is and sub that in.

This is a nice illustration of how you can integrate Dynamics CRM and SharePoint, but it also applies to other scenarios when you want to do what I call contextual searching from within Dynamics CRM. Let me know what you think!

Comments (3)