logo
  • Training
  • How-Tos
  • Documentation
  • FAQs
  • Support
  •  
  • Training
  • How-Tos
  • Documentation
  • FAQs
  • Support
  • Log In
  • Create an Account

How to Create a Custom JSON Feed

Page Navigation

    Related Topics

    • Template Overview
    • {{ blog_post }}
    • {% set_content_type %}
    • {% set_header %}

    Custom JSON feeds are valuable in many situations, and while it is easy to create a JSON feed in Marketpath CMS there are a few challenges that you should be aware of in order to prevent frustration.

    Collecting Your Data

    There are numerous ways to collect and prepare your data - exactly the same as for a normal page load. The exact method you use will depend on what you are trying to accomplish, but here are two suggestions that work well and are easy both to create and maintain. Note that you can easily combine the two for further power and flexibility:

    Using Custom Fields

    In your JSON template, define custom fields for your content editors to fill out. This is the data that will be output in the JSON feed. Fieldsets are particularly useful for allowing editors to fill out repeating data structures (JSON arrays).

    Fetching Dynamic Content

    There are dozens of ways that you can pull dynamic content from Marketpath CMS in your template - each of which can be combined with the others. A few examples are:

    • Fetch a list of articles by folder
    • Fetch a list of blog posts by blog, tag, and/or author
    • Fetch a list of calendar items by calendar and date
    • Fetch a list of datastore items with a custom query
    • Search through all content by keyword
    • Fetch information about whether or not the user is currently logged-in to a profile

    Reusable Templates

    One of the beautiful things about making JSON templates is that, if you build them with enough flexibility, you can re-use the same templates and/or pages multiple times for similar purposes by providing different input either through the custom fields on the page or through query string parameters passed in the request (or both).

    HTTP Headers

    Before beginning to output your data in the template (well, order doesn’t actually matter too much here, but it is generally more readable to put this at the top of your template), there are a few methods that you need to call so that your scripts can access and utilize your data:

    • {% set_content_type 'application/json' %} - tells the browser that the HTTP response contains a JSON object, which generally helps other scripts to be able to process the contents properly.
    • {% allow_cors %} - tells the browser that it is OK for websites on different domains to load this content. If you want to make this content available from all websites set {% allow_cors always %}, otherwise you will need to test that the origin matches the domain that you want to allow (eg: {% if request.headers.origin == 'https://specifically-allowed-domain.com' %}{% allow_cors %}{% endif %}).
    • {% set_header %} - If you specifically need to set other headers in the HTTP response (due to custom script requirements), you may use this method to do so. Keep in mind that there are a number of specifically enumerated headers that you are not allowed to set.

    Outputting JSON

    Outputting JSON to the template is exactly the same as outputting HTML or any other content types. There is one special challenge, however, due to the nature of the liquid syntax and how it conflicts with JSON syntax - both languages rely heavily on the “{“ and “}” characters:

    • JSON Example: {"object":{"text":"Value","url":"http://something.com"}}
    • Liquid Example: {{entity.title.value}}

    Outputting a single JSON property to the template could not be simpler with the “json_encode” filter. When using this filter you do not need to concern yourself with whether or not the value is null or an empty string.

    • Example: "custom_value":{{ entity.custom_value | json_encode }}

    Outputting a JSON object, on the other hand, can be a little more tricky due to the bracket limitation. The most simple workaround for this limitation is to output JSON brackets as a variable - particularly when it would otherwise result in multiple brackets next to each other in the liquid template. The "url_decode" filter makes defining the variable easy:

    • Bad: {"url":{{entity.full_url | json_encode}}}
      Reason: multiple brackets next to each other will likely cause a liquid error
    • Better: {"url":{{entity.full_url | json_encode}} }
      Reason: at least the brackets are not next to each other, but this is more difficult to read and may cause unintended side-effects in some circumstances. While you may get away with it in a small file there is a high probability that the three brackets next to each other will come back to hurt you later.
    • Good: {"url":{{entity.full_url | json_encode}}{{ '%7D' | url_decode }}
      Reason: you do not have multiple brackets next to each other in liquid anymore, and the JSON output is exactly what you originally wanted.
    • Best: {% var openbracket = '%7B' | url_decode %}{% var closebracket = '%7D' | url_decode %}{{ openbracket }}"url":{{entity.full_url | json_encode}}{{ closebracket }}
      Reason: all of the brackets in the liquid template are either for liquid methods or liquid output, and all of the JSON brackets are output as variables - which makes the code easier to troubleshoot and maintain (particularly in larger templates). While this may look a little disgusting in a small file or for a small example it adds up quickly to time saved troubleshooting larger or more complicated templates.

    Example: Blog Post JSON Feed

    Here is an example of a very simple template which will output the next 10 blog posts with a post date in the future (note: if this is intended to be usable outside of your own website you will need to add {% allow_cors always %} to the template.

    {% set_content_type 'application/json' -%}
    {%- var openbracket = '%7B' | url_decode -%}
    {%- var closebracket = '%7D' | url_decode -%}
    {%- blog_posts posts = start_date:request.date limit:10 sort_by:'post_date' sort_direction:'asc' -%}
    [{% for post in posts %}{{openbracket}}
        'title':{{post.title.value | json_encode}}
        ,'post_date':'{{post.post_date | format: 'o' }}'
        ,'summary':{{post.summary_html.value | json_encode}}
        ,'blog':{{post.blog.title.value | json_encode}}{% if post.image.is_valid %}
        ,'image':{{post.image.path | json_encode}}{% endif %}
    {{closebracket}}{% unless forloop.last %},{% endunless %}{% endfor %}]

    Full Blog Post Example

    For a fully-featured JSON template example, install the Flexible Blog Post JSON Feed package on your site. This package contains a single template which outputs a blog feed. The JSON structure is configurable at the page level and the blog posts returned are configurable via query parameters. Pagination-related information is returned using X-Pagination-* headers.

    Contact Marketpath Support

    • Secure Support Portal

      Call Us (M-F 8AM - 5PM EST)
    • 800.657.7786 - Toll-Free Support
    • 317.660.0209 - Local Support

    Courses

    • Editor Training
    • Developer Training
    • Other Training Options
    • FAQs
    • Examples

    Developers

    • Developer Training
    • Liquid Reference

    Marketpath CMS Logo in White

    Follow Us: