Showing posts with label Sitecore. Show all posts
Showing posts with label Sitecore. Show all posts

Friday, June 15, 2007

Blog War: EPiServer vs Sitecore vs Reddot


Some months ago I came across Blogpulse.com (by Nielsen Buzzmetrics) which is a cool service that monitors how popular certain topics arein the Blog-sphere. Just for fun I ran this comparison between 3 of the major european CMS vendors: Sitecore, EPiServer and Reddot.
It would seem that all of the vendors have huge variations in their blog-popularity.

I also couldn't resist trying out battle-of-the-giants BlogPulse and this is what I came(Google vs. Microsoft vs. Apple) on the up with. It would seem that Google is in the lead Blog-wise, but both Microsoft and Apple are gaining (naturally you'd have to take into consideration that all blogs about the fruit that goes by the same name as a major soft/hardware company is also part of the graph).

Friday, March 16, 2007

MondoSearch Result Authentication

A very typical request I often hear from customers and partners is the ability to return only the results that the current user is allowed to see. This desire is very natural, but can often present quite a challenge to 3rd party search engines like MondoSearch. The problem is that it varies a lot from each individual setup how authorization works, and hence no general solution can be made. We can only deliver specific solutions of authorization to specific systems (like we have done for EPiServer or Sitecore) or provide general toolkits/examples that makes it easier to custom-build an integration.
The problem with authenticated problems can really be divided into two sub problems:

  • Indexing secure content
  • Searching in secure content
Indexing isn't that big of a problem. There's many ways to make that content available to the search engine. MondoSearch has built-in support for basic-authorization, challenge-response (integrated authorization) and forms log in, just as well as it's quite easy in many CMS systems to override the security if the client originates from a specific IP, or has a specific HTTP Request setting. Generally we see only very few problems in actually indexing the content. The only thing that can be tricky is when the content on the individual pages vary based on who is logged in. In order to handle that, would require the Search Engine to index the same URL, as all the different users that can access it. Luckily pages with user-dependent contents are typically portal pages that are not all that interesting to index. The articles, documents and database content that's interesting to index are not a problem.

Searching in Secure Content is really the main challenge when it comes to authenticated contents. Even though security for the individual pages typically is checked when you try to access a page, it can still be quite revealing when the title (and perhaps description) of a page is displayed on the result page. In fact, to be totally safe, a user who doesn't have access to certain documents must not even know of their existence from the result page! (Suppose I searched for "invasion plan Iran" on Pentagon's website and was told that there were 10.000 documents I that matched the phrase, but none I was allowed to see).
In order to achieve this there's generally three approaches:
  • Authentication by filtering. Store access rights when indexing the documents and use them in the search
  • Authentication by exclusion. When performing a search, manually check that the current user has permission to see each of the results, before returning it.
  • Rules based authentication. Where a number of specific filters is defined for each user-group.
In general I prefer to use Filtering to perform search result authentication.
With MondoSearch this typically means adding Meta-tags (/data) to all documents defining which groups / users are allowed to view them. And perhaps even which groups/users have specifically denied access.
A Meta-tag like that could look something like this:
<meta name="ALLOW" contents=";53;124;351;33;12341"/>
Then, on the result page, all you'll need is a piece of code that extracts the user-id and the group-ids of the current user and then adding search filters to the search query. Suppose we have a user with user-id "42" and who belongs to the group "users" (id: 351) who performs a search that returns a document with the above meta-tag. The MQL that is sent to the search engine would then have to have these filters added:

"... FILTERS ALLOW CONTAINS ';42;' OR ALLOW CONTAINS ';351;' ...."

To also enforce DENY is a bit more tricky, but certainly just as doable.
The obvious benefits here are: It's very (!) fast, it's clean, it's easy
However there's also a number of downsides:
  • Not all CMS systems support outputting permission-lists to the crawler
  • If access-rules change, they will not be propagated to the index until next crawl
  • It typically doesn't work for non-html documents like Office and PDF (since it's kinda hard dynamically to attach meta-data to these types). However there is a number of workaround to this problem.
