Thursday, March 31, 2011

SalesForce Knowledge, a look Underneath

A little while ago I finished work on a support website that was housed on force.com sites and powered by knowledge, Salesforce's new KB solution. While it was fun to figure everything out, I thought I would share to help other avoid that same headache. 

Like all newly released software, it has some bugs and some issues that you will want to look out for, but overall, Salesforce did a great job on this one. Hopefully with some more updates it will reach its full potential and there will be less need for customization.

Creating articles in knowledge can be very troublesome, and the trouble can start sooner rather than later, so its important to carefully think out the best way to implement it based on the company's needs. Knowledge allows multiple 'DataCategories', which is what is used to help filter the search and organize the content. In the old Knowledge version(before 21.0) they didn't give much consideration to Language, so if multilingual support was needed, you would need to make sure you set theDataCategories appropriately before starting. Also if you wanted multilingual, you needed to figure out how to do the urls -> each doc requires a unique URL field(we ended up appending the lang code to the end). Otherwise you would have to go back thought and edit each doc you made to accommodate for that. With the newest release of knowledge (v21.0), it will have a required Language field that 'fixes' the need for it for so much for thought for such an otherwise simple option.


 The DataCategories themselves have their own issues, for one you can only edit / access them though the website, it is not available in the schema browser except though the article types, but only access based on that Artical type for filtering the query / search. On top of that, the interface to edit DataCategories in is, as far as i can tell, an attempt at improving the old edit pages with an ajax-ified 'high-tech' looking one. The page seems to be overloaded with onHovers, double-click to edit, ajax-rerenders and modals, to a point that loses usability, making it had to get at the data you need, thus rendering the page unusable. It does look nice though.

Creating different Articles Types for your knowledge base raises some more considerations that must be thought about before getting started. One nice thing is that you can create any number of Article Types, for example, my implementation has 9 including:
  • Alerts
  • Internal
  • Videos
  • Documents
  • FAQs
  • Release Notes
etc. On the surface, in the 'Article Management' tab, it gives you another 'ajax-ified' looking UI, that doesn't allow for easy sorting or viewing of the Articles. The table's columns are mostly sortable except by Type, they also allow you to filter by Data Category OR allow Queuing , making it impossible to manage anything more than a hundred articles. My Org has somewhere around  5000 articles across 3 languages and growing I might add. 


Unlike other sObject records in Salesforce, the Article Type obj has a required 'URL name' field that is also required to be unique. They also added attachments as a field type to the Article sObjects, but it can cause some unexpected errors saying that the DML limit has exceeded in certain use cases, and it had a few other quirks that just made working with them a headache. Since the out-of-the box fields on the sObject is minimal, its key to plan out each ArticalTypes fields carefully, and thoroughly to avoid having to back track later.
In making  an Article, the first thing to note is that Salesforce enforces the save draft, then publish principal, which would be good but without queues to sort the articles, it does little more than become a performance issue. Its also not possible to create and then publish Articles via apex, you can create a draft article, but not to publish or make it 'public'. 

The rich text editor that Salesforce uses is limiting since they are using a 'lite' version of another rich text editor called FCKeditor, making it necessary to compose the Article in HTML else where and copy / paste it into the editor. But as you would expect there is issue with this as well, since it was not designed for such use.

Looking at the Article in the schema browser you will notice that there are 5 sObject for every Artical Type, and each has a unique extension:

  • ArticalType__ka
  • ArticalType__kav
  • ArticalType__ViewStat
  • ArticalType__VoteStat
  • ArticalType__DataCategorySelection

The __ka sObject is the top level article, but it doesn't hold any of the actually article info like Body, Title, etc, that is housed in the __kav obj, which has access to the  __DataCategorySelection obj for searching. But if you want to see __ViewStat or __VoteStat, you need to go through the __ka object. This may seem like a pratical set up but the __ka object almost holds no value except to make it harder to transverse the layers, ideally it should be the __kav with everything underneath it. The __ViewStat and __VoteStat sObjects have a few drawbacks as well, if you were to have it on a public site, only users that login could rate Articles (__VoteStat), which means a Salesforce license for every potential user on the site. The __ViewStat however doesn't require log in, but with testing over time, we found that it would stop working periodically, and so wasn't reliable.

Example SOQL code with Data Categories:

List<FAQ__kav> f = Database.query('Select f.ranking__c,f.VideoUrl__c,MacVideoUrl__c,f.Localized_Title__c,f.KnowledgeArticleId From FAQ__kav f WHERE f.ranking__c != null and PublishStatus = \'online\' and IsVisibleInPkb = true WITH DATA CATEGORY Languages__c BELOW '+lang+'__c AND Products__c BELOW '+prod+'__c order by f.ranking__c DESC limit 10');

Example SOSL:

List<List<SObject>> qry = search.query('FIND \'access code\' IN ALL FIELDS Returning Documentation__kav(ID, knowledgearticleid, Title, Localized_Title__c, UrlName, LastPublishedDate WHERE PublishStatus = \'Online\' LIMIT 5),FAQ__kav(ID, knowledgearticleid, Title, Localized_Title__c, UrlName, LastPublishedDate WHERE PublishStatus = \'Online\' LIMIT 5) WITH DATA CATEGORY Products__c BELOW (lmipro2__c,lmifree__c) AND Languages__c BELOW (en__c,es__c)');

Example in accessing Data Categories:

               for (FAQ__kav f : faqList)
               {
                        FAQ__DataCategorySelection[] dc =  f.DataCategorySelections;
                        for(FAQ__DataCategorySelection d : dc)
                         {
                              if(d.DataCategoryGroupName == 'products')
                              {
                                    if(GlobalHelper.CheckForNotNull(dataCProd))
                                    {
                                          dataCProd = d.DataCategoryName;
                                    }else{
                                          dataCProd += ', '+ d.DataCategoryName;
                                    }
                              }
                              if(d.DataCategoryGroupName == 'languages')
                              {
                                    if(GlobalHelper.CheckForNotNull(dataCLang))
                                    {
                                          dataCLang = d.DataCategoryName;
                                    }else{
                                          dataCLang += ', '+ d.DataCategoryName;
                                    }
                              }
                        }
                  }

Again this was not meant to 'Bash' salesforce, rather it is meant to be a guide around the mishaps that I encountered when doing my implementation. But on a side note, because some of the issues are too big to ignore, I am now tasked with re-creating the whole site in .Net :-P 

Questions? 

Twitter: @SalesForceGirl  or Facebook



10 comments:

  1. Great post Randi. Thanks for sharing your knowledge about Knowledge. So is the nav list on the left on the site the Data Categories?

    ReplyDelete
  2. Sorta, since we divide our site up by Product, it made sense to also use it as a Data Category. But it does set the product in the search param and the site cookie.

    ReplyDelete
  3. Nice post. What about leveraging multi-lingual knowledge feature that we release in Spring'11 instead of having this Language data category?

    ReplyDelete
  4. take a look at my newest post:

    http://salesforcegirl.blogspot.com/2011/04/knowledges-new-multi-lingual-support.html

    ReplyDelete
  5. Fantastic Articles SalesforceGirl! Thanks, saved me a headache just like you said!

    ReplyDelete
  6. Hi , I am curious
    I installed salesforce's app exchange package , knowledge on public site 2
    and i want to show image on main page instead of title ,
    how will i proceed about this ..
    https://appexchange.salesforce.com/listingDetail?listingId=a0N300000059QxXEAU

    ReplyDelete

  7. Thanks, this is generally helpful.
    Still, I followed step-by-step your method in this salesforce cpq online training
    salesforce cpq online training India

    ReplyDelete