Instant Answer Display Reference
The Instant Answer framework gives you many options for displaying your results in the DuckDuckGo AnswerBar. Below is a detailed reference of the properties and usage of each.
Each Instant Answer has its own ways of declaring these options. We strongly recommend starting with the appropriate usage section, depending on your Instant Answer type:
These sections explain how to display each Instant Answer, as well as code samples involving the options in this reference.
Display Properties
Each Instant Answer is added to the AnswerBar by passing a set of properties to the Instant Answer Framework.
The following properties are required:
- id - A unique identifier for your Spice. The
id
should match the name of your callback function - name - The name that will be used for your Spice's AnswerBar tab
- data - The object containing the data to be used by your templates
- meta - Used to define elements of the MetaBar including the "More at" link
- templates - Used to specify the template group and all other templates that are being used
The following properties are optional:
- normalize - This allows you to normalize the
data
before it is passed on to the template - relevancy - Used to ensure the relevancy of your Spice's result
- sort_fields
- view - This allows you to explicitly specify the view class used for displaying the Instant Answer
- model - This allows you to use one of our predefined data models that include domain specific helpers/normalization/formatting.
- You may also optionally handle several of the AnswerBar's frontend events.
id
string [required]
A unique identifier for your Instant Answer.
Notes for Spice Instant Answers
The id
should match the name of your callback function. For example, if your callback function is named ddg_spice_name
, your id
should be spice_name
.
name
string [required]
The name that will be used in the tab above the Instant Answer, in the AnswerBar.
Tab names should ideally be one word nouns (Images, Videos, Products, Audio, Answer, News, etc.) that describe the type of content being shown.
We will not accept brand names for tabs. Instead, it's best to use the general topic name. For example, 'videos' for YouTube, 'gaming' for Twitch, 'products' for Amazon, and so on.
If none of the topics below apply to your results, or need help, we recommend choosing "Answer" for the time being, and contacting us to brainstorm.
To get an idea for choosing a good name, here are some examples:
Spice IA | `name` |
---|---|
GitHub | 'Software' |
Last.fm | 'Music' |
HackerNews | 'News' |
'Social' | |
Amazon | 'Products' |
Ideally your Instant Answer name
should be one of the existing topics:
- Answer
- Apps
- Audio
- Computing
- Cryptography
- Currency
- Dictionary
- Domain
- Entertainment
- Finance
- Food & drink
- Games
- Geek
- Geography
- Health
- Images
- Jobs
- Literature
- Local
- Math
- Movies
- Music
- News
- Politics
- Productivity
- Products
- Programming
- Recipes
- Reference
- Science
- Social
- Software
- Special interest
- Sports
- Statistics
- Sysadmin
- Tools
- Travel
- Tv
- Videos
- Weather
- Web design
- Words & games
data
object [required]
The object containing the data to be used by your templates. In most cases, it is best to pass along api_result
to data
, so that all of your API response is accessible to your templates.
meta
object [required]
The following options are used to define elements of the MetaBar including the "More at" link.
The following are all properties of the meta: {}
object.
sourceName
string [required for Spice, optional for Goodie]The name of the source as it should be shown in the "More at" link. For example, in "More at Quixey", "Quixey" is specified as
sourceName
.Notes for Goodie Instant Answers
While Goodies don't, by definition, have external data sources, you may still decide to specify
sourceName
andsourceUrl
(below). For example, the BPM to ms instant answer (search for "120 bpm to ms") specifies Wikipedia as the source, and links to an article that explains the calculation performed by the Goodie.For the best experience, if a relevant Wikipedia page, or authoritative explanation, exists for your Goodie, you should provide it as a
sourceName
andsourceUrl
.sourceUrl
url string [required for Spice, optional for Goodie]The URL to follow when the "More at" link is clicked. This value is the
href
attribute of the "More at" link. This can refer to the main page of the source, or better yet, the specific page relevant to the user's query.A secure https:// connection should be used whenever possible.
Examples
- In rand_word.js, the
sourceUrl
is a hardcoded address. - In is_it_up.js, the
sourceUrl
is dynamically generated to direct to a specific page relating to the search query.
- In rand_word.js, the
searchTerm
string [optional]Determines the modifier in the MetaBar's description: "Showing 15
itemType
forsearchTerm
".The
searchTerm
is used to describe theitemType
and it can be determined by removing any skip words from the original query.For example, searching "alternatives to emacs", will display the description "Showing 12 Alternatives for GNU Emacs" in the MetaBar. In this case, the phrase "GNU Emacs" is the
searchTerm
.If no
searchTerm
is specified, the description will simply read "Showing 12 Movies" or, if noitemType
specified, "Showing 12 Items".Examples
- In news.js,
searchTerm
is passed the search query after some basic cleanup. - In images.js,
searchTerm
is passed the original query as-is. - In alternative_to.js,
searchTerm
is passed a name provided by the API. - In songkick_geteventid.js,
searchTerm
is passed a city name.
- In news.js,
itemType
string [optional]Determines the noun in the MetaBar's description: "Showing 15
itemType
forsearchTerm
". In other words,itemType
is the type of item being shown (e.g., Videos, Images, Recipes).Searching for "alternatives to emacs", "Showing 12 Alternatives for GNU Emacs", the word "Alternatives" is the
itemType
.If no
itemType
is specified, the default itemType is 'Items'. For example, the MetaBar description will read "Showing 12 Items", or "Showing 12 Items for Electronics" when asearchTerm
is provided.Examples
- In news.js, the
itemType
is'News articles'
. - In alternative_to.js, the itemType is
'Alternatives'
.
- In news.js, the
primaryText
string [optional]If defined, this text will replace the MetaBar's "Showing n Items" text.
Example
- In parking.js, the
primaryText
is set to'Parking near'
plus the location.
- In parking.js, the
secondaryText
string [optional]This is an optional text label, displayed to the left of the "More at" link. For example, a weather forecast Instant Answer might use this to indicate the temperature unit, such as "Temperature in F°".
sourceLogo
url string [optional]If defined, the image provided will replace the
sourceName
with a logo. Generally this is not necessary; in rare cases, API providers require that a specific image be used to represent their brand.Example
From quixey.js:
meta:{ ... sourceLogo: { url: DDG.get_asset_path('quixey','quixey_logo.png'), width: '45', height: '12' } }
This is the result:
sourceIcon
boolean [optional]A boolean flag that determines if a favicon should be shown to the left of the "More at" link. The favicon is determined automatically by DuckDuckGo based on the
sourceUrl
.When a
sourceUrl
is given, this will default totrue
. It should only be set tofalse
when thesourceUrl
domain does not have a favicon.sourceIconUrl
url string [optional]If the
sourceUrl
domain has no favicon (or if a different favicon is preferred), you can explicitly set a url path for the favicon shown to the left of the "More at" link. This value, if set, will take precedence any favicons pulled from thesourceUrl
domain.snippetChars
integer [optional]For blocks of text that require truncation,
snippetChars
allows you to specify the maximum number of characters before truncation (to whole words with ellipses). This applies mainly todescription
elements in templates.This property is expected to be used in rare cases. Each template comes with its own optimal, default
snippetChars
value.pinIcon
string [optional]Specifies the class of the built-in icon to use as the map pin. If you are using the Places Template Group, which displays an interactive map, use this to specify which built-in icon you'd like used to mark locations.
This takes a CSS class name of the built-in icon to use. You can find the icons listed in the style guide. For example:
meta: { ... pinIcon: 'ddgsi-circle', pinIconSelected: 'ddgsi-star' }
pinIconSelected
string [optional]Same as
pinIcon
, but for selected pins. When focusing on a particular location, use this icon to highlight the corresponding pin on the map.
templates
object [required]
A templates: {}
property should be used to specify the template group, and/or other templates that are being used.
Template options
can also be provided to enable or disable features depending on the chosen template group.
More about how templates work can be found in the Template Overview.
*Note for Goodie Instant Answers: Several properties below allow you to specify a function datatype, in order to reference a custom handlebars template. However, if you intend to do this in a Goodie Perl file, you must pass the name as a string in order to work.*
group
string [required, unlessitem
anddetail
are specified]Setting the
group
property specifies a preset group of default templates and options (for example,item
,detail
,options
etc.). These presets can be customized and manually overridden. The template groups available are described in the Template Groups Overview.For example,
group: 'info'
will implicitly set:templates:{ item: 'basic_item', item_detail: 'basic_info_item_detail', detail: 'basic_info_detail' }
item
string (template name) or function (template reference) [required if nogroup
is specified]The template to be used for each item in a tile view.
Note: The
item
template is only used when your Instant Answer returns multiple items (like the recipe or BPM to ms Instant Answers). This means the object passed todata
is an array with more than one element.Generally, a string is provided to indicate the name of the built-in template to be used, e.g., "products_item"
In rare cases, where necessary, a function referencing a custom template can be passed. Passing a custom template is a measure of last resort due to maintenance difficulty. Learn more about picking templates; if you feel that no current templates fit your idea, please contact us at [email protected] and we'll happily help you find a solution.
item_mobile
string (template name) or function (template reference) [optional]An alternative
item
template to be used when displaying on smaller screens, such as mobile and hand-held devices.detail
string (template name) or function (template reference) [required if nogroup
is specified]The template to be used for the detail area. Find out more about when the
detail
template is displayed in the templates overviewIf your Instant Answer only returns a single item, a `detail` template is **required**. If your Instant Answer usually returns multiple items, the `detail` template is **optional**.
detail_mobile
string (template name) or function (template reference) [optional]An alternative
detail
template to be used when displaying on smaller screens, such as mobile and hand-held devices.item_detail
string (template name) or function (template reference) [optional]An alternative
detail
template to be used when a tile is clicked. Learn more about whenitem_detail
is used in the templates overview.options
object [optional]Allows you to explicitly disable or enable the available features of your template using boolean values or by specifying sub-templates to include.
For example, you might set the the
content
feature of thebasic_info_detail
template to a particular sub-template, and enable therowHighlight
feature.For example:
templates: { group: 'info', options: { content: 'record', rowHighlight: true } }
Available features will vary with each chosen template (see the templates reference for details on each template). For example, the
basic_info_detail
template doesn't have abrand
feature, so settingbrand: true
orbrand: false
will have no effect.It's important to note that there are implicit default options which apply in the absence of an
options
object or a templatesgroup
.moreText
string or object or array [optional]Display additional text or link content adjacent to the 'More at' link. Note that
moreText
is nested under theoptions
property.For text alone, pass a string:
templates: { ... options: { moreText: "Movie showtimes are shown in PST time zone" } }
To display a link, pass an object:
templates: { ... options: { moreText: { text: "See a 10-day surf forecast" href: "https://..." // Use SSL when possible } } }
To display multiple values (either text or links), pass an array:
templates: { ... options: { moreText: [ { text: "See a 10-day surf forecast" href: "https://..." // Use SSL when possible }, { text: "Global Swell Chart" href: "https://..." }, "Subject to local conditions" ] } }
Multiple values will be separated by a '|' and display as follows:
More at Surfline | See a 10-day surf forecast | Global Swell Chart | Subject to local conditions
variants
object [optional]If you'd like to modify a template's visual appearance to fit your needs, the Instant Answer framework offers preset options called Variants. Variants are passed as the
variants
property oftemplates
.Variants correspond to pre-determined css classes (or combinations of classes) from the DDG style guide that work particularly well in each context.
For more on the options and usage of
variants
, visit the templates reference.elClass
object [optional]When variants don't suffice in customizing your templates' appearance, you may directly specify classes from the DDG style guide through the
elClass
property oftemplates
. This feature is mainly used for specifying text size and color.These custom classes can be directly specified on the same template features available to Variants; the locations are identical. If you are specifying both
variants
andelClass
, both will be applied together.For more on the options and usage of
elClass
, visit the templates reference.
normalize
function [optional]
Specifying this optional function allows you to normalize each item in the data
object before it is used by the template. You can use this function to rename properties, add new properties, or modify values.
This function is applied both for single results or multiple results. When dealing with multiple items returned in the data
object, the normalize function iterates over each item. Each item is individually normalized and passed to its own instance of the item
template.
Notes for Goodie Instant Answers
Because Goodies have no external sources and run on the server, a normalize
function is not completely necessary to normalize data for templates. However, it is possible (and conceivable) to use a normalize
function in a Goodie Instant Answer.
Defining a normalize
function in a Goodie, must be done in the frontend part of the code, as JavaScript. For more information about Goodie JavaScript visit the Goodie Display section.
Usage
The function set for normalize
is expected to return an object with the properties to be rendered for each item.
The object returned by the normalize
function is combined with the original respective item from data
.
The normalize
function will extend the original data
item instead of replacing it. (This uses jQuery's $.extend()
method, shallow copy.) Each normalized item will contain its original properties unless they were explicitly overwritten in the normalize
function.
Use with Built-In Templates
Normalize can be particularly useful if you are using a built-in template (for example, basic_image_item
).
Built-in templates expect that certain properties will be present (such as title
and image
). The normalize
function allows you to provide those (or normalize their values if the property already existed in your data
).
For example, if you have a data
object that looks like this:
// original data object from API
{
heading: "My awesome title",
image: "http://website.com/image.png"
}
You will likely want to pass the heading
property as the title
for the basic_image_item template, so your normalize
function would need to look like this:
normalize: function(item){
return {
title: item.heading
};
}
This would result in your data
object looking like this once it gets passed along to the template:
// normalized data object
{
heading: "My awesome title",
image: "http://website.com/image.png",
title: "My awesome title"
}
Now, your object has all the required properties for the basic_image_item template and everything will be displayed as expected.
Important Note on Enabling Features
If you intend to use a template feature that is disabled by default or disabled by a template group defaults, that feature must be enabled in the options
to display.
Even if the property exists in the data
object, the template system will ignore it if the feature is disabled.
In this example:
normalize: function(item){
return {
// these won't work!
rating: item.customerRating,
brand: item.brandname
};
},
templates: {
group: 'products_simple'
}
The template will not display the rating
or brand
as they are disabled by default in the products_simple
group default options. Only once they are explicitly enabled in an options
object will they work:
normalize: function(item){
return {
// now they'll show, because they're enabled below
rating: item.customerRating,
brand: item.brandname
};
},
templates: {
group: 'products_simple',
options: {
rating: true,
brand: true
}
}
exactMatch
boolean and boost
boolean
Two special properties, exactMatch
and boost
, can also be set in the normalize
function to add particular items to the list of exact matches or boosted items.
When the tile view displays, the exact match items will come first, followed by the boosted items and then the rest of the items.
Example:
normalize: function(item) {
if (item.name === DDG.get_query()){
item.exactMatch = true;
} else if (item.developer.name === DDG.get_query()) {
item.boost = true;
}
return { ... }
}
relevancy
object [optional]
When dealing with multiple items, the relevancy
property can be used to ensure the relevancy of each individual item. It can also be used to de-duplicate the returned items if desired.
In most cases you will only need to specify relevancy properties for the primary
relevancy block. However, if your Instant Answer is capable of dealing with different types of queries though, where different relevancy checks are necessary, you can supply additional relevancy blocks.
For example, the Quixey Spice (app search) handles two distinct types of app searches:
- Categorical searches, such as "social networking apps"
- Named searches such as "free angry birds apps"
When dealing with categorical searches, the name of the app doesn't need to be checked against the query for relevancy. However, the app's category does need to be checked and so two separate relevancy blocks, primary
and category
, are used to define the different relevancy constraints.
Sample code from quixey.js:
relevancy: {
...
category: [
{ required: 'icon_url' },
{ key: 'short_desc' },
{ key: 'name' },
{ key: 'custom.features.category', match: category_match_regexp, strict:false } // strict means this key has to contain a category phrase or we reject
],
primary: [
{ required: 'icon_url' }, // would like to add alt: 'platforms.0.icon_url'
{ key: 'name', strict: false },
]
}
Notes for Goodie Instant Answers
The relevancy
property is unlikely to be used in a Goodie Instant Answer, although it is completely functional. Potential use in a Goodie might involve large data sets to search through.
If using relevancy
in a Goodie, it must be specified in the frontend part of the code, as JavaScript. For more information about Goodie JavaScript visit the Goodie Display section.
Relevancy Blocks
A relevancy block is comprised of an array of simple objects. For each object, the properties are used to indicate certain constraints. The concept of a relevancy block is best explained with an example:
// First we provide the name for the relevancy block, "primary"
primary: [
{ required: 'icon_url' },
// "required" means the item must have a defined property matching the
// given name, in this case and "icon_url" must be defined for each Quixey
// item
//
// Note: "required" only ensures the presence of a property. It does NOT
// perform a relevancy check
{ key: 'name', strict: true },
// "key" indicates a property which will be checked for relevancy. If
// the given key is determined to be relevant, the item as a whole is
// considered relevant and no other keys in the relevancy block are
// checked for the current item
//
// The "strict" key allows you to turn on the "strict mode"
// for DDG.isRelevant
{ key: 'short_desc' }
// this is an extra "key" which serves as a fallback. This means if
// either the 'name' or 'short_desc' or relevant the item is considered
// relevant
],
// here we provide a secondary relevancy block with a chosen name of "category"
category: [
{ required: 'icon_url' },
{ key: 'name' },
{ key: 'short_desc' },
{ key: 'custom.features.category', match: category_regexp }
// the "match" key allows you to specify a regular expression which the
// given "key" must match
//
// Note: "match" only ensures the property matches the given regex. It
// does NOT perform a relevancy check
],
Note: The relevancy checking is done using the DDG.isRelevant()
function.
type
stringThe name of the relevancy block to use. If no value is provided, the default
primary
block will be used.For example, the Quixey spice determines the
type
based on the query. If the query matches against our category regex (i.e. the query contains a category word), we settype
to "category", otherwise we use "primary".skip_words
arrayA list of words to skip when comparing the specified text against the current query. Generally these words should include any trigger words for your Instant Answer. The skip words list is not dependent on the chosen relevancy block.
primary
array [required if usingrelevancy
]The list of relevancy terms for this particular relevancy block
<additional_relevancy_block>
arrayAn additional list of relevancy terms, using the same format as
primary
. This object (and other relevancy blocks) can be named arbitrarily.dup
stringThis indicates which property should be used to check for de-duplication. The given string supports dot path formatting, e.g., "item.foo.bar"
sort_fields
object [optional]
In some cases, the order of the tiles is important (e.g., price, rating, popularity) and you can use the sorting properties to specify the default ordering of the tiles. You can also specify additional sorting fields that will allow users to re-order the tiles using a different sort method.
This object specifies sorting fields (e.g., name, price, rating, reviews) and their respective comparison functions, which will be passed along to JavaScript's sort()
method.
Example:
sort_fields: {
name: function(a,b) {
return a.name < b.name ? -1 : 1;
},
rating: function(a,b) {
return a.rating < b.rating ? -1 : 1;
}
}
Notes for Goodie Instant Answers
When setting sort_fields
properties in a Goodie, you must specify them in the frontend part of the code, as javascript. For more information about Goodie javascript visit the Goodie Display section.
sort_default
string or object
A string specifying the default sort_field
to be used for initial sorting of the tiles.
sort_default: 'name';
If you have used more than one relevancy block, sort_default
can be given an object
specifying the default sort_field
for each relevancy block.
For example, if we had two relevancy blocks named primary
and category
our default_sort
could look like this:
//because we have two relevancy blocks...
sort_default: {
primary: 'name',
category: 'rating'
}
view
string [optional]
Typically you don't need to specify a view for Instant Answers unless you're using special functionality like the playable Audio tiles for the SoundCloud IA, or the Maps used in our Places IA.
Available Views:
- Audio
- Detail (default view for IAs with a single item)
- Images
- Map
- Places
- Tiles (default view for IAs with multiple items)
- TilesWithTopics
- Videos
model
string [optional]
Some Instant Answers use data to display results which is not directly displayed in a template. For example, the latitude and longitude of a Place, or the dimensions of an Image. The Instant Answer framework comes with built-in models to manage these data. Some views require a model - such as Audio or Places.
If you are specifying a template group, the model
property is automatically set for you.
Available models:
- Audio
- Image
- Place
- Product
- Video
More about using models and their properties can be found in their respective template groups.
Events
If you need to fire off an event handler when a tile is clicked or when your Instant Answer's tab initially opens, you can handle these events with a callback function.
onItemSelected
functionThis event occurs each time a tile is selected with a click.
Example:
onItemSelect: function(item) { player.play(item); }
Learn more about the
item
argument below.Note: If a tile-view result returns a single result, this event will also fire when the tab is opened/clicked, so you don't need to use both
onItemSelected
andonShow
to handle the case of a single-result tile viewonItemUnselect
functionThis event occurs each time a tile is unselected - i.e., the user clicks somewhere else on the page.
onItemUnselect: function(item) { // Pause playing media, change appearance, etc. }
Learn more about the
item
argument below.Note: If a tile-view result returns a single result, this event will also fire when the tab is closed, so you don't need to use both
onItemSelected
andonShow
to handle the case of a single-result tile viewonShow
functionThis event occurs each time an Instant Answer tab is displayed. This event fires when the Instant Answer is initially shown. It also fires when a user clicks another AnswerBar tab, then clicks to show it again.
onItemShown
functionSame behavior as
onShow
, but fired on a per-item basis. This is useful for separately requesting and updating information relevant to each tile - e.g. secondary API calls. For example, the Amazon Spice uses this event to render product ratings, and the Movie Spice sets each tile's image element using this event.onItemShown: function(item) { // Do something to the item, such as update latest info }
Learn more about the
item
argument below.onHide
functionThis event occurs when a Instant Answer tab is closed i.e. when another tab is selected.
The item
Argument
Events relevant to specific items pass an item
to their handler functions. This is a reference to the item's data object, rendered to the template. Modifying the properties will not update the DOM.
An added item.$html
property references the respective item DOM element as a jQuery object.
Notes for Goodie Instant Answers
When creating a Goodie, you must declare event handlers in the frontend part of the code, as JavaScript. For more information about Goodie JavaScript visit the Goodie Display section.