The alternative to filtering, is exclusion which in my eyes is definitely not pretty, but sometimes necessary. Authentication by exclusion calls for a custom method is defined that checks if the current user has access to a given URL. A pointer (delegate) of this method is then passed to the search engine that will call it and evaluate every result in the result-set.
The obvious problem is the performance of this solution. On a result-set of 10 pages, with a fast-checking method, it can be acceptable, but often result-sets can be very large. Imagine having to call a custom-made method for every one of 100.000 results - or worse!!
Another problem is that in order to pass a delegate to the search engine the search-engine needs to be installed on the same server as the CMS - something that doesn't always fit into the desired machine architecture.
Of course the performance can be increased of such a method in some cases: intelligent caching, only check the results on the first page, etc. but in my experience it's never a really good solution. In my eyes the only really acceptable use of this is as a compliment to the filtering search (for instance to check access for non-html documents) - or where no other solution works.
In order to set this up on a MondoSearch template, assign a method handler to the "OnAuthorize" event in the SearchControl, like this: OnAuthorize="CheckAuthorization" .
Then define the method elsewhere:


public bool CheckAuthorization(string url){
return true;
}

The last authentication method I will briefly touch in this post is to use a number of rules.
The idea here is that by applying knowledge about the security setup on a website, a couple of simple rules might do the trick.
Imagine a simple setup where only two types of visitors exist on a web-site: logged-in and not-logged-in, and that all the content that only the logged-in users were allowed to see is in the sub-directory "/secure".
In this case you could simply apply some additional MQL when a visitor performs a search:
if(!logged-in){ mql+="FILTERS @CHANNEL!='secure'"; }

This is an ideal approach, but it doesn't work on all sites.

Monday, February 5, 2007

MondoSearch for Sitecore (Part 4)


Like all good trilogies, this one comes in more than 3 parts :-)

The last little detail in the integration I want to show is the overall architecture. The entire integration between the products are based on 4 key XML WebServices, provided by the MondoSearch products and consumed by the integration within Sitecore.
These are:
  • MondoSearch Search WebService
    Probably the most important WebService. This is the service that handles all the searches. It takes a query in MQL (Mondosoft Query Language), performs a search, and returns results as a dataset. It's used by the search/result pages, the editor search as well as the Similar Pages code example. It's possible to have the integration working only with this service enabled - although naturally all other features than search in the integration will be disabled.
  • MondoSearch Admin/Crawler WebService
    This service can control the MondoSearch crawler as well as doing some essential setup and configuration - like adding starting points, reporting on crawler status, etc. It takes MQL and a connection string (holding user name and password and license key) as input. It's used in the Crawler Control application and the Start Crawler task.
  • BehaviorTracking WebService
    This is the service that extracts all the important information about the users search behavior from BehaviorTracking. Once again it's based on MQL and Datasets which makes it easy and standardized to use. It's used all over - in the BT Portal, Term Details, Related Topics, Item Details, autocomplete searchbox, etc.
  • InformationManager WebService
    InformationManager is typically used by the webmaster or marketing dept. to optimize the search based on user behavior. This could be by adding SearchHeaders (custom pieces of HTML in the top of the search results, based on query), SearchNames (direct link to a specific page for a given search query), synonyms (goes without saying) and so on. The webservice provides easy MQL based access to all these features. However the only feature thats included in v.1.1 of the integration is SearchHeaders - so here's room for improval :-)

Since all of this is based on WebServices it's easy to imagine how you can split up your servers. It's quite easy to have a hosted search solution, as well as hosting the search yourself. You could even host it yourself each product on a different server, and have a fallback hosting scenario setup if company policies requires it.

Another benefit that I find really cool is that the integration leaves room for adding your own components based on the search/behaviortracking functionality, since the classes used to call the webservices are public. Just imagine the possible awesome features it's possible to implement on your site. For instance how about adding a "Personal Suggested Links" box on the front page, based on the visiting users history of searches/browsing on your site?!
Or how about implementing your very own "Local-by-global" search which catches the queries from Global search engines that led users to your site and performs a local search on them, suggesting other relevant pages?!
And the code is pretty simple. In order to perform a search simply write something like this:


using Mondosoft.SitecoreIntegration.Search;
...

