Creating custom apps

In the settings section, click Custom apps in the column on the right hand side to access the list of own apps that you have created. You can add and edit your own apps and remove existing ones, provided that they are not currently in use.

The way it works is that you write your own Transformation logic in the Javascript programming language to transform the data from your source into one or more "articles". An "article" is much like a news article and can be shown either one at a time upon each new page transition or as a ticker of multiple consecutive articles.

Base Properties

You start by configuring a number of base properties. Some of these are core to the app and its structure, which means that they cannot be changed by the end user when he/she uses the app in the designer. Other base properties can be changed by the end user and the values you configure here will be the app's default values in the designer.

Property Explanation Can be changed by the end user
Web address of data source The web address (URL) of the JSON or XML datasource. You can use app specific properties between double curly brackets as a variable in the address.
XML data that is returned by the data source is converted to a JSON structure so that it can easily be used in the transformation logic.
No
Refresh icon (Re)load the source and display the next article or start running the ticker. N/A
Source online accessible within my network (Only if the request method is "GET") Indicates that the data source sits within you own network (intranet) and cannot be accessed over the public internet. If the playback devices are on the same internal network as the data source they should be able to retrieve the data this way. It's important that the source server has the right CORS configuration. You need one configuration for allowed origin http://*.playr.biz and one for https://*.playr.biz with:
  • Allowed method: GET, PUT and POST
  • Allowed header: *
No
Request method Select the HTTP request method. In almost all cases this will be GET. No
Request body (Only for request method "POST" or "PUT") Configure the datastructure that is sent to the server with the HTTP POST or HTTP PUT request. No
Style Sets the way you like your articles to be displayed:
  • As a single message
  • As a ticker
  • As a vertical ticker
Specific individual article styles can be chosen by the end user when he/she uses the app in the designer.
No
Base font type Sets the base font type from which you can deviate using the fontType formatting function in the transformation logic. Yes
Base text size Sets the base text size. You can use the relativeTextSize formatting function in the transformation logic to make parts of your text smaller or larger. Yes
Base Line spacing (Only if the app is available as "Single article" or "Vertical ticker") Sets the space between you lines. Yes
Base text color Sets the base text color which you can deviate using the textColor formatting function in the transformation logic. Yes
Alignment Set the way you like the text within the element to be aligned: to the left, centered, to the right or justified. Yes

Advanced Options

The advanced options section provides you with a couple of specific parameters that you might need to get your app to work correctly.

Property Explanation Can be changed by the end user
Refresh interval This let's you specify the frequency with which the app needs to poll the data source for new data during playback. No
Content type Some data sources require you to explicitly specify what format you like the content to be in. This let's you specify that. No
Authorization type If your data source requires you to be authorized, this let's you specify the type of authorization that you want to use. The options are:
  • None
  • Basic authentication
  • Authorization header
  • Generic header
  • Oauth2
No
Basic auth. username When the source requires basic authentication, this enables you to set the username. No
Basic auth. password When the source requires basic authentication, this enables you to set the password. No
Authorization header When the source requires an authorization header or OAuth2, this enables you specify the contents of the header. No
Generic header When the source requires a proprietary header for authentication, you can use this field to specify the value. The format is [header name1]: [header value1], [header name2]: [header value2], e.g. Subscription-Key: 34A55dd8fd8ad9a4345fb46d42, API-key: acme. No
OAuth provider When the source requires an OAuth2 connection to be made, you need to select the OAuth provider) that is configured for your data source. You can create/edit OAuth provider configurations by clicking on the gear/settings icon next to the select box. The test account that is associated with the selected OAuth provider is also the account that will be used when this app is used by the end user.
Once you have selected an OAuth provider with an attached OAuth account, you need make sure that the access token that is associated with the test account, is passed along in the request to the data source. In general a provider requires you to pass it either as an URL parameter or as a header. Either way, you can use the predefined system-property called {{accessToken}} to have SmartSign2Go insert the right access token in the right place. E.g. as URL: https://api.geonames.org/SearchJSON?placename={{locationName}}&accessToken={{accessToken}} or as authorization header: Bearer {{accessToken}}.
No

Transformation Logic

Transformation logic is written in the programming language Javascript. There are a number of basic objects and functions available that enable you to format data you get from the data source. Please read the transformation logic guide to learn how to write correct transformation logic.

App-specific Properties

Apart from the base properties, you can also create your own app-specific properties that you can use in the web address of the data source as well as your transformation logic. This allows the end user to customize the app's behavior when it's used on a specific page.

Creating App-specific Properties

Each app-specific property is defined by its:

  1. Type: primarily defines the way the end user can configure the property in the designer:
    1. boolean: represents a true/false value that can be configured with a checkbox
    2. enumeration: represents a list of selectable options. The format of selectable options is [value1,label1],[value2,label2],...(etc.), where the values are the only things you work with in the web address and transformation logic. The labels are only shown to the end-user when he configures the app. In general you want values and labels to be strings of letters (and optionally digits), in which case you need to enclose them between quotes. For example ["NY","New York"],["LA","Los Angeles"],["SF","San Francisco"] shows the end user a list of three city names. The code of the selected city is available in your app. The default and test values must not be enclosed in quotes, so you can simply fill out (e.g.) NY.
      You can also let the user select multiple options. In that case the default and test values are just a comma separated list, like so: NY,LA.
    3. integer: represents a number between a minimum and maximum that can be configured with both a slider and an input field
    4. string: represents a string of any type of characters that can be configured with an input field
  2. Name: the exact label that is shown in the designer when the end user configures the app
  3. Default: the default value that the property has when not explicitly configured
  4. Test: this is only used for testing your transformation logic within the custom app creation page.

