Tool

Schema Markup Templates for Software Companies

Four JSON-LD blocks for a property-ops software vendor’s site, with where each one goes. Replace the values in angle brackets, wrap each block in <script type="application/ld+json">, and validate before shipping. The structured data guide covers which of this the answer engines make use of and which is decoration; this page is the files.

Before you paste

One Organization node per site, with an @id, and every other node refers to it by that @id rather than repeating the name. Values match the visible text on the page; markup that describes something the page does not show is against Google’s structured data guidelines and, more to the point, it is a contradiction between two of your own sources. Do not add aggregateRating unless the reviews are on that page. G2 and Capterra ratings live on G2 and Capterra, and the sameAs array is how you point at them.

Validate with the Schema.org validator at validator.schema.org and with Google’s Rich Results Test, then view the source of the deployed page rather than the CMS preview, because more than one plugin strips script tags on publish. The same values should appear in your llms.txt; the llms.txt template uses the same fields on purpose.

1. Organization with sameAs

This goes on every page, in the head, and it anchors the entity: it is the node that says the name on your site, the name on LinkedIn and the name on G2 are one company. The sameAs list is the important part, so include every profile you control, including the PMS marketplace listings.

{
  "@context": "https://schema.org",
  "@type": "Organization",
  "@id": "https://<yourdomain.com>/#organization",
  "name": "<Vendor name>",
  "legalName": "<Legal entity name, Inc.>",
  "url": "https://<yourdomain.com>/",
  "logo": "https://<yourdomain.com>/<logo>.png",
  "description": "<The same one-sentence category description as the homepage and llms.txt>",
  "foundingDate": "<YYYY>",
  "address": {
    "@type": "PostalAddress",
    "addressLocality": "<City>",
    "addressRegion": "<State>",
    "addressCountry": "US"
  },
  "contactPoint": {
    "@type": "ContactPoint",
    "contactType": "sales",
    "email": "<sales@yourdomain.com>"
  },
  "sameAs": [
    "https://www.linkedin.com/company/<slug>",
    "https://www.g2.com/products/<slug>/reviews",
    "https://www.capterra.com/p/<id>/<slug>/",
    "https://www.crunchbase.com/organization/<slug>",
    "https://x.com/<handle>",
    "<PMS marketplace listing URL, e.g. your AppFolio Stack or Buildium Marketplace page>"
  ]
}

2. SoftwareApplication

This goes on the product page, once, and describes the thing you sell in the category words a property manager uses. applicationSubCategory carries the category phrase and featureList carries three to six features in plain words; put the integrations in the description and the feature list, because Schema.org has no dedicated integrations property.

{
  "@context": "https://schema.org",
  "@type": "SoftwareApplication",
  "@id": "https://<yourdomain.com>/product/#software",
  "name": "<Product name>",
  "url": "https://<yourdomain.com>/product/",
  "applicationCategory": "BusinessApplication",
  "applicationSubCategory": "<Category as a property manager says it, e.g. Maintenance coordination software>",
  "operatingSystem": "Web, iOS, Android",
  "description": "<One sentence: what it does, for whom, door range. Integrates with <PMS list>.>",
  "publisher": { "@id": "https://<yourdomain.com>/#organization" },
  "audience": {
    "@type": "BusinessAudience",
    "audienceType": "<Property management companies with 200 to 5,000 doors>"
  },
  "featureList": [
    "<Feature 1, e.g. Resident repair requests by text, email and portal>",
    "<Feature 2, e.g. Vendor dispatch with COI tracking>",
    "<Feature 3, e.g. Two-way sync with AppFolio and Buildium>"
  ],
  "softwareHelp": {
    "@type": "CreativeWork",
    "url": "https://<yourdomain.com>/help/"
  },
  "offers": {
    "@type": "Offer",
    "url": "https://<yourdomain.com>/pricing/",
    "priceCurrency": "USD",
    "price": "<lowest published per-unit price, e.g. 1.60>",
    "description": "<Per unit per month, $<x> monthly minimum>"
  }
}

3. FAQPage

This goes on any page where the questions and answers are printed in full in the visible text, and nowhere else. Google’s FAQPage documentation limits the FAQ rich result to government and health sites, so do not expect one; the value is that each buyer question gets a single-paragraph answer that is the same in the markup and on the page.

{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "Does <Product name> integrate with AppFolio?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "<Yes or no, then how: what syncs, in which direction, and setup time. Same words as the page.>"
      }
    },
    {
      "@type": "Question",
      "name": "How much does <Product name> cost?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "<Per-unit price, monthly minimum, setup fee, as published on the pricing page.>"
      }
    },
    {
      "@type": "Question",
      "name": "What size portfolio is <Product name> built for?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "<Door range and property types, e.g. 200 to 5,000 doors, SFR and small multifamily.>"
      }
    }
  ]
}

4. Product with Offer for the pricing page

This goes on the pricing page only, one Offer per tier, and every number in it also appears on the page. A quoted tier gets an Offer with no price and a description saying so; do not invent a number to satisfy a validator.

{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "<Product name>",
  "url": "https://<yourdomain.com>/pricing/",
  "description": "<One sentence, same as the SoftwareApplication description>",
  "brand": { "@id": "https://<yourdomain.com>/#organization" },
  "offers": [
    {
      "@type": "Offer",
      "name": "<Tier name, e.g. Core>",
      "url": "https://<yourdomain.com>/pricing/#core",
      "priceCurrency": "USD",
      "price": "<2.00>",
      "priceSpecification": {
        "@type": "UnitPriceSpecification",
        "price": "<2.00>",
        "priceCurrency": "USD",
        "unitText": "per unit per month",
        "referenceQuantity": { "@type": "QuantitativeValue", "value": 1, "unitText": "unit" }
      },
      "eligibleQuantity": { "@type": "QuantitativeValue", "minValue": <80>, "unitText": "units" },
      "availability": "https://schema.org/InStock"
    },
    {
      "@type": "Offer",
      "name": "<Tier name, e.g. Enterprise>",
      "url": "https://<yourdomain.com>/pricing/#enterprise",
      "priceCurrency": "USD",
      "description": "<Quoted per portfolio above <N> units; say the same on the page>",
      "availability": "https://schema.org/InStock"
    }
  ]
}

What these do not do

They do not put you in an answer. A vendor with perfect markup and no presence on the pages that get cited for its category is a vendor with tidy markup. Structured data removes ambiguity about who you are and what you sell, which is a precondition, and the audit checklist puts it in section two of five for that reason. Run the checker before and after you ship these; if the row does not move, the cause is in the other sections. The rest of the free tools cover them.

Get your row explained — $3,500

Seven days. Twenty-five prompts across four engines. The cause behind your row and a 90-day fix. Ryan replies with an agreement and an invoice; no call required.

Prefer a call? Contact.

Goes to ryan@webpossible.com with this page’s URL attached. Never shared, never sold. See the privacy policy.

Part of the tools.