private void DoSearch(){
ServiceWrapper service;
DataSet results;
...
service = new ServiceWrapper(Configuration);
results = service.ExecuteSearchMql("OPTIONS Query='Sitecore' "+
"FILTERS AUTHOR CONTAINS 'Allan' "+
"LIMITS FirstResult=0 MaxResults=5");

gridView1.DataSource=results.Tables["Pages"];
gridView1.DataBind();
}

I hope a lot of partners and customers will pick up this challenge and make some really cool implementations of this. Now it's up to you guys :-)

Wednesday, January 31, 2007

MondoSearch for Sitecore (Part 3)

As promised, I'm going to share some more screenshots of the integration between MondoSearch and Sitecore. This time I'll focus on the integration of BehaviorTracking.

BehaviorTracking Portal. The main entry to the BehaviorTracking information from within Sitecore is in the BehaviorTracking Portal, a portal somewhat similar to the well-known Sitecore Today portal, only this time the portlets filling it are BehaviorTracking portlets. Although we're still missing some of the graphics from the original BehaviorTracking this makes out a pretty decent approach to discovering what your website visitors are interested in and by double-clicking on a given keyword, it will open the BehaviorTracking Term Details for that search term.



BehaviorTracking Term Details. When you want to examine a specific search term, you can use the XAML application Term Details. Here you can look up search words, and examine

a) Which search terms are related (meaning which other terms are typically used by the same users in their searches). This can be quite helpful in inspiring new keywords for pages as well as new synonyms for the search.


b) Which pages are typically chosen from the result page, giving you a more exact idea of what the user actually meant. Use this for improving ranking of some pages, or perhaps adding a searchheader or searchname for a given page.


c) The most recent user sessions searching for this term. This might not be so useful, but it does give you that cool "Big brother" feeling :-)


Finally, you can also get BehaviorTracking Item Details. For any given item on the website that inherits from the MondoSearch Base Template, you can see a list of which search terms sent users to the various versions of this page. This is an excellent tool to optimize the content on the individual pages, to the expected content of the users.




As mentioned in Part 2 of this trilogy the along with the integration we also released some code samples, showing how to use BehaviorTracking and search to spice up your site.

On last of these examples is the "Most Wanted" list that is a small control listing the top 5 pages most often chosen from a search result page. I find this to be quite useful, as this is not the most visited pages on the website (the most visited page on a website is quite often the front page that doesn't hold any relevant information at all), but the pages that most people have been looking for. In many cases it will be quite a good help for your users to promote these pages on the front page so they can go directly to them without wasting any more time.

Monday, January 29, 2007

MondoSearch for Sitecore (part 2)

As earlier promised, here's some more info on v. 1.1 of the integration between MondoSearch product suite and the Sitecore CMS system, that was released just before christmas. In this second part of my story I will focus on the search itself and the ways it has been integrated.

The point of the integration was to integrate not only the search engine but also search analytics, crawler administration into Sitecore, making Sitecore a common user interface for both products.

The reason is simple. Although website search over the last couple of years has become increasingly commoditized it's not just something you plug in once, and then expect to have working perfectly ever after. Search is a dynamic thing - like the website it indexes and for the best end-user experience it should be continiusly tweaked and improved to match the expectations of the end-users. The ideal way to do this is by studying the behavior of the users and then optimize both website and search for them (I could talk for hours about this subject, but I'll safe that for another post). Nevertheless that makes it even more important to make the Search and Behavior analytics easy to use for the webmaster/marketing dept. responsible for a given website - and hence we decided to go for as complete an integration between the products as possible.

The search part of the integration includes:

3 Search Result Sublayouts, all based on a Search Template. All of the support Sitecore authorization enabling them to only show the results the logged-in user is allowed to see. All the texts used on the templates is defined in the template, so it's easy to translate in Sitecore. The Sublayouts use the standard MondoSearch SearchTemplate technology so it's easy to change look & feel and add functionality.














2 SearchBox sublayouts, simple and advanced that can be placed on any layout to enable the possibility to search.

Click Item and corresponding layout, enabling logging and highlighting of search results.


A Meta-data xslt rendering for sending item-related meta-data to MondoSearch.



A Base template that allows Sitecore items to have fields to hold meta-data for MondoSearch, including Search categories and indexing rules.














A Crawler Control XAML application that allows an administrator start and stop the MondoSearch crawler as well as publising crawled databases. This tool will also display the current status of the crawler, crawler log and number of indexed pages.


