What are Tag Templates in ScopeStack, and how do they work?
Tag Templates
This article teaches the conceptual model behind Tag Templates—how they interact with structured data, how sections and loops work, and how tags are interpreted during document generation. It sets the stage for more practical guides on formatting and syntax.
Not that we have inserted extra spaces in the tags throughout this document because Hubspot's Help Center interprets them as code otherwise.
What Are Tag Templates?
In the ScopeStack application, “Tag Templates” are document templates that use “tags” rather than Mail Merge Fields to insert data into the template in order to produce a document for a client.
Where Does the Data Come From?
In addition to “tags”, Document generation platforms have settled on the use of JavaScript Object Notation (JSON) as the standard data format. JSON is ubiquitous in today’s internet, but three key features make it ideal for document generation. First, it is entirely text-based. This means that no special tools are required to read or write data in JSON format. Second, it is concise so it’s inexpensive to move between servers. Third, it’s very human readable. Consider the following example for describing the first government of the United States:
{ president:
{ first_name: “George”,
last_name: “Washington”,
state: “Virginia” },
vice_president:
{ first_name: “John”,
last_name: “Adams”,
state: “Virginia” },
representatives: [
{ first_name: “Fisher”,
last_name: “Ames”,
state: “Massachusetts” },
{ first_name: “John Baptista”,
last_name: “Ashe”,
state: “North Carolina” },
...
]
The “O” is JSON stands for Object. An object is delimited by curly brackets. In the above example, { first_name: “...”, last_name: “...”, state: “...” } is an object. Each object has “attributes” and in the example “first_name”, “last_name”, and “state” are attributes of the people who served in the first U.S. Congress.
There is a special kind of object in JSON for a collection of things called an “array.” In the example above, the values for the “representatives” is an array of individuals who served in the first Congress. An array can be recognized by the square brackets (“[“ and “]”) that wrap objects inside them.
These ideas of “objects” and “arrays” are important to how tags are handled in the document generation process.
View Merge Data to See the JSON Data
Think about what the above first U.S. Congress data would look like if we made a few alterations to the way it was laid out:
- Strip away the curly braces
- Move the attribute values below the attribute name
- Put dotted lines around the objects in an array
It would look something like this:
president
first_name
George
last_name
Washington
…
representatives
First_name
Fisher
Last_name
Ames
State
Massachusetts
Why is that important? Well, this is basically what you will see if you click on the “gear” icon in the header on a project page and select “View Merge Data.” That is one way that you can visualize the data that is available to you when building document templates. Be sure to view “V2” data when preparing Tag Templates!
Special Tags in Document Generation
Data Context
Before jumping into the special tags, we need to understand “data context”. In document generation, “data context” describes what part of the data we’re looking at. In the U.S. Congress example, the initial data context is the object with attributes for “president”, “vice_president”, and “representatives.” The special tags described below allow the data merge process to change “data context” and focus on a more specific part of the data. For example, we could change the data context to focus on just the “president” or the array of “representatives.”
Document Sections
There are two special and related “tags” in the new document generation process. The special tags look like this
{ #path.to.something}
…
{ /path.to_something}
These two special, related tags must occur in matching pairs in the order shown. The tags declare a “section” of the document and must always begin with the tag that opens with “#” and must always end with a tag that opens with “/”. The text value for “path.to.something” must also match.
What Is This “path.to.something”?
The “path.to.something” is just representative of how to navigate from the current “data context” to find an item. It could be as simple as the name of an attribute like {name}, but it could also traverse multiple layers. For example, {president.first_name} is the path to the name of the president.
What Happens in a Section?
What happens within a section depends on what is found at “path.to.something”. If “path.to.something” returns an object, then the section between the special tags will change the “data context” to focus on that specific object and any tags within the section will only be able to consider the attribute of that object. Consider this section:
{ #president}
The first President of the United States was {first_name} {last_name} of {state}.
{ /president}
{ #vice_president}
His Vice President was {first_name} {last_name} from the state of {state}
{ /vice_president}
Assuming we are using the example data, these two sections would produce the following output:
The first President of the United States was George Washington of Virginia.
His Vice President was John Adams from the state of Massachusetts.
If the object at “path.to.something” is an array, something a little different happens. With an array, the context loops over the elements in the array. The data context will switch to each element of the array in order from top to bottom.
The House of Representatives was as follows
{ #representatives}
- {last_name}, {first_name} of {state}
{ /representatives}
The above section would produce the output below.
The House of Representatives was as follows
- Ames, Fisher of Massachusetts
- Ashe, John Baptista of North Carolina
- …
Be careful! With an array, everything in the section will be repeated for each value of the array. If you accidentally include an introductory line like “The House of Representatives was as follows” then you will get a copy of that introductory text for each item in the array.
If the value found at “path.to.something” is any other kind of value, then the data context will not change. For example, the value of {#president.first_name} is “George.” If that tag were used to start a section, then the data context would still be focused at the “root” of the data. Where that can come in handy is when it is used as a true/false test. The example below shows how this could be applied and implies another nice feature of ScopeStack’s new Tag Templates – the ability to do comparisons.
The representatives from Massachusetts were
{ #representatives}
{ #state==”Massachusetts”}
- {first_name} {last_name}
{ /state==”Massachusetts”}
{ /representatives}
Result:
The representatives from Massachusetts were:
- Fisher Ames
- Elbridge Gerry
- Benjamin Goodhue
- Jonathan Grout
- George Leonard
- George Partridge
- Theodore Sedgwick
- George Thatcher
Other Special Tags
Two other tags will be very useful for generating documents in ScopeStack. The first is the tag that begins with a tilde like this
{ ~formatted_service_description}
This type of tag indicates that the value at “formatted_service_description” should assumed to be HTML content and converted from HTML when added to the document. Any field that uses Markdown (e.g., service_description, language fields, text blocks) will have a “formatted” equivalent added to the merge data (e.g., service_description has formatted_service_description) and the “formatted” fields will need this special html tag to be converted from HTML when added to the document.
The second helpful tag will allow images to be added to the document. The image tags begin with “%” like
{ %project.account_logo}
Wait, Comparisons? What Else??
Yes, comparisons like checking for items being equal (==), not equal (!=), greater than (>), less than (<) and similar can be used when building document sections as described above. The tags can also perform basic math, so something similar to the snippet below will work
{ #services}
{name} will cost {hourly_rate * extended_hours}.
{ /services}