Skip to main content
With the $wsExternalData module, you load file-based external data (JSON) from the shop’s own S3 into your templates and process it there. Typical use cases are additional information that does not come from the standard shop data, for example PDF lists for a product or content from WEBSALE components such as a Strapi instance. This page covers read access to stored files. Populating the buckets (upload, Strapi export) is done via the data interface, not via this module.

Basic concept

$wsExternalData has no variables of its own. Instead, you load data via a method into a template variable of your own and then continue working with it. The flow is always the same:
  1. Load - load() reads a file and returns its contents; you assign the result to a variable (e.g. $data).
  2. Check - you check with {{ if $data }} whether the loading succeeded.
  3. Output - only then do you iterate over or display the contents.

Always check for success

External data may be missing or unreachable (wrong path, empty bucket, access problem). Therefore, always wrap the output with {{ if $data }} – otherwise empty placeholders or “dead” HTML structures arise. In the error case, getLastError() returns a diagnostic message (for development only, not for the frontend).

How the three methods work together

  • load() loads the contents of a file (map or list, depending on the JSON).
  • read() lists the files of a directory without loading their contents – useful to dynamically determine which files are present and then load them with load().
  • getLastError() returns the last error message.

Data sources (source)

Both loading methods know two sources: user (bucket external-data, default) for your own project-related files, and system (bucket system) for files provided by WEBSALE components (e.g. Strapi exports).

Note on timing

load() and read() access S3 during page rendering. Each call is a network request. Therefore, load only what the page needs, instead of unnecessarily loading many files per page view.

Module overview

Example / excerpt of $wsExternalData
{{= $wsExternalData | json }}
JSON output
{
  "load": "ƒ()",
  "read": "ƒ()",
  "getLastError": "ƒ()"
}
Note: "ƒ()" denotes a function. Methods overview
MethodReturn typeDescription
load()map | listLoads the contents of a JSON file.
read()listLists the files of a directory (without contents).
getLastError()stringLast error message from load() / read().

Templates

External data can be loaded into any template, depending on the use case for example on product detail pages (additional data), category pages (additional lists), or content pages.

Variables

$wsExternalData does not provide any variables of its own. The loaded data is stored in the template variable to which you assign the result of load() (see Basic concept).

Methods

$wsExternalData.load()

Loads the contents of a file from the external data interface and returns it, depending on the JSON structure, as a map (for an object) or a list (for an array), so that it can be output in the template (e.g. PDFs, additional attributes, CMS content). Signature
$wsExternalData.load(file, options)
Return value
map | list – depending on the JSON structure, empty/null in the error case.
Parameters
NameTypeRequiredDescription
filestringyesPath to the file within the source (e.g. products/product_123.json).
optionsmapyesFormat and source options (see table).
Options (options)
KeyTypeRequiredDefaultDescription
typestringyesFile format. Currently allowed: json.
sourcestringnouserData source: user (bucket external-data) or system (bucket system).
maxDepthintno7Limits the read depth of nested JSON structures; deeper levels are truncated.
{{ var $data = $wsExternalData.load("products/product_123.json", { type: "json" }) }}
{{ if $data }}
  {{= $data | json }}
{{ /if }}

$wsExternalData.read()

Lists all files of a directory of the external data interface (optionally including subfolders) and returns their paths as a list. The file content is not loaded; use load() for that afterwards. Helpful when you need to determine dynamically which files are present in a directory. Signature
$wsExternalData.read(path, options)
Return value
list – paths of the files found.
Parameters
NameTypeRequiredDescription
pathstringyesDirectory path within the source (e.g. json/Deutsch/).
optionsmapnoSource and filter options (see table).
Options (options)
KeyTypeRequiredDefaultDescription
sourcestringnouserData source: user or system.
recursiveboolnofalsetrue: also search subfolders.
globboolnoSwitches the pattern interpretation on/off. Expects a boolean, not a pattern string (see note).
{{ var $files = $wsExternalData.read("json/Deutsch/", { source: "system" }) }}
{{ if $files }}
  <ul>
    {{ foreach $file in $files }}
      <li>{{= $file }}</li>
    {{ /foreach }}
  </ul>
{{ /if }}

$wsExternalData.getLastError()

Returns the last error message as a string if an error occurred during load() or read() (e.g. file not present, access not possible). The message is intended for troubleshooting and should not be output to customers in the frontend. Signature
$wsExternalData.getLastError()
Return value
string – error description, or empty/null if no error is present.
{{ var $error = $wsExternalData.getLastError() }}
{{ if $error }}
  <script>
    {{ autoescape "js" }}
      console.error("$wsExternalData Error: {{= $error }}");
    {{ /autoescape }}
  </script>
{{ /if }}
Output the error message only to the console (development), never visibly in the frontend. The autoescape "js" block ensures that special characters in the message do not break the surrounding script.

Actions

No actions are available for $wsExternalData.

Examples

Load and display product additional data (PDF list)

A common case: PDF links are maintained for a product via a JSON file. For product 137497, the file under products/137497.json contains:
{
  "pdf": [
    { "link": "https://medienserver.example/faq.pdf", "name": "Frequently asked questions and answers" },
    { "link": "https://medienserver.example/anleitung.pdf", "name": "User manual" }
  ]
}
Load the file, check for success, and output the PDFs as a list:
{{ var $data = $wsExternalData.load("products/137497.json", { type: "json" }) }}
{{ if $data and $data.pdf }}
  <ul>
    {{ foreach $doc in $data.pdf }}
      <li>
        <a href="{{= $doc.link }}" target="_blank" rel="noopener">{{= $doc.name }}</a>
      </li>
    {{ /foreach }}
  </ul>
{{ /if }}
Result
A list of linked PDFs. But only if the file was loaded and contains a pdf array.

Load CMS/Strapi content from the system source

From the system bucket, you typically load Strapi exports. In Content, Strapi mixes different block types. Each block carries a __component field, which you can use to filter selectively.
{{ var $cms = $wsExternalData.load("json/Deutsch/ws_start.json", { source: "system", type: "json", maxDepth: 20 }) }}
{{ if $cms }}
  {{ foreach $item in $cms.attributes.Content }}
    {{ if $item.__component == "elemente.categories" }}
      {{ include "components/cms/categories.htm" with $cContentItem = $item }}
    {{ /if }}
  {{ /foreach }}
{{ /if }}
A block in the JSON file looks like this, for example:
{
  "id": 1,
  "__component": "elemente.categories",
  "CategoryIDs": "10-04418,2-06719,3-82749",
  "ClassList": "row mb-3"
}
Result
Only blocks of type elemente.categories are rendered via the matching component. Other block types are skipped.

List the files of a directory

With read(), you determine which files are present without loading their contents. You then load the contents specifically with load().
{{ var $files = $wsExternalData.read("json/Deutsch/", { source: "system" }) }}
{{ if $files }}
  {{ foreach $file in $files }}
    {{ var $data = $wsExternalData.load($file, { source: "system", type: "json" }) }}
    {{ if $data }}
      <!-- continue processing $data -->
    {{ /if }}
  {{ /foreach }}
{{ /if }}
Result
All matching files are found and loaded one by one.

Loading with error handling

Output only on success; otherwise write the error message to the console.
{{ var $data = $wsExternalData.load("products/product_123.json", { type: "json" }) }}
{{ if $data }}
  {{= $data | json }}
{{ else }}
  {{ var $error = $wsExternalData.getLastError() }}
  {{ if $error }}
    <script>
      {{ autoescape "js" }}
        console.error("$wsExternalData Error: {{= $error }}");
      {{ /autoescape }}
    </script>
  {{ /if }}
{{ /if }}
Result
On success, the data appears; otherwise the cause of the error ends up in the browser console.
If you build a path from several components, you can join an array into a string with | join before passing it to load() / read(). For a fixed path, the string by itself is sufficient (as in the examples above).