Localization of your search page

speak the language

Couple weeks ago I was psyched to start a series on our first hand experience dealing with Coveo for Sitecore on a multi-tenant/multi-site Sitecore instance.  Check out my first two posts below:

Link Manager Gotcha
Get Your Links right

Now, last, but, not least when you have such huge instance of Sitecore, you are bent to have things you would want to localize due to multiple languages you are supporting.  I usually see the solution in two folds.

  1. Coveo OOTB component localization
  2. Custom string localization – Like Facets or any strings on your search listing card that are computed field for instance.


The first one is quite simple and easy to do as Coveo carries responsibility OOTB to load most close culture based on context language.  If you go to viewsource on your search page, you will see that Coveo has already done some magic for you.  It loads the culture *.js file based on your context language.    This happens right the view based on below line of code on Coveo Search View. 

<script type="text/javascript" src="/Coveo/js/cultures/@(Model.CultureName).js"></script>

That should take care of your result summary on left top corner above your results.   For your sorting components which you may have added using your DateSortView or RelevancySortView, to localize the sorting header such as “Relevancy” or “Date” in context language, Coveo looks for special data attribute on HTML called ‘data-caption’ and if your HTML element for your facet has this attribute loaded with your title and if that is a existing key on locales dictionary object of your interested culture/language then it is respected and corresponding localized string is shown on your page. 

Now, for the second fold, if you would like to localize your Facet values, Headers, etc., There are few things to consider/answer – Do you show just one language content on your search page per site?  If you are – Life is simple, just ensure you have localized content loaded on your Facet field.  If your facet is based on computed field, ensure you are loading language specific value based on currently indexed item language.   For your facet header to be localized, you have couple of options here as well, you can either read it from your localized dictionary on Sitecore if you have one, if not, load up your JS localize dictionary with new values as noted in the link below.

https://docs.coveo.com/en/421/javascript-search-framework/changing-the-language-of-your-search-interface

Now, the problem actually happens when you have more than one language content show up on your search page, in that case, you will have an issue with mixed values which obviously is not UX friendly.    You can see a good solution and huddle between me and my favorite Sitecore MVP and Coveo champ below(@jflh ). 🙂

https://answers.coveo.com/questions/16338/localize-facet-values-on-multi-site-solution-using.html?childToView=16358#comment-16358

This is the last piece of this series and I am sure there will be more to come, this one is near and dear to my heart and the amount of learning and information I gathered through this Implementation is priceless.  Although, Coveo and Sitecore never fail to amaze me, there is more room to learn and grow with these products every single day. 😉

Happy Coveo for sitecore implementation to every one!

Some helpful links:

https://developers.coveo.com/display/public/JsSearch/Localization

https://docs.coveo.com/en/421/javascript-search-framework/changing-the-language-of-your-search-interface

 

Coveo and Sitecore Link Provider

links

My last post was a kick off a series of things to watch out for and pay attention to while implementing Coveo For Sitecore on a Multi-tenant/Multi-Site Sitecore instance.   This is a runner-up for my last post and part of same series.  Let me start this by saying, URL on search result is single most important entry point for your user to see detailed content around what they think is relevant.  To ensure this is rendered right every single time,  It is very critical that you know your Sitecore Link provider or Custom Link provider if any in and out on your Coveo For Sitecore installation.

There are few things that you will need to know in order to fine tune anything or in order to debug issues if any when you see things you do not wish to see in relation to Url’s either on Indexes or on your search page.  If you are lucky and do not have much of customization going in your Sitecore link provider, you should be fine doing nothing as Coveo fires off link provider at it’s two most important phases OOTB.

  1. Index Sync Process
  2. Displaying paged results on Coveo driven search page

Now, the most important thing to remember is that while Coveo does #1 noted above it calls Sitecore Link Provider in “shell” context while doing it’s best to load up UrlOptions object that is passed in as a parameter to Sitecore GetItemURL method of Link Provider with appropriate site details it could resolve the currently indexed item with.   Coveo has their algorithm that runs as part of ResolveItemSiteProcessor located in coveoResolveItemSite pipeline.  Below is the snippet of that processor located on Coveo.SearchProvider.Config

<coveoResolveItemSite>
<processor type="Coveo.SearchProvider.Processors.ResolveItemSiteProcessor, Coveo.SearchProviderBase" />
</coveoResolveItemSite>

If this processor is not working wonders for you, go ahead and remove this in your favorite custom coveo configuration file and add your own.   For curious brains,  I recommend changing your level of logging to DEBUG to understand what happens step by step while Coveo tries syncing your Index.    That was very insightful in understanding sequence of calls and pipelines that fire while Coveo is indexing or doing sync process.  But, do remember change that back to INFO after your appetite is satisfied. 😉

Now, for the last clue,  on #2 stated above when your Coveo Search Page renders your search results for a query, it calls Sitecore link provider again to get the click uri for each search result that goes with each search result.  Now, pay attention here, very important to know that the context site this call runs in is “coveorest”.  If your link provider is super awesome and written very well thought out, you will have no problems regardless on the context site the call is running in.  But, if your link provider is using context.site instead of using site info from UrlOptions or doing some thing really out of this world, you have to know these things to ensure you hit the gold.

Hopefully these tidbits will help you debug any issues while Coveo constructs the URL’s at indexing or run time.  If you have lot of shared content that does not reside under a specific site node, then, it is very hard to get the URL right at indexing time which is why it is even more important to focus on #2 to ensure the end user experience is seamless and correct leading them to correct site, language and context.

There, I gave away a hint, next up, I will be covering language related insights like fall back and localization in my next post.  That is all for now, tune in soon for more.  🙂

 

 

 

 

 

Implement Coveo on Multi Tenant/Multi Language Architecture

I am very excited to start this series as we are almost close to pulling off Coveo Cloud Implementation on a multi site/multi language Sitecore Instance using legacy Coveo For Sitecore Javascript Framework to support web forms Sitecore Implementation.  I am gathering my thoughts around all the challenges we faced while getting Coveo to work seamlessly with complex Sitecore Instance.  Some were very straight forward and some were anything but that. 🙂

I am going to list down each important problem and note options to tackle each.  Do note that though most of the solutions I would attempt to provide are generic, it highly depends on your Sitecore implementation and customization done to Sitecore in general.

One thing that really helped me solve some of these is understanding when and where Coveo connects with Sitecore.   I would recommend to deep dive on this to any one who is attempting to implement Coveo For Sitecore on their multi tenant and multi lingual Sitecore implementation.

I will start by noting the first problem we faced right after Coveo for sitecore installation on our system.  On Diagnostics page, we had the error such as noted in question and answer below.

https://answers.coveo.com/questions/15435/coveo-search-rest-endpoint-invalid-uri-the-format.html?childToView=15530#comment-15530

One of the first question to answer when implementing Coveo For Sitecore is – Does your Sitecore implementation have a custom link manager as that drives what you would need to watch out for or customize if needed, a quick way to check would be

-> Go to your /sitecore/admin/showconfig.aspx and examine what you see in the node below.  if you see default provider as something other than “sitecore”, then, you can ensure that there has been some customization done on this.  To be honest, any medium to high sized Multi tenant instance that has been active on Sitecore for long time would have some customization around it.  So, it is even more important to know how to ensure Coveo works with your custom link provider settings.

link provider section on config

For instance, in our case languageembedding setting on Linkprovider was set to “always” which means that any website/site served by Sitecore, when a link is generated it would append language to it.  That should surely ring some bells, in  Coveo For Sitecore case upon installation of package, you would see three new sites in the <sites> node when you take a peek at showconfig which are named as coveo_website, coveoanalytics, coveorest.  We definitely do not want to add language embedding on these URL’s here to ensure we do not throw off internal business logic on Coveo end.

To gracefully solve this, I would recommend having an ability to use different Link Providers per site.  There is a very decent solution compiled by my favorite Sitecore MVP Jammy Kam below.

Site Specific Link Provider for Multisite Implementation in Sitecore

By doing this we can assure that Coveo specific sites do not have language embedding in it that would cause issue noted on Q&A above.

Of course, if your sitecore implementation was done more on old school style where the answer was – There is a pipeline for that. 🙂

In those cases, check to see where you can ensure to exclude Coveo sites from having language embedding on them.

One open question I do have is would this be any different with Sitecore 9.0+, a short answer might be a NO.  If any one has any input in regards to this, leave a comment.

That is it about our first ever hiccup, more to come soon.  My hope is that this series will help any one who is driven to use Coveo for Sitecore components and power of framework on a complex Sitecore instance, but, are worried that it might be quite a feat or they might be safe using total custom system.  You can re-visit my blog on this topic and I am sure you will get confidence in sticking to framework instead.  🙂

Tune in for more on this series!

 

 

Coveo Cloud Learnings – Part 3

Follow my trail if you have not  read coveo cloud part 1 and 2.  Get a read on them here –

Coveo Cloud Learning – Part one 

Coveo Cloud Learning – Part two 

This is the last blog of this series, but, of course there is no end to learning.  I will continue to post new blogs as and when I encounter an interesting thing to share with you all as I proceed to take on new challenges and projects.

On this blog, I will cover how we used underscore, organized our views for better maintainability and all of this with Helix in play.

First though, Coveo does do an awesome job of documenting how to split result templates on conditions which comes in handy in various json situations.  Learn more here:
https://docs.coveo.com/en/413/javascript-search-framework/result-templates

After some pondering, we did go with data-condition route on our result templates.  We also have to remember to have a default result template at the last in the pile.  For better maintainability, we chose to add in partial views in MVC.  We do not have dynamic views as we only have a set of types.  If your implementation calls for content author control over these, you might choose to provide that additional layer of flexibility.  For us, it is an overhead in various ways, so, we avoided that and loaded the partial views on our own custom coveo search view.

Some thing like below:

@Html.Partial(“~/Views/Search/ResultTemplates/ProductResultTemplate.cshtml”, Model)
@Html.Partial(“~/Views/Search/ResultTemplates/StandardResultTemplate.cshtml”, Model)
@Html.Partial(“~/Views/Search/ResultTemplates/GeneralResultTemplate.cshtml”, Model)

Also, we definitely needed some same key attributes on all of this views and we do not want the Controller code to actually hit every single time, it would be in-efficient.  So, we chose to have a custom coveo model that inherits from the Search Model available in Coveo.UI.Mvc.Models with the additional attributes we need.   It was quite easy to make this happen, also, these instructions noted here might come in handy if you are trying something similar.   Awesome post by Vincent. 🙂 Basically, chose bits and pieces I needed to pull this off.

https://source.coveo.com/2014/12/10/creating-custom-model-coveo-for-sitecore/

Now, we have manageable pieces, so, we can work parallel on different result templates and also great for the future when it is time for enhancements.   In real life situations, it becomes very important while working with underscore templates to ensure a specific json piece you are looking for is not undefined and has a value in it, we had quite a few requirements to not even show a matching label on the view if a specific json attribute is missing.  We accomplished that with a simple underscore check as below on those applicable.  Below is a snippet for your reference.

{{ if (!_.isUndefined(raw.yearoforigin) && !_.isEmpty(raw.yearoforigin) ) { }}
<li class=”coveo-product-details__item”>
<span class=”coveo-product-details__category”>@Translate.Text(“Year of Origin”)</span>
<span>{{=raw.yearoforigin}}</span>
<a href=”#” class=”more”>(+)</a>
</li>
{{ } }}

Also, note that we continue to follow Sitecore best practices on the side to load all labels from Dictionary instead of hard coding on the view.  Another thing to note, is for the data conditions you need on the result templates, if it is a static value such as a GUID or string, always follow Helix best practice of having these defined in Templates.cs file of your project.  In our case, we maintained this in Feature Search project.  So, the data condition and templates.cs would look like –

<script id=’faqResultTemplate’ class=’result-template’ type=’text/underscore’ data-condition=’raw.contenttype==”@Templates.ContentTypes.FAQType”‘>

public struct ContentTypes
{
public static readonly string FAQType = “FAQs”;
}

I know, I wish this is not a string and is a GUID, but, unfortunately due to content structure we had to work with has these distributed out in content areas rather than defined templates, so, had to go this route.  But, where you can always rely on GUIDS as that is more stable implementation.

Also, we had lot of external fields which need to be used as Facets in our case.  There is documentation on how to make an external field Facetable, but, one thing to remember is actually a combination that you will need to do to make this work.  You have to do what is noted here and also ensure you add the field to external fields section as well.  As always,  it is always recommended to patch using a special config file on your Helix project rather than updating either custom coveo config  or raw coveo config file.

Say, if I had a field on my Cloud Index called contenttype, I would then add the following on this patch config file to ensure it is facetable and hash is excluded considering this is an external index.

<configuration xmlns:patch=”http://www.sitecore.net/xmlconfig/”>
<sitecore>
<coveo>
<defaultIndexConfiguration>
<fieldMap>
<fieldNames hint=”raw:AddFieldByFieldName”>fieldType fieldName=”contenttype” isExternal=”true” settingType=”Coveo.Framework.Configuration.FieldConfiguration, Coveo.Framework” />
</fieldNames>
</fieldMap>
<fieldMap>
<externalFields hint=”raw:AddExternalField”>
<field fieldName=”contenttype” />
</fieldMap>
</defaultIndexConfiguration>
</coveo>
</sitecore>
</configuration>

Also see this interesting post below that we used to migrate all our external fields on to production sandbox when we are ready.  We had lot of custom fields added to sandbox due to what we were trying to accomplish and wanted to eliminate manual work to load these up and replicate to avoid error and mundane task.  Thanks to coveo team for letting us know a better way does exist.  Take a peek of that here

Another interesting thing I bumped in to while working on this project was how some functionality is abstracted out from us on Cloud as compared to on-premise.  On Cloud, especially when working with trail sandboxes, if you queue way too many rebuilds, it might take a while, so, do not panic and give it some time.  All should be fine unless there is something else going on, if your logs are clean and no obvious errors on cloud console logs, you should be fine and it is just a delay on the cloud queue as trial sandboxes might not be given immediate preference.  If in doubt, talk to your Coveo point of contact and they will calm you down. 🙂

Also, when you are in active indexing state, say items are being added to your external index on cloud.  Sometimes, same queries and parameters passed from your Coveo Search Page/Components could yield different results due to elastic nature of Coveo.  Obviously, this should not happen when indexing is done.  But, I was super curious to know the reason behind this as I was doing some smoke test on my end.

That is all for now you all, have fun and enjoy the week ahead. Happy Monday!

Leave me a comment if you are curious to know more.

 

 

 

 

 

 

Coveo Cloud Learnings – Part 2

search

Last week, I kick started a planned series in effort to pour over my side of story using Coveo Cloud platform first hand.  You can read more on the initial piece here

I am hoping this series will help any one starting a Coveo cloud implementation in making appropriate choices along the way based on project and requirements on hand.  I would also post catches/gotchas that I experienced along this journey as well.

Now,  let us move on to more.  After the initial steps, there are more choices to make such as below.  I wish I could say – go with your  gut, lol.  Always go by a thoughtful and knowledgeable call on each of these.  When in question, use rock solid support from Coveo and Sitecore team.   You can ping on slack channel or load a Q&A here .  More than likely, if your decision is a basic one, there could be one already out there. 🙂

Ensure to squeeze out as much as you can from the OOTB product, Coveo Cloud offers Machine learning and AI that could help users find relevant results.  So, embrace it and try to make it work to your architecture and timing.   In our case, we thought query suggestions are very important.  But, what to do when there is not enough data available on Coveo Analytics that would get back ML query suggestions.  Ensure you always have a back up plan!  We turned on result suggestions with Omnibox component as a back up.  Although, be very careful and diligent to drop this off as these queries are accounted towards the quota you signed up for with Coveo.

A parallel note on ML/Query Suggestions and reminder to ensure to change the tuning parameters on your test sandbox to test your ML query suggestions.  If you leave them to default, it might or not bring up query suggestions.   If you do not know where to find them, go to your Coveo Administration console either via sitecore or direct link if you have one on you, then, click on Query Pipelines under Search section, pick a model you want to tune the settings on and you will see the screen below

trainingset

I also was curious to see and test the ML query suggestions, so, I followed the instructions noted here and could quickly create a new report of my own way to track if there are any ML query suggestions available on my model.

https://onlinehelp.coveo.com/en/cloud/reviewing_suggested_queries_by_coveo_machine_learning.htm

Our Architecture was subtly different as it uses older/legacy Sitecore version to push all the data on to Cloud index using Push API.  We had to ensure we are following all the good practices as much as we can to ensure Coveo can then perform and do it’s thing on relevancy.  Here is a good Q&A link and responses I got when I was eyeing and planning to ensure we are covered with this Architectural decisions we have in play.
https://answers.coveo.com/questions/14602/best-practices-when-using-push-api.html

Another little POC that I had to do on my side to ensure our Architecture decisions will not have any unknown risk on main requirements. One such requirement was to have Coveo Stand Alone search box to be available and working on older version of Sitecore site and it would then redirect to the new version of Sitecore search page that was built off of Coveo components and JS framework.  Initially, I had hiccups due to CORS issue as the domain was not matching, but, later all was cool when we had set up load balancer to swap between old and new sitecore versions.   Below is Q&A reference for this step as well, if you are curious
https://answers.coveo.com/questions/14985/can-we-have-a-coveo-component-html-on-a-site-while.html

Next up, I will add my notes around how we built the components and used underscore and any other caveats we encountered during the same.

That is all for now folks, if you need more information on this subtly different architecture we have in play, feel free to drop in a comment.   Have a great weekend! You all deserve it. 🙂

Coveo Cloud Learnings – Part 1

Coveo_Cloud

I am super excited to share my experiences with you as I rolled up my sleeve to play with super cool search tool out there, Coveo Cloud!

Before I got this chance to work intimately with this platform, I did hear a lot and read a lot.  Was wondering and anticipating, when will I get to actually do hands on and I really wished to do that before I head out to Coveo Impact at SanFrancisco this year. Between, crazy excited to hear all the awesome new things and also geared up to participate in their Hackathon event as well.  Know more about their event here below

http://impact.coveo.com/

Now, I plan to write up my experiences with Coveo cloud first hand, the project is near completion on my end and I think this is the perfect time to reflect on all the set of challenges we had while pulling off a simple yet complex due to Architecture decisions involved on the project.

First things first, when you are about to start implementation on Coveo for Sitecore platform, decide on your version and framework you plan to use.  This goes long way to ensure you picked the correct version that supports all your other related third party components and ensure it is indeed a right step towards desired search experience.

On this project, we chose December 2017 version matching the Sitecore version we are using on this instance.  My first comment on getting Coveo for Sitecore up and running on my local and other environments is “Piece of Cake”.  Compared to challenges, hiccups I and my fellow team members had with on premise version of Coveo, this was a total opposite.  It took me less than an hour as opposed two full days(give or take) with on-premise version.  It was an awesome feeling to see the green quite quickly this time.

While you are at this step in your project, also, decide which version of JS framework would you like to use.  I would vote for Hive as it is new, more robust and modular, but, it highly depends on project of course.   You can see compatibility and more decision factors here on their documentation.

https://developers.coveo.com/display/public/SitecoreV4/What%27s+New+In+Coveo+for+Sitecore+4

While I was doing the steps or while trying to understand the new platform, I tried comparing and contrasting to the knowledge I had working with their on-premise version.  It did help me a lot actually trying to figure – “How is this different from before?”

Some helpful notes on Installation and Set up with Cloud.   Do note that your sitecore indexes, both, master and web would be now on Cloud and so are your logs, content browser and other cool things you were used to pulling up from port 8081, it should now all be located on Coveo Cloud Console. Also, understand that some features are now abstracted out, like you can not turn off and on the live monitoring on indexes for instance.  One important thing to realize is all your index rebuilds are queued in some fashion which you may not have control over, so, talk to your Coveo consultant or drop in a support ticket if you encounter some delays more than usual on your rebuilds.

On our end, we always ensure to use cloud sandbox(trial) for all our lower environments.  Note that there could be some limit on number of indexes on Sandbox, so, check with your Coveo rep when in question.

One subtle catch I would like to mention is – after installation of Coveo for Sitecore and hooking up proper Coveo Sandbox configuration and a full site publish, I did see the web index on the cloud from Sitecore perspective, but, note that master did need a manual rebuild by going in to your Indexing Manager on Sitecore Control Panel.

If you got time on you, explore the Coveo Cloud Administration Console, it has different and clearly named sections that should give you fair idea on which is what, but, it is definitely worth going over this as you drill deep in to Cloud Implementation.

Also, note that with Cloud you can build sample search pages on the fly, it is a cool feature to test some of the fields you have on your index or could be a custom build external index that you would like to target, but, if your implementation calls for some thing more complex, I would recommend to house your search pages within your sitecore instance by customizing the components and adding them to your presentation plus creating the templates.

So, you installed Coveo For Sitecore cloud version, got all green in diagnostics, sitecore indexes in check and could see your items and indexed data on cloud console content browser.  Did I hear that right? That is it, we can now jump right ahead and do some cool stuff that is made possible by the platform.

