Answer Generators

Overview

Answer Generators use Combined Content Recognition Results to produce links, inline content, and associated metadata that comprise the answer results presented to the user. Answer Generators are usually activated by Triggers, but can also be activated by activation codes and/or activation keywords.

To get started creating an Answer Generator quickly, check out the guides.

What they do

Input

The following information is available to Answer Generators:

Name Example Value Description
q 92126 The user's answer query, with activation codes and options (like --debug) removed, truncated to 80 characters, and trimmed of leading and trailing whitespace
recognitionResults
{
  "com.solveforall.recognition.Number" : [
    {
      "matchedText" : "92126",
      "relevance" : 1.0,
      "number" : "92126"
    }
  ],
  "com.solveforall.recognition.USAddress" : [
    {
      "matchedText" : "San Diego",
      "relevance" : 1.0,
      "city" : "San Diego"
    },
    {
      "matchedText" : "92126",
      "relevance" : 1.0,
      "zipCode" : "92126"
    }
  ]
}
See Combined Content Recognition Results
context
{
  "user" : {
    ...
  },
  "pageUri" : "http://blah.com",
  "location" : {
    ...
  }, ...
}
See Query Context

Output

Answer Generators output a list of answer results. Each answer result may either be a link answer result, which contains a URI, or an inline answer result, which contains HTML 5 content that can be directly shown to the user.

Both types of answer results have the following properties:

Name Example Value Description
label Map It! The label to show with the answer result (becomes the tab label in a browser extension).
iconUrl https://mapit.com/favicon.ico The URL of the icon to show with the answer result (becomes the tab icon in a browser extension).
tooltip Map It! Zip Code Details Extra information about the answer result (becomes tooltip of a Quick link, or the tab tooltip in a browser extension).
summaryHtml View a map with <b>MapIt</b>! Optional HTML content describing the link. Will be sanitized so only <a>, <b>, <blockquote>, <br>, <cite>, <code>, <dd>, <dl>, <dt>, <em>, <i>, <li>, <ol>, <p>, <pre>, <q>, <small>, <strike>, <strong>, <sub>, <sup>, <u>, and <ul> tags are allowed. If the content is blank and the answer is a link answer, the answer will be eligible to be shown as a Quick Link at the top of the results page.
relevance 1.0 A number between 0.0 and 1.0 that indicates how strong of a match this result is, relative to other results. If left blank, the Answer Generator uses the recognition level of the recognition result associated with a found recognition key, or 0.0 if no associated recognition result exists. Use this to order the result relative to other results, to give the user results from most helpful first.
uri https://mapit.com/?zip_code=92126 The URI that contains information about the answer query. Might not be publicly available to all users, but should be available to the searching user. This property is optional for inline answers.
categories [{"value": "video", "weight": 1}, ...] A list of weighted categories for the result. Weights should be between 0.0 and 1.0. For future use in filtering results.
tags [{"value": "laser", "weight": 0.6}, ...] A list of weighted tag words for the result. Weights should be between 0.0 and 1.0. For future use in filtering results.
minWidth 410 The minimum width, in pixels, that should be used to display the linked page (if embeddable) or the inline content.
preferredWidth 500 The preferred width, in pixels, that should be used to display the linked page (if embeddable) or the inline content. May not be honored by clients, but a best effort will be made.
minHeight 300 The minimum height, in pixels, that should be used to display the linked page (if embeddable) or the inline content.
preferredHeight 420 The preferred height, in pixels, that should be used to display the linked page (if embeddable) or the inline content. May not be honored by clients, but a best effort will be made.
eligibleAsBestAnswer true

If true and the answer is the most relevant answer, and either inline or embeddable, it will be placed at the top of the answers page and given the full width of the page. Otherwise, the answer will be placed in the inline answer sidebar on large screen devices.

depth 0

The number of links followed / service APIs called to retrieve the result.

Additionally, link answer results have the following properties:

