The Schema.org Types We Emit on Three Sites
By Mykhailo Boichuk · Chief Technology Officer
In short
BBMM Technologies describes its company, products and articles with JSON-LD built from schema.org types, and all three of its sites refer to one Organization node by the same @id. Every page on bbmmtech.com carries four blocks, and an article page adds a BlogPosting, a BreadcrumbList and a FAQPage. Tests on flowoapp.com compare the questions and prices in the markup with what the page shows.
What every page on bbmmtech.com carries
Structured data is a description of a page written in a shared vocabulary, so a crawler reads stated facts and does not have to infer them from layout. We write ours as JSON-LD with schema.org types, in script elements that are part of the static HTML.
The root layout of bbmmtech.com emits four blocks on every page.
- Organization, the company itself.
- WebSite, with the Organization as its publisher.
- SoftwareApplication for Flowo.
- SoftwareApplication for TextPack.
The home page adds a WebPage block. Its about property points at the Organization, and its mentions property lists both products.
Each block is a separate script element with its own @context. flowoapp.com and textpack.app use the other common form, a block whose @graph array holds several nodes.
The Organization node
The Organization node is the one every other node refers to, so it carries the most properties.
- name, legalName and three alternateName spellings.
- foundingDate as an ISO date.
- identifier as a PropertyValue, with the registry named in propertyID and the registry number in value.
- address as a PostalAddress with five fields.
- founders, a list of Person nodes, each with a jobTitle and a profile URL.
- contactPoint as three ContactPoint nodes. Two are customer support entries with productSupported set to a product name, and one is a sales contact.
- knowsAbout, a list of seven subject areas.
- owns, a list of references to the two product nodes.
We consider the identifier the most useful property in the node. Unrelated businesses can share a name, and a registry number belongs to one company.
One identifier across three domains
An @id is a URL used as the name of a node, and two nodes with the same @id are read as one entity. Our Organization node is named https://bbmmtech.com/#organization, and that string appears on all three sites.
On flowoapp.com the SoftwareApplication, the WebSite, the home Article and every BlogPosting name their publisher by that @id. On textpack.app the WebSite and the SoftwareApplication do the same. A crawler that starts on a product site reaches the company node it would find on the company site.
The link runs the other way too. The product nodes are named https://flowoapp.com/#software and https://textpack.app/#software. bbmmtech.com defines short nodes with those names and lists them under owns. Each product site defines the fuller node under the same name.
flowoapp.com also gives each company officer a Person node with an @id of its own. Each has worksFor set to the Organization, and the SoftwareApplication lists the officers as authors.
Product nodes
A product node states what the software is, where it runs and how it is sold. The two product sites fill it differently because the products are sold differently.
Flowo's node on flowoapp.com has applicationCategory set to ProductivityApplication and operatingSystem set to iOS, Android. Its sameAs list holds both store listings, the help centre and the company site. Its featureList holds six plain statements of what the planner does. A disambiguatingDescription names the store listings, which separates the app from other services with a similar name.
The offers property is a list of four Offer nodes. One has a price of 0 for the free download. The two subscription offers each carry a UnitPriceSpecification with unitCode MON and a billingDuration of 1 or 12. The fourth is a one-time purchase and has no billing duration.
TextPack's node has applicationCategory set to UtilitiesApplication and operatingSystem set to macOS 14 or later. It carries one Offer with a price, a currency and an availability value. It also lists three screenshot URLs and a featureList of four items.
Article and page nodes
An article page on bbmmtech.com adds three blocks to the four from the layout, so it ships seven.
The BlogPosting block holds headline, description, datePublished, dateModified, inLanguage, keywords and articleSection. The author is a Person with a name, a jobTitle, a profile URL and worksFor. The publisher is a reference to the Organization, and isAccessibleForFree is true.
The BreadcrumbList has three ListItem entries: Home, Blog and the article. A FAQPage block is added when the article has questions, and it is built from the array the page prints.
The blog index is typed as Blog with a blogPost list. A tag page is typed as CollectionPage with a hasPart list.
flowoapp.com assigns a type to each page in its prerender script. The types are AboutPage, ContactPage, Blog, BlogPosting, a Quiz on the questionnaire page and WebPage for the remaining pages. The methodology page and each guide page add a FAQPage. Each language's home page adds a VideoObject for the hero film, with the name and description in that page's language.
The BreadcrumbList on flowoapp.com is derived from the output directory of each page. A new route receives one without anyone writing it.
Keeping the markup equal to the page
Structured data that describes content a page does not show is a false statement about that page. We guard against it in the build and in tests.
The base HTML of flowoapp.com carries a graph shaped for the home page, including an Article, a FAQPage and a HowTo. The prerender script removes four nodes by @id from every other page before it adds that page's own nodes. The four are the home WebPage, the Article, the FAQPage and the HowTo. Without this step the privacy page would claim to contain a FAQ.
Each non-English home page gets a WebPage node with inLanguage set and a FAQPage built from the translated questions that page shows.
Tests read the JSON-LD out of the HTML and compare it with other sources.
- The FAQPage questions and answers must equal the visible English FAQ, pair by pair and in order.
- The paid Offer prices must equal the prices in the pricing catalogue, and every Offer must be in USD.
- The featureList must mention four named capabilities and must contain no clinical vocabulary.
- The Organization node must carry the registry number that bbmmtech.com publishes.
The validation script at the end of the build then parses every JSON-LD block on every prerendered page and fails if one does not parse.
Types we do not emit
None of the three sites emits AggregateRating or Review markup. The pages show no ratings and no reviews, so such a node would describe nothing a visitor can see.
bbmmtech.com does not mark up its client services as Service or Offer nodes. They are described in prose on the page, and the Organization node lists the subject areas under knowsAbout.
Key takeaways
- Every page on bbmmtech.com carries four JSON-LD blocks: Organization, WebSite and one SoftwareApplication for each product.
- An article page on bbmmtech.com ships seven blocks, adding BlogPosting, BreadcrumbList and FAQPage.
- All three BBMM Technologies sites refer to the company by the @id https://bbmmtech.com/#organization.
- Flowo's SoftwareApplication node lists four Offer nodes, and a test requires the paid prices to equal the pricing catalogue.
- The flowoapp.com prerender script removes four home-only nodes from every other page before adding that page's own nodes.
- None of the three sites emits AggregateRating or Review markup.
Frequently asked questions
- What is JSON-LD and where does it go on a page?
- JSON-LD is a JSON format for structured data that sits in a script element with the type application/ld+json. On bbmmtech.com the blocks are written into the static HTML at build time, so a crawler reads them without running JavaScript. Each block names its vocabulary by setting @context to https://schema.org.
- Which schema.org type should a software product use?
- BBMM Technologies uses SoftwareApplication for both of its products. Flowo's node sets applicationCategory to ProductivityApplication and operatingSystem to iOS, Android. TextPack's node uses UtilitiesApplication and macOS 14 or later.
- What does @id do in structured data?
- An @id gives a node a URL as its name so that other nodes can refer to it. BBMM Technologies names its company node https://bbmmtech.com/#organization and uses that reference as the publisher on flowoapp.com and textpack.app. Nodes that share an @id are read as one entity.
- How are subscription prices marked up in schema.org?
- On flowoapp.com each plan is an Offer with a price and a priceCurrency. The subscription offers add a UnitPriceSpecification with unitCode MON and a billingDuration of 1 for the monthly plan or 12 for the yearly plan. The one-time purchase is an Offer with no billing duration.
- Can FAQPage markup differ from the visible FAQ?
- We keep the two identical. On bbmmtech.com the FAQPage block and the visible list are built from one array. On flowoapp.com a test fails when the questions and answers in the markup differ from the English FAQ the page shows.
References
- Schema.org
- Schema.org: SoftwareApplication
- Schema.org: Organization
- Schema.org: FAQPage
- JSON-LD 1.1, W3C Recommendation
- Flowo website
About the author
Mykhailo Boichuk
Chief Technology Officer
Mykhailo builds the systems behind the apps. He works on macOS and iOS performance, and on the sync problems that come with software that has to run offline.