A Sitecore task for starting the crawler
so the Sitecore scheduler can be used to scheduling crawls.


An Editor Search XAML application that allows Sitecore editors access to use MondoSearch to find the items they want to edit. When a result is selected it will of course open in the Content Editor for easy editing.



Templates and items for defining Categories used in Search.



MondoSearch Examples
On top of the integration Mondosoft also supply some coding examples of how to improve the overall functionality on the website. Like this Autocomplete search box that uses frequently searched words as autocomplete suggestions that appear while you type a search query.




One of the other examples is a "Related Pages" box that will use the search engine to search for other related pages to the current page, and "Related Topics" that will use Behavior Tracking to suggest search terms relevant for the page you are currently on.

Now, this was just a brief overview of the "search part" of the integration. In the next post I'll go through all the new cool features the integration adds to Sitecore to track visitor behavior and search term popularity.
Later on I'll also show how the it's possible to add SearchHeaders (custom html/sponsored links) to the search results from within Sitecore and outline a couple of ideas I have on how to further improve the overall value of a Sitecore website.

The new update of the Integration demo-site is due to be launched any day now and it'll be possible for all interested to try out these features on their own - either on the demo-site, or by downloading the integration.

Wednesday, January 24, 2007

MondoSearch for Sitecore (part 1)

As my previous post today might indicate I've been spending my time setting up a public demo-server for the MondoSearch-Sitecore integration.

Even though I was project-manager on the integration project, I must admit that I'm a once again a bit surprised (read: proud) how smooth and easy the integration works once both Sitecore and MondoSearch is installed and working.

It just takes a few steps like installing a package in Sitecore, adjusting web.config, and doing a little customization in your Sitecore website for neatness.
It's a pretty full integration, integration both Search, Crawler Administration, Search BehaviorTracking and Marketing tools for optimizing search within the Sitecore admin UI.

I just need to tweak a few more details to make the website really fit for public display - and as soon as that's done I'll post a lot of screenshots here about it.

For now you will have to settle with this screenshot of the MondoSearch Crawler Control as a Sitecore XAML application.

Permissions. Can't live with them, can't remove them

Here's an annoying little problem that has been pestering my life for a good day or so. On a newly installed win2k3 server with SQL Express 2005 I was trying to install the Sitecore Demo-site "Printers Inc.". Since the demo-site uses attached databases to SQL Express 2005 it was supposedly fairly easy to install: unpack a zip file, setup IIS, set the right login/password for your connectionstring in a config file.
All done, and try to open the site, but get greeted with this message:

Server Error in '/' Application.

Unable to open the physical file "D:\sites\Sitecore\MySite\Databases\sc53Master_Data.mdf". Operating system error 5: "5(Access is denied.)".
An attempt to attach an auto-named database for file D:\sites\Sitecore\MySite\Databases\sc53Master_Data.mdf failed. A database with the same name exists, or specified file cannot be opened, or it is located on UNC share.


Okay...Looks like a permissions thing I thought...So I hurry and give ASPNET and NETWORK SERVICE users full rights on the entire site, and set it to propagate rights to children (security, who needs it anyway?!). Still the same problem....At this point I actually start reading the error message more carefully..Oh, it actually suggest 3 possible error scenarios...well - let me see: It's on a local disk, so forget about the UNC thing. A visit to SQL Server management studio proofs that there's no database with the same name (why would there be? it's a brand new server). And I had just made sure that the permissions were right.
At this point I naturally went to the no.1 problem-fix with microsoft products - but even a full reboot didn't seem to do the trick...Now what?! Checked with the local SQL-server wizards and our sysadmin guru....posted the problem on SDN5 Forum...still no luck.
After wasting too much time I (we) reached the point of desperation where you try out stuff that just doesn't make sense in trying to solve this problem - like setting up the SQL Express service to run as "Local System" instead of "Network Service". And what do you know - it paid off...all of a sudden everything worked splendidly. Still doesn't make sense to me - Network Service had full permissions for the databases....arggh.

Thursday, January 18, 2007

"Manually" importing Sitecore Items

Well back from Ukraine, I better deserve the kind mention on Alexey's blog with a couple of Sitecore hints.

As many others I've on occassions spend some time struggling with packages in Sitecore. Especially with large packages, the scaling of the build-in packager doesn't seem optimal (at least in versions prior to 5.2.0.12), and when running through a webbased environment the entire installation process of a large package could easily fail do to browser / IIS timeouts.
All in all, I must admit to having been a bit annoyed with the entire webbased architecture of the packager - it was difficult to generate a package as part of an automated build-process, it was difficult to work with programmatically and as mentioned, it would crash often (it does seem to look somewhat better in Sitecore 5.3). So naturally I set out on a small quest to make my own console-based packager for Sitecore, however still based on the same package format (zip files with a mixture of files and xml-items). The goal of this tool was to run in a build-test enviroment for packages doing the following:
  1. After a new compilations of the components of a package is completed, extract the items and files necessary and make a package automatically
  2. Automatically install a number of packages on a dev-server to prepare it for regression-testing.
  3. A tool for manually syncronising certain items in Sitecore
I examined the architecture of the packages a bit and decided that it would probably be easiest to let my source-control system handle the files, extract them to a "files" folder, then add the items extracted through the Sitecore WebService (from a list of items defined in a source-controlled file) and put them as xml files in an "items" folder, then add meta-data and zip the two folders. However I never got my solution working - my best guess is that zip-format used by Sitecore isn't standard. This could probably be brought to work - but not in the time-frame I had available.

However for the second task I did manage to create a small, but ugly, tool that could assist in manually installing packages (the ordinary packager crashing was a good motivation here).
Since I never completed the tool, I won't put it here for download, but let me just share the code-bit that uses the Sitecore webservice (located at "/sitecore/shell/webservice/service.asmx") for updating items. Perhaps it will be of use to someone out there facing the same problems as I was.
To manually install items extract the items from a sitecore (5.2) package using a zip-program. Then run this code on the folder containing the items.



string importpath = args[1];
ws.Credentials c = new SitecoreItemExport.ws.Credentials();
c.UserName = Properties.Settings.Default.Username;
c.Password = Properties.Settings.Default.Password;
ws.VisualSitecoreService service = new SitecoreItemExport.ws.VisualSitecoreService();
List<String> Paths = new List<string>();
GetPaths(importpath, ref Paths);
foreach (string p in Paths.ToArray())
{
StreamReader sr=File.OpenText(p);
string xml = sr.ReadToEnd();
sr.Close();
string db = "";
string id = "";
ExamineItem( p, ref db, ref id);
XmlNode xn=service.InsertXML(id, xml, false, db, c);
if (xn.InnerText == "ok") Console.WriteLine("Success: " + p);
else Console.WriteLine(xn.InnerText+" "+p);
}


The "ws" is a namespace pointing to a web service reference, the credentials used is the admin login for Sitecore and it uses the method "ExamineItem" for some simple string manipulation (getting the database and db-item-path from the file-path of the item xml file).

Friday, January 12, 2007

Adding web applications to a Sitecore IIS site

A problem one often faces when trying to install 3rd party web software (like MondoSearch) on a Sitecore website, is that any non-Sitecore related virtual directory or web-application place on the same IIS website will run into a lot of problems.
This is naturally due to the httpModules, httpHandlers and roleManagers set by the Sitecore Web.Config in the root of the website.
The easiest way to get around this (besides installing on another IIS Site, which can be difficult on an XP developer machine) is to put a web.config in the non-Sitecore related web-application that removes all of the modules, managers and handlers set by Sitecore.

For a default installation of the Sitecore 5.3 demo-site, Printers Inc. this would be:


<httpModules>
<remove name="SitecoreHttpModule" />
<remove name="SitecoreUploadWatcher" />
<remove name="SitecoreXslWatcher" />
<remove name="SitecoreLayoutWatcher" />
<remove name="SitecoreConfigWatcher" />
<remove name="StatCenterPersonalizer" />
</httpModules>
<roleManager enabled="false">
<providers>
<clear />
</providers>
</roleManager>
<httpHandlers>
<remove verb="*" path="sitecore_media.ashx"/>
</httpHandlers>


In other installations / versions this might vary a bit, but you can always check the sitecore web.config and see whats added, so you can then remove it.