Name Example Value Description
embeddable false True if the URI can be embedded in a sandboxed iframe. Solve for All gives the user the option of previewing each embeddable URI in a container below the corresponding link. However, some sites send the X-Frame-Options header which prevents them from being embedded in an iframe, and some sites do not work when sandboxed. (iframes are sandboxed with allow-forms allow-scripts allow-same-origin). Setting embeddable to false means that Solve for All won't try to display the URI in an iframe. This property does not affect browser extensions that use Solve for All.
shouldEmbed false True if the URI should be initially shown in an iframe, without the user having to open it manually.

Finally, inline answer results have the following properties:

Name Example Value Description
content
<html><body>
  This is HTML!
</body></html>
A string containing HTML used as the inline answer. Must be an entire HTML document (with the <html> tag). Only the contents of the <body> will be kept.
serverSideSanitized true

If true, the inline content will be sanitized on the server side before sending it to the client. See Server-Side Sanitization for more details.

If false, the inline content will be loaded into a sandboxed iframe on the client side. This means you can run scripts which may use any browser API, including XMLHttpRequest.

Internal Use

The URIs in link answer results don't have to be publicly available, but they should be available to the users of the Answer Generator that produces them. So Answer Generators are suitable for use inside a company's intranet. You can use them to view employee profiles in an employee profile site, when a name is selected, for example.

Inline Answers

There are a number limitations, gotchas, and tricks for generating inline answers. For more details, see the inline answer guide.

Common Answer Generator Properties

In addition to the common plugin properties, all Answer Generators have the following additional properties:

Name Example Value Description
Provider GitHub The Content Provider that this Answer Generator belongs to
Required Recognizers United States Address The set of Content Recognizers that this Answer Generator requires to be executed, before executing the Answer Generator. The Content Recognizers may output recognition results that the Answer Generator needs.
Semantic Data Collections Companies The set of Semantic Data Collections that this Answer Generator requires to be searched, before executing the Answer Generator. The Semantic Data Collections may contain documents that are transformed into recognition results that the Answer Generator needs.
Categories com.solveforall.category.Location, com.solveforall.category.Travel The set of Plugin Categories that this Answer Generator falls under
Icon URL https://mapit.com/favicon.ico Used to set the iconUrl property of output answer results
Removed Query Terms skype,call A comma-separated list of lower-cased terms to be removed from the answer query before being passed to the Answer Generator
Removed Query Term Boosts 1.0,0.2 A comma-separated list of boosts for each of the corresponding removed query terms. If the corresponding query term is found in the query, the boost will be added to the output relevance. If a query term is found in a query, and it has no corresponding boost, the previously specified boost before its position will be used. If multiple query terms are found, the matching boosts are added together to yield the final boost. Each boost should be 1.0 or less. You can specify negative boosts to ensure results from an Answer Generator won't be included in the answers page. If no boosts are specified, the relevance is not changed even if removed query terms are found.
Default Activation Code ghc A code that can be used to force the Answer Generator to execute. The code must be between 1 and 10 alphanumeric characters. Any user can type ? followed by the code to activate the Answer Generator, even if it hasn't been added to his preferences. Activation codes 5 characters or less require approval from the Solve for All administrator. The code must not conflict with an existing activation code, so hurry up and claim yours before it gets taken!
Requires Recognition Results false A true value indicates that the Answer Generator needs to read the combined recognition results to generate its output. If false, and this Answer Generator is activated by the Any Trigger, an activation code, activation keywords, or a --g option, the Answer Generator will executed at the same time as content recognition, instead of waiting until the Triggers are run. This can hide the latency of making network requests or performing computations, resulting in a faster answer response.

Content Providers

Answer Generators may optionally be associated with a single Content Provider. A Content Provider represents a website or domain that is a source of information for answers. Content Providers also have the common plugin properties.

For example, Google is a Content Provider, which contains the YouTube and Google Videos Answer Generators.

Plugin Categories

Plugin Categories group together Engines and Answer Generators that provide answers related to a specific topic or area. An Answer Generator may belong to one or more Categories, and Plugin Categories may contain one or more Answer Generators. An example Plugin Category is Location-Based, which contains Answer Generators that utilize the user's location. Categories also have the common plugin properties.

Kinds of Answer Generators

Developers can create Answer Generators implemented in one of three ways:

Either kind of Answer Generator can be created on the Answer Generator creation form.

URI Template Answer Generators

URI Template Answer Generators produce link answer results by looking in the Combined Content Recognition Results for a list of recognition keys. For each recognition key of the Combined Content Recognition Results that appears in the list of recognition keys, the list of recognition results is transformed into a list of link answer results. All created answer results are then added to the answer result list.

In addition to the common Answer Generator properties, URI Template Answer Generators have the following properties:

Name Example Value Description
Recognition Keys com.solveforall.recognition.UsAddress The comma-separated recognition keys to look for. Can be blank if no recognition key is necessary.
Max Results 1 The maximum number of results to output
URI Prefix https://www.mapit.com/?q= The beginning of the output URI that is taken verbatim (no substitutions)
URI Middle ${q}&zip=${zipCode} &lang=${c.locale.language?upper_case} The middle part of the output URI that has placeholder substitution applied to it
URI Suffix &results=100 The end of the output URI that is taken verbatim (no substitutions)
Deprecated Substitutions
[
  { "foo_bar" : "baz" },
  { "-" : "_" , " " : "_" }
]
A list of dictionaries mapping regular expressions to their literal replacements, in JSON format. Each regular expression must conform to the supported syntax of RE2. Substitutions are done in order from the first list element to the last. Back-references in the replacement are not supported.
Label Map It! Used to set the label property of output answer results. May also contain placeholders.
Tooltip View zip codes with Map It! Used to set the tooltip property of output answer results. May also contain placeholders.
Relevance 1.0 Used to set the relevance property of output answer results
Embeddable false Used to set the embeddable property of output answer results
Should Embed false Used to set the shouldEmbed property of output answer results
Min Width 400 Used to set the minWidth property of output answer results
Preferred Width 415 Used to set the preferredWidth property of output answer results
Min Height 310 Used to set the minHeight property of output answer results
Preferred Height 320 Used to set the preferredHeight property of output answer results
Summary HTML View with <b>Map It!</b>! Used to set the summaryHtml property of output answer results

Each answer result has the label, iconUrl, tooltip, relevance, embeddable, and summaryHtml properties set to constant values that are properties of the URI Template Answer Generator. The URI of each answer result consists of three parts:

  • URI Prefix: A prefix that never changes
  • URI Middle: The middle part which is built dynamically based on the answer query, the Combined Content Recognition Results, and the context
  • URI Suffix: An optional suffix that never changes

Placeholder Substitution

Placeholder substitution is used to transforms the uriMiddle property of a URI Template Answer Generator to the final middle part of the URI:

  1. Each occurrence of ${x} is resolved as follows:
    • If x is q, the original answer query will be used.
    • If x is a string like c.y, then the property value for y is looked up in the Query Context and converted to a string. If the property is not present, the empty string will result.
    • Otherwise, then the property value for x is looked up in the current recognition result and converted to a string. If the property is not present, defaults will be used (see step 3).
  2. Transformations, specified like ${x?transform1?transform2} are applied on the resolved value, from left to right.
  3. If resolution of the variable in step 1 failed, default values, specified as a quoted Java string, like ${x!"3"}, or additional variables with transformations are used instead until resolution succeeds. If no default value is given, the empty string will be used, may results in a parameter being removed from the query part of a URI. If ${x!!} is used, and x cannot be resolved, no answer result will be generated. It is possible to combine transforms and default values like this: ${x?raw!q?lower_case!"n"}.
  4. Deprecated For each substitution dictionary in the list of substitutions, substitutions are applied by replacing all the occurrences of each key of the dictionary with the corresponding value. Substitutions are applied in the order that the dictionaries appear in the list. In the future, the step will be performed with transformations.
  5. Each resolved result is URL encoded, and the placeholders in uriMiddle are replaced with their respective resolved results.
  6. Empty parameters are removed, so if the middle is ${q}&filter=${c.settings.filter} and c.settings.filter is missing or the empty string, the output URI won't contain the filter parameter. This is useful for when the parameter codes from user-defined settings which may be not be set by the user yet.

The supported transforms are:

Name Behavior
raw Prevents the resolved value from being URL encoded or HTML encoded. Useful for / characters.
upper_case Converts the resolved value to upper case letters
lower_case Converts the resolved value to lower case letters
trim Trims whitespace from the beginning and end of the resolved value
capitalize Capitalizes the resolved value
delete_whitespace Removes all whitespace from the resolved value

Placeholder substitution is also used on the label, tooltip, and summaryHtml properties as well, except that the values won't have URL encoding applied to each placeholder. The summaryHtml property will apply HTML encoding to each placeholder, unless the ?raw transform is used.

Given the answer query of it's 92126, the combined recognition result of

{
  "com.solveforall.recognition.UsAddress" : [
    {
      "matchedText" : "92126",
      "relevance" : 0.80,
      "zipCode" : "92126",
      ...
    }
  ]
}
and a Query Context of
{
  "locale" : {
    "fullName" : "en_US",
    "language" : "en",
    ...
  },
  ...
}
  

a URI Template Answer Generator configured as above would output

[
  {
    "label" : "Map It!",
    "iconUrl" : "https://www.mapit.com/favicon.ico",
    "tooltip" : "View zip codes with Map It!",
    "url" : "https://www.mapit.com/?q=it%27s_92126&zip=92126&lang=EN&results=100",
    "relevance" : 1.0,
    "embeddable" : true,
    "shouldEmbed" : true
  }
]

URI Template Answer Generators are by far the most common type of Answer Generators, since they require no programming.

Content Template Answer Generators

Content Template Answer Generators produce inline answer results by looking in the Combined Content Recognition Results for a list of recognition keys. For each recognition key of the Combined Content Recognition Results that appears in the list of recognition keys specified in the answer generator, an inline answer result is created by processing an EJS template. All created answer results then are added to the answer result list. The advantage of using a template is that you can avoid manually writing a bunch of string concatenation code in Javascript.

In addition to the common Answer Generator properties, Content Template Answer Generators have the following properties:

Name Example Value Description
Recognition Keys com.solveforall.recognition.UsAddress The comma-separated recognition keys to look for. Can be blank if no recognition key is necessary.
Max Results 1 The maximum number of results to output
Label Map It! Used to set the label property of output answer results. May also contain placeholders.
Tooltip View zip codes with Map It! Used to set the tooltip property of output answer results. May also contain placeholders.
Relevance 1.0 Used to set the relevance property of output answer results
Min Width 400 Used to set the minWidth property of output answer results
Preferred Width 415 Used to set the preferredWidth property of output answer results
Min Height 310 Used to set the minHeight property of output answer results
Preferred Height 320 Used to set the preferredHeight property of output answer results
Server Side Sanitized true Used to set the serverSideSanitized property of output answer results
Content Template (File) A text file containing an EJS template for a full HTML5 document

Content Template Answer Generators produce answer results that have the label, iconUrl, tooltip, relevance, and serverSideSanitized properties set the corresponding properties of the Content Template Answer Generator that produced them.

The content template has access to the q, recognitionResults, and context input variables in the top-level scope.

Here is an example content template that converts numbers to hexadecimal strings:

<!doctype html>
<html>
  <head>
    <title>Hexadecimal Converter</title>
  </head>
  <body>
    <%
    let number = null;
    const numberResult = recognitionResults['com.solveforall.recognition.Number'];

    if (numberResult) {
      number = Math.floor(numberResult[0].doubleValue);
    } else {
      number = parseInt(q, 10);
    }

    const hexString = number.toString(16);
    %>
    <pre><%= number %><sub>10</sub> == 0x<%= hexString %></pre>
  </body>
</html>

Note Unlike EJS 1.0, filters (like x | upper) are not available in EJS templates processed by Solve for All. This applies to User Preferences Pages and Recognition Key documentation as well.

Meta Overrides

Sometimes, as a result of the computations done in a Javascript section, you may wish to set or override properties of the answer result produced by a Content Template Answer Generator. For example, a Content Template Answer Generator normally produces answers without the uri property set, but you may want to set it so that the inline answer has a link as well as inline content. To enable this functionality, Solve for All parses the HTML produced by Content Template Answer Generators and looks for meta tags to set or override properties in the corresponding answer result. The meta tags should look like this:

<%
  const uri = 'http://example.com/' + encodeURIComponent(q);
  const embeddable = true;
  ...
%>
<!doctype html>
<html>
  <head>
    <meta name="com.solveforall.meta.answer.uri"
          content="<%= uri %>" />
    <meta name="com.solveforall.meta.answer.embeddable"
          content="<%= embeddable %>" />
    ...
  </head>
  <body>
    ...
  </body>
</html>

Names for meta overrides start with com.solveforall.meta.answer., followed by:

Suffix Type
label String
uri String
relevance Float
tooltip String
icon_url String
summary_html String
categories Array, e.g. [{"value": "video", "weight: 1}, ...]
tags Array, e.g. [{"value": "cat", "weight: 0.8}, ...]
embeddable Boolean (true or false)
should_embed Boolean (true or false)
min_width Integer
preferred_width Integer
min_height Integer
preferred_height Integer
eligible_as_best_answer Boolean (true or false)
depth Integer

If a property is found in the meta overrides, it will take precedence over the corresponding property of the Content Template Answer Generator.

Pro Tip  The only good EJS editor that we know of is Atom with the language-ejs package.

Pro Tip  Instead of uploading EJS templates multiple times to Solve for All, and having them rejected due to syntax errors or fail during runtime, you can use the test harness contained in the example plugins repository to test your templates. See the test for the HTML Entity Answer Generator for an example of a unit test of an EJS template.

Publishing Content Template Answer Generators

Once you have written a content template, follow these steps to publish your Content Template Answer Generator:

Javascript Answer Generators

You can also create Answer Generators by writing Javascript. See Javascript execution for information about the execution environment.

To create an Javascript Answer Generator, create a file, say answer_generator.js, that contains the following function:

function generateResults(q, recognitionResults, context) {
  return [
    {
      "label" : "Yahoo! Maps",
      "uri" : "http://maps.yahoo.com/?where=" + encodeURIComponent(q),
      "relevance" : 0.5,
      "embeddable" : false,
      ...
    },
    ...
  ];
}

in the top level scope, where recognitionResults is an Object representing Combined Content Recognition Results and context is an Object representing the Query Context. Your implementation of generateResults() should return an array of Objects, which correspond to answer results. You can return either link answer results (with the uri property set and without the content property set) or inline answer results (with the content property set). If you omit the embeddable property, Solve for All will make a guess based on a static set of domains known to be embeddable. (Let us know if you have a domain you wish to be added to the set of embeddable domains.)

Pro Tip  To output an inline answer result, it may be useful to process a template. To define a template, use an ES6 interpreted string, which may span multiple lines. Then use EJS to render the template:

const template = `
<!doctype html>
<html>
  <body>
    <p>
      Search results for <%= q %>:
      <% _(results).each(r => { %>
         <a href="<%= r.url >"><%= r.title ></a><br>
      <% }); %>
    </p>
  </body>
</html>`;

// Ensure _ (Underscore.js) is available in template
// Use an ES6 object literal to avoid repeating names
const model = { _, q, results };
const content = require('ejs').render(template, model);

See the source code of the Zillow Answer Generator for an example.

Some examples of Javascript Answer Generators can be found in the solveforall-example-plugins repository in GitHub.

Publishing Javascript Answer Generators

Once you have written the Answer Generator script, follow these steps to publish your Javascript Answer Generator:

Next Steps

Check out more details on inline answers.

Unless the user includes an activation code or activation keyword in the answer query, an Answer Generator is only activated when a Trigger associated with it activates. The association is embodied in an Answer Generator - Trigger Association, which you should create if you want to activate your Answer Generator by a Trigger.

To get started creating an Answer Generator quickly, check out the guides.