Upgrade form files to modern UI


This guide provides advice on converting Classic UI templates (.form files) to Modern UI Freemarker templates (.ftl files).

Classic UI was available in Funnleback 14.2 and earlier. The Modern UI was introduced in Funnelback v11.0.

Upgrade script

Funnelback ships with an script that converts Classic UI .form files into Modern UI .ftl files. This is run automatically if you upgrade Funnelback. After the script runs there are some manual steps that need to applied to the converted template.

This script can also be run manually.

Running the script manually

$ $SEARCH_HOME/bin/convert-form-file.pl  </path/to/file.form> </path/to/newfile.ftl> [-v or -vv]

After running the conversion the converted .ftl file will probably require further rectification work.

Fixing the converted template file

General technique is to search for <s: in the .ftl file. This will uncover things that have not been converted.

Commonly used Nickscript tags that require manual conversion

Classic UI compare <s:Compare>

These can usually be converted directly to an <#if> tag

You will need to ensure that the <#if> tag doesn’t have variables like <#if ${s.result.liveUrl} == "www.funnelback.com"> (this should be <#if s.result.liveUrl == "www.funnelback.com">)


<tr><th>Classic UI</th><th>Modern UI</th>
<tr><td>&lt;s:Compare var == "val"&gt;</td><td>&lt;#if var == "val"&gt;</td></tr>
<tr><td>&lt;s:Compare var != "val"&gt;</td><td>&lt;#if var != "val"&gt;</td></tr>
<tr><td>&lt;s:Compare var =~ regexp"&gt;</td><td>&lt;#if var?matches("regexp")&gt;</td></tr>
<tr><td>&lt;s:Compare var !~ regexp"&gt;</td><td>&lt;#if ! var?matches("regexp")&gt;</td></tr>

Classic UI include <s:IncludeFile>

<tr><th>Classic UI</th><th>Modern UI</th>
<tr><td>&lt;s:IncludeFile>/path&lt;/s:IncludeFile&gt;</td><td>&lt;#Include "path"&gt;</td></tr>

Note: path is relative to $SEARCH_HOME/conf/<COLLECTION-ID>/<PROFILE-ID>


<#include "../collection.cfg">

Classic UI eval perl <s:EvalPerl>

This was used to implement some custom logic in Classic UI templates.

This will need to be replaced with Freemarker code that replicates the logic.

The following Freemarker built-in functions may be equivalent to what the custom EvalPerl codeblock does:


<tr><th>Classic UI</th><th>Modern UI</th>
<tr><td>&lt;s:IncludeUrl args/&gt;</td><td>&lt;@fb.IncludeUrl args/&gt; (v12+)<br/>
&lt;@IncludeUrl args/&gt; (v11)</td></tr>


<@IncludeUrl url="http://www.example.com/template.html" expiry=86400 start="<div id=\"global-header\">" end="</div> <!-- /#global-header -->" convertRelative=true />
<#--v12: IncludeUrl is now part of the fb namespace-->
<@fb.IncludeUrl url="http://www.example.com/template.html" expiry=86400 start="<div id=\"global-header\">" end="</div> <!-- /#global-header -->" convertRelative=true />

The IncludeUrl tag was undocumented in v11 but is since v12: http://docs.funnelback.com/help-ftl/funnelback.ftl.html#IncludeUrl


  • (?ms) is set on the backend so you don’t need to include these flags in the start and end parameters

  • for the expiry value and convertRelative you need to omit any quotes or you get a FreeMarker error because it expects a number and not a string: ie. expiry=86400 and not expiry="86400"

  • start/end parameter Regex encoding:

    • You need to encode any double quotes ie. start="<div class=\"somthing\">"

    • Valid escape sequences don’t need to be escaped: \t, \n, \r …​

    • Backslashes need to be escaped: \\ will result in a single slash \

    • Brackets should be escaped, otherwise they’ll be considered matching groups: start="\\(test\\)"

    • You don’t need to encode a forward slash.

  • Keep in mind that the regex patterns use java regex so you sometimes need lots of additional backslashes. See: http://www.regular-expressions.info/java.html for further info.

  • In v11 you can’t have more than one include from the same source URL, eg. a header and footer from the same source page - if you attempt to do this you will get the same code chunk repeated for each include call regardless of the start and end values. To workaround this add a parameter to the URL so that each URL is unique. E.g. if you are importing http://site/home.html call it with a parameter url="http://site/home.html?include=1", url="http://site/home.html?include=2" etc.

Result transforms

Result Transforms are not supported in the Modern UI but the functionality can be implemented using a post-process hook script.

Classic UI: result_transform collection.cfg parameter:

result_transform=$$result{'title'} =~ s/ - Example Site Suffix//g;

Modern UI: hook_post-process.groovy

if ( transaction.response != null
  && transaction.response.resultPacket != null) {
  transaction.response.resultPacket.results.each() {
    // Transform each result's title
    it.title= (it.title =~ / - Example Site Suffix/).replaceAll("")

CGI transforms

CGI Transforms should be re-implemented as a hook_pre-proceess.groovy script.

Faceted navigation transforms

Faceted navigation transforms are not supported in the modern UI.

  • In Funnelback 15.10 and earlier complex faceted navigation requirements are most likely covered by the faceted navigation GitHub project.

  • In Funnelback 15.12 and newer faceted navigation has been completely rewritten.

The FeedbackLink plugin isn’t implemented in the modern UI. However, in Funnelback 14.2 and earlier it can be easily called from the modern UI. The functionality is not available in v15.0+.