upsert_schema: Agent-Applied JSON-LD Structured Data

What the Get AI Traffic agent writes into your page's head, what it will not touch, what validation catches, and how to roll it back.

Published on July 16, 2026

upsert_schema is the tool the Get AI Traffic agent uses to add structured data to a page after you approve a fix. It writes a JSON-LD block into the page’s <head>, then publishes it through your site’s connection.

This page documents what the tool touches, what it refuses to touch, and how to undo it. For the decision of whether a page should carry a given schema type, read No Structured Data Means AI Has to Guess Who You Are, FAQ Schema Won’t Get You Rich Results Anymore. Add It Anyway., or You Have Reviews But No Review Schema. Those are business calls. This page is about the mechanics.

What it does

The tool takes three things: a page URL, a schema.org type (Organization, FAQPage, AggregateRating, Person), and a JSON-LD payload. It stores the block against that page, and your site emits it in the <head> on every render, wrapped in a <script type="application/ld+json"> tag.

The markup is server-rendered. It is in the HTML of the first response, not injected later by JavaScript. That is the point: AI crawlers mostly don’t run JavaScript, and Google renders JavaScript in a second pass, so a block added late can be processed late or missed entirely.

Nothing visible changes for a human reader. JSON-LD keeps the markup separate from your text.

Blocks are stored one per schema.org type, so a page can carry several. An Organization block and an FAQPage block coexist as separate tags.

Re-running it

Upsert means insert-or-replace, and the key is the page plus the type:

  • Same page, same type. The new payload replaces the old block. Running the tool twice does not leave you with two Organization blocks.
  • Same page, different type. The new block is added alongside the existing ones. Nothing already stored is disturbed.
  • Empty payload. The block for that type is removed.

So a re-run is safe and idempotent per type. The thing to watch is not the tool running twice, it’s a second source of the same type, which is the next section.

What it will not touch

  • Your visible content. The tool writes to the head and has no path to the body. It cannot alter a word your readers see.
  • Schema you already have. The output is additive: your site emits the blocks this tool stored, and leaves everything else alone. If your theme or SEO plugin already emits JSON-LD, this composes with it rather than replacing it. That cuts both ways. If a page already has an Organization block from another source, adding a second one leaves two entity claims on the page, and conflicting entity data is worse than one clean block. Check what you already emit before adding.
  • Anything that isn’t a single post or page. Blocks emit on singular pages. An archive, a category listing, or a search results page has nowhere to hang one, and a URL that doesn’t resolve to a post on your site has nothing to attach to.

Validation

The payload has to parse as JSON before the tool will accept it. A syntax error is rejected rather than published as a broken tag.

Know the limit of that check. Valid JSON is not valid schema.org, and neither one makes the claim true. The tool will not catch an AggregateRating whose count disagrees with the number printed on the page, and that mismatch is exactly what Google’s guidelines police: marked-up content has to be visible and a true representation of the page, or the rich result can be dropped or flagged as spam. Syntax is the tool’s job. Accuracy is a review question, and it stays with you.

Timing

The block is in the HTML on the next render, so you can view source and confirm it immediately. Everything downstream is slower. Search engines and AI crawlers see it on their next crawl, and rich result eligibility follows re-indexing after that. Expect weeks, not minutes.

Set expectations on the ceiling too. Structured data is not a ranking factor, per Google’s longstanding guidance. This makes a page legible and eligible. It does not move you up the results, and nothing here should be measured that way.

Rolling back

Every applied change is written to the ledger with the prior state: the previous JSON-LD for that page and type, or an empty value when there was none. roll_back restores it exactly. When there was no block before, the reversal removes the tag rather than leaving an empty one behind.

Because the markup is server-rendered, a rollback is live on the next render. Crawlers pick it up on their next visit, with the same lag as the original apply.

  • purge_cache runs automatically after an apply, so a cached copy of the page without the schema does not linger at the edge. It is best-effort and skipped when the site has no Cloudflare credentials.
  • set_head_item writes arbitrary markup into the head. Use upsert_schema for structured data instead: it is keyed by schema.org type, which is what makes it safely re-runnable and cleanly reversible.
  • set_author_profile and reassign_author handle the human half of Person schema, the real byline and bio that an author.url points at. Person markup naming an author your site cannot back up is a claim with no source behind it.

Findings this tool resolves

  • missing_schema: the page has no Organization or LocalBusiness JSON-LD.
  • missing_faq_schema: the page has question-and-answer content but no FAQPage markup.
  • missing_aggregate_rating: the page shows ratings but no AggregateRating markup.

Want this checked on your own site?

Get your free AI-visibility audit