My next blog will focus on more challenges, gotchas and learning we had during this wave of time.   Also, will expound on choices we made at each step as well.

References/Helpful Resources for Coveo For Sitecore Cloud 

Installation guide:
https://developers.coveo.com/display/public/SitecoreV4/Installing+Coveo+for+Sitecore

Architecture and Beyond
https://developers.coveo.com/display/public/SitecoreV4/Understanding+the+Architecture+of+Coveo+for+Sitecore

Framework Choice

https://developers.coveo.com/display/public/SitecoreV4/What%27s+New+In+Coveo+for+Sitecore+4

Coveo Impact

http://impact.coveo.com/

Versions

https://developers.coveo.com/display/public/SitecoreV4/Downloads

A Battle – Coveo Search Framework | Coveo Search API

I am going to give it away to you all in who is the winner. 🙂

In reality, I think there is no battle when there is a clear winner and your vision to pursue should always be to use Coveo for Sitecore platform.  When the world turns up side down, you hit the wall like 100 times and when Coveo team also gives up only then you would pick the other option to build ground up.

Folks who love to code to solve problems or passionate to take full control in to their own hands in terms of business logic implementation have to remember and think about why did the executives spent money and time investing in Coveo For Sitecore.  Now, with the cloud version, their biggest selling point is of no suspense, heavy contexual marketing and machine learning are sure a huge cherry on top to their easy to integrate search experience.  Between, if you have installed Coveo for Sitecore on-premise and then also had experience with Coveo For Sitecore cloud, you will have to agree with me.  It took minute slice of earlier to set up cloud platform on a Sitecore instance.

Recently, after we did a thorough comparison between these two options for one of our clients, Coveo team released their best practices, I included the link here.  If you have not already, please check this out, it is very useful.  I definitely learned and shared a thing or two from here with my teams.  Now, this document just solidified what we pitched and I could not be more happier. I mean getting a backing from Technical Architects from Coveo on what we thought was correct approach.  Nice feeling you all!

Coveo Best Practices Document:  https://developers.coveo.com/display/public/SitecoreV4/Coveo+for+Sitecore+Project+Guide

Hint:  Look at Page Number 52 – Section Developing Against the Coveo Search API directly

I would like to share pros/cons of these approaches for any one who is trying to convince their client to not lean towards re-building something they don’t have to. 🙂

To keep this to the point, I will list what you will miss if you go with using Coveo Search API instead of Coveo for Sitecore framework.

Disclaimer:  Got to Hurt…Ouch!!!

  1. You will forgo ability to be able to add in Coveo Custom Components, they are becoming more and more powerful especially if you have Enterprise and above license where you hardly would need to write any JS, just use properties as much as you can to pass in those Filtering and other settings.
  2. Incremental refresh of Indexes – Depending on how huge your solution is, this will hurt you more. 😉 Coveo when integrated with your sitecore deeply you will notice that it taps on to most important pipelines to ensure it keeps your master and web indexes in sync using some clever strategies.  That means it will not rebuild the whole indexes until you request it to do so, saving lot of time and being efficient.  Web sources and other type of indexes you might create might not have this feature.
  3. Machine Learning/Coveo Analytics and any thing beyond.  Now, let me re-iterate the obvious, the world is moving towards AI for better or for worse and this might be one the biggest reasons why Coveo was a big win and hence the decision to go forward with the product.  Coveo Analytics are collected through one of their component that when added to search interface will push all the goodness ML would need to then use awesome Coveo ML features such as query suggestions and ART for instance.  You will miss out on this if you do not install the framework.  Now, I do see some API’s with which you can get usage analytics and either do a read or write to Coveo Analytics using the same, but, why go through this process when you can simply add a component that has been built and tested by Coveo.  If you are curious –

https://usageanalytics.coveo.com/docs/write/

https://usageanalytics.coveo.com/docs/read/

There could be more?  you think you know some? Leave a comment.

Now, remember all this losses while making a decision, but, also do understand that in some really complicated architectures where there seem to be no way that we can seamlessly integrate and use full power of Coveo platform then Coveo Search API in combination of a lot of custom code might be a way.  But, before you go that route I urge you talk to every one you think might know a different, better or easier way to fully juice and extract the goodness of the platform.  At the end of the project, we definitely do not want regret on our plate on this type of decisions.

Now go out there and make some tough decisions. 🙂