Customizing the Knowledge Syndication widget

I've observed a couple of Knowledge Syndication widget questions popping up lately, so I thought I'd do a quick demo of how you can customize the behavior of the widget.

Customization via Config Options

As always, you can use the standard configuration options during widget instantiation. These are well defined in the CP admin panel and can be found a the following address (substitute in your domain).

https://interface.custhelp.com/ci/tags/syndicated_widgets/standard/KnowledgeSyndication

For example if I wanted to change the Search Button label to "Find", I could pass the "label_search_button" config to the instantiation like so:

RightNow.Client.Controller.addComponent( { div_id: "myDiv", instance_id: "skw_0", module: "KnowledgeSyndication", label_search_button: "Find", type: 3 }, "//training.rightnowdemo.com/ci/ws/get" );

Advanced Customization via Events

Additionally, RightNow syndicated widgets use an event bus that allows a developer to subscribe to certain events and execute custom code. I've written a post on this topic previously titled Proactive Chat - Intercepting Chat Events

The Knowledge Syndication widget exposes events in a similar fashion including:

  • evt_dataRequest
  • evt_searchResponse
  • evt_searchRequest

I can use these events to tailor the behavior of my widget implementation.

Example Customization

Say hypothetically I wanted to change the behavior of the widget so that if a user performs a search and results are returned, a new window opens that displays the search results directly in Customer Portal. If no results are returned, the widget follows its default behavior which may include displaying spelling suggestions. I can accomplish this by subscribing to the "evt_searchResponse" event and taking appropriate action. One of the data elements returned by the "evt_searchResponse" event is how many search results are returned by the query. I can use this information in my event handler to determine whether I should open a new window. Additionally, I can retrieve the original Query parameters and pass this to the new window. Since I am opening the standard Customer Portal Answer List page, I can pass the query as a URL parameter (note: not in GET format) with a key of 'kw'.

RightNow.Client.Controller.addComponent( { div_id: "myDiv", instance_id: "skw_0", module: "KnowledgeSyndication", type: 3 }, "//training.rightnowdemo.com/ci/ws/get" ); RightNow.Client.Event.evt_searchResponse.subscribe(function (event_name, data) { if (data[0].id == "skw_0") { if(data[0].data.totalResults > 0) { window.open("//training.rightnowdemo.com/app/answers/list/kw/" + encodeURIComponent(data[0].data.Query[0].searchTerms, "_blank", "height=800,width=900")); //Do other things, like CSS operations on DOM elements } else { //no results are returned. do something different } } });

I've additionally published this working demo on JSFiddle at http://jsfiddle.net/fishnugget77/J7ShH/. Feel free to fork my code and experiment with how the events work and what data is returned by the 'evt_searchResonse' event.

Comments

Thanks Andy. This really helps.
My only concern is I also have to display some pre-selected answers based on which page the client has searched. For example if the client is searching from page 1, then the answers displayed should be based on their search plus few answers that I think is relevant to them.
I am losing the ability to do so with this approach. since persist_prodcat attribute is not being considered.

Any views how this can be achieved.

So If i understand correctly, when you instantiate the widget you are passing a product ID "p" and the "persist_prodcat" flag as true.

I've update my fiddle code to show how you would handle this.
You can get to those initial config values in the event handler and use them to construct the URL of the window you open.

http://jsfiddle.net/fishnugget77/J7ShH/

This example shows both how to pass the p and c parameters to the new window.

Andy,
I tried to search for 'return' keyword in Knowldege Syndication Customization Demo but it is not opening any window nor returning any result whereas

http://training.rightnowdemo.com/app/answers/list/kw/return

return 6 FAQs when run from a seperate browser.Can you tell me why is it not launching a new window?

Hey Andy.

Your code works perfect !!! but I am still have issues.

My requirement is to display results based on
1. The keywords\phrases searched by the client.
+ (plus)
2. Few additional answers based on what page the client had done searching (The KS widget will be available on multiple pages)

If I use the product id, it actually filters the record and does not add more answers to the result set. Therefore your code still works fine but my logic to achieve this requirement in not correct.

Any idea if I can achieve this, I have tried the 'Search Query (q)' parameter. It works when the page loads but as soon as the client searches, the value for 'Search Query (q)' is not retained and only results related to clients search is displayed.

I assumed 'persist_prodcat' will work for 'Search Query (q)' as well but it does not. As name suggest it only works for product and category :)

Any hacks for this?

The answer really depends upon how you have your Answer search report configured. I believe (note: i'm not 100% certain) the knowledge syndication widget will use the report indicated by the Answer Report that is selected for your interface under the Interface Workspace (Configuration component -> Site Configuration folder -> Interfaces workspace).

It sounds like this report will need to be configured to use "OR" conditional logic instead of strictly "AND" conditions. You could easily map your Bucket 2 answers to products or categories and use this as your mechanism of segmentation (we already have the code set-up to pass through the Product/Category). Since the Knowledge Syndication widget doesn't have the ability to pass custom filters to the report (at least as far as I'm aware), you are stuck with using these fields only.

You could probably also get creative and set up another event handler to modify the query string upon search. You could try setting a prefix on the query string, then use some logic in the Answer search report setup to search either simply on the entire string, or use a regular expression to slice out the prefix and suffixes (this might be overkill for what you need).

I forked my JSFiddle to show an example of how I would do this. My example uses another event called the evt_beforeDataRequest to modify the search parameters before they are sent to the server. My implementation inserts a prefix to the query string.

http://jsfiddle.net/fishnugget77/3m2nA/

You'll probably have to play around a bit, but hopefully this give you some additional ideas.

I had tried the approach of adding the addition search criteria in URL. The issue is it appears in the Search box.
For example:
The client searches for Iphone and I am adding that additional search criteria in URL as "Contract Details Page".
The search box displays 'Contract Details Page: Iphone'
This gives me the required result but the from the clients perspective, he is seeing as the text above which is not very decent

Andy,
These are super helpful posts. Thank you for writing them.
I'm trying to change some of the initial response from the Knowledge Syndication Widget before rendering it.
Specifically, the base URLs for the links to the articles returned.
Is there an "onLoad" or "onReady" for that?
The 3 events listed here only fire when the search feature is used.
I've searched the RightNow.Client.js for something that would work to no avail.
Thanks for your help/ideas!

Typically a syndicated widget will fire the "evt_widgetLoaded" event after loading, which allows you to modify the object. I dug around and it seems like the KSW doesn't ever call this event.

There seems to be no good way to modify the initial content within the RN framework. You could choose to not display the initial content using CSS, then using the JS callbacks modify the first dynamic search results and re-enable the content. Other than that, you might have to use JS to watch the DOM for that first content load.

Thanks for taking the time Andy.
I did end up having to go with something similar to your last thought there:
Not great, but works.

$(function(){
$(document).on('DOMNodeInserted', '.KnowledgeSyndication', function(){
$('.KnowledgeSyndication a').each(function(){
// modify links
});
});
});

Zircon - This is a contributing Drupal Theme
Design by WeebPal.