Using App-specific Properties

You can reference app-specific properties by their "camelized" name. This means the name is transformed as follows:

  1. the first letter becomes a lower case letter
  2. if the name consists of multiple words (separated by spaces, dash or underscore), then they are joined together with each word starting with an uppercase letter

For example:

"Location name" => "locationName"
"CODE" => "cODE"
"App-specific property" => "appSpecificProperty"

In The Web Address

In the web address of the data source, you can embed a property by enclosing it in double curly brackets: {{locationName}}.

For example:

https://api.geonames.org/SearchJSON?placename={{locationName}}&username=demo

In case of a multi-select enumeration property, the value will be a comma separated list of selected options.

In The Transformation Logic

In the transformation logic you can reference the property through the app.props object, like so: app.props.locationName.

In The Request Body

You can use the app-specific properties in the request body in a similar manner as in the web address: by enclosing the property in double curly brackets. But this goes even further: you can write your request body as a Mustache template, which gives you additional convenient options like conditional rendering of text.

Dynamic Values With Code

In some cases a preset value is not sufficient and you have to pass a dynamic or calculated value along with a request. For this you can use bits of Javascript code (which is also the basis for transformation logic) in both the web address and the request body. The code should be placed in a block that starts with [[= and ends with ]]. For example:

<StartDate>[[= new Date().toISOString()]]</StartDate>.

Multiple lines are also possible. In that case, the result of the last line is the value used. For example:

<AuthToken>[[=
  var key = "foobar";
  var secret = "12345678";
  var param = new Date().toISOString();
  MD5(key + secret + param); // The result of this statement appears in AuthToken
]]
</AuthToken>

Useful Javascript Libraries

Two useful Javascript libraries are available by default in your code:

  • Momentjs: for easy date processing
  • MD5: for calculating hash values, e.g. for authorisation

With MomentJS you can easily create formatted date and time strings:

<StartDate>[[= moment().format("MM/DD/YYYY")]]</StartDate>

App-specific Properties In Code

You can also use the values of app-specific properties in your code by using these properties as described above: between double curly brackets, for example:

<EndDate>[[= moment().add({{daysAhead}}},'days').format("MM/DD/YYYY")]]</EndDate>

Input/Error Inspector

The Input/error inspector is a section that is collapsed by default, but can be opened and closed again by clicking on the title. When opened it will show the latest input that has been retrieved from the data source in a browsable way. This makes it a lot easier to find the right data you need in your transformation logic.

The Errors section will show errors that occur when retrieving data or executing your transformation logic.

Sample

In a "mini page" the rendered output is shown as it would be displayed when the app is used. When you click the Refresh icon, the next formatted article will be shown here or the running ticker with the formatted output.

By default the sample page has a white background, but if you are creating the app with light colors to specifically be used (by default) on a dark background, you can use the Sample background color color picker to display the app against a fitting background.

OAuth Providers

Within your company, you can configure multiple OAuth providers. An OAuth provider is a configuration to access an OAuth2 app that you have configured on a specific third party website. E.g. let's say you like to access the LinkedIn API. Then you need to have a LinkedIn account with which you go to LinkedIn's Developer section. There you create a new "app" through which you can access the LinkedIn data on behalf of yourself. You don't need much to configure such an "app"; the most important thing is that you need to specify the right callback URL, which should be set to:

https://playr.biz/auth/oauth2_generic/callback

On the SmartSign2Go end, you need to configure the settings listed below:

Property Explanation
Name Give your OAuth provider an appropriate name, since this will be shown in the selection box when configuring your app. E.g. "LinkedIn".
Client ID Fill in the client ID/key provided by the third party OAuth2 app you created.
Client secret Fill in the client secret provided by the third party OAuth2 app you created.
User info URL Fill in the full URL of where the OAuth2 user info can be retrieved from this provider.
Authorization URL Fill in the full OAuth2 authorization URL from this provider.
Token URL Fill in the full OAuth2 token URL from this provider.
Scope Fill in the scope for which you are requesting authorization. This needs to match the scopes that you specified in the third party app. If multiple keywords need to be specified, you generally separate them with a space. For instance r_liteprofile r_emailaddress r_organization_social.
Path to email (optional) The path to the attribute in the user info response where the user's email can be found. E.g. when the response is something like { user: { info: { email: "foo@bar.com", firstName: "Foo", lastName: "Bar" }}}, then specify the path, using a forward slash separator like so: user/info/email.
Path to first name (optional) The path to the attribute in the user info response where the user's first name can be found. E.g. in case of the user info response example above, specify the path, using a forward slash separator like so: user/info/firstName.
Path to last name The path to the attribute in the user info response where the user's last name can be found. E.g. in case of the user info response example above, specify the path, using a forward slash separator like so: user/info/lastName.
Test account Once your provider is configured correctly, you need to connect your own user account to it so that data can be retrieved on behalf of you. This can be done by clicking the Connect test account button. Note that this is also the account that will be used during playback of the app in which this OAuth provider is used.