Canonical Presence, step by step
Your business information lives in one record on your own website. A check reads the places you can’t change every morning and emails you when one is wrong.
The problem
Google says you close at five. You close at six. Your website still lists last year’s prices, and ChatGPT is quoting both. Each of those was right when someone filled it in. Then your business changed, and most of them didn’t.
→ The solution
Canonical Presence wires how your business runs to its front door, so you stop paying an agency to keep it current. One record in your website’s code fills in your pages, what search engines read and what AI assistants quote. It changes when your business does, from the email you were sending anyway. Every day a check reads the places you don’t control and emails you when one is wrong. Nothing changes until you say so.
01 · Where this started
Twenty days at the wrong price
When an artist we work with closed her first gallery show, her own website went on showing the gallery’s prices, 40 to 53% below hers, for twenty days before we changed them.
She didn’t mind, and that’s the problem. Twenty days is what small businesses have been taught to expect: no budget, no support. The people who build small-business websites are judged on the launch, on how the work looks in their own portfolio, not on how you look a year later. Keeping it current gets sold as upkeep, someone who comes around now and then to tidy up. It’s like hiring a janitor to update your website. So we fixed it on our side: a check now flags a show that has ended the morning after, with its prices still up.
She is Sara Paula Hoffman, a visual artist who sells through galleries. When we inventoried where she appeared online, we found eleven places describing the same person and the same work, and she controlled four of them.
Hers were her site, a second site under her full name (it now forwards to the first), Instagram and LinkedIn. Three were institutional: a university faculty page, from a post she has since left, carrying the most authoritative version of her biography, and two gallery pages. The rest were marketplaces and show announcements that appeared when a gallery decided to post.
Meanwhile her actual inventory (titles, sizes, prices) lived in spreadsheets on her own computer, connected to none of it.
This is the normal condition of a small business. Not neglect: accumulation. Every one of those pages was made for a good reason, by someone competent, at a moment when it was true.
The engine
02 · How it fits togetherThe record is a handful of files. Not a CMS, not a database the client logs into: files in the repository that the build reads. Titles, years, media, dimensions in inches, the price and how it was derived, which show a work is currently hanging in, and the exhibition history.
Everything else is a projection of those files. The work pages render from them. The sitemap enumerates them. The VisualArtwork markup serializes them. The share images are drawn from them. The plain-text edition for language models is written from them. None of these can drift from each other, because none of them is a copy.
How the record changes over time
03 · Over timePaula does not log into anything. The intake we are building next asks nothing new of her either: she writes the email she was going to write anyway, and copies one address.
When she submits work to a gallery for a show, she is already negotiating in prose: which pieces, what price for this show, what dates. That email is the authoritative version of the agreement. It exists whether or not anyone builds a system around it.
So the system will read it. A private alias on her own domain (call it robot@) is not an inbox anyone opens. Mail arriving there will start a job. The job pulls out the things the record cares about (the venue, the run dates, the works named, any price agreed for the show) and drafts the change: a new exhibition entry, a consignment price on each work, and inquiry routing switched to that gallery for the length of the run.
Then it stops, and waits for a person.
Today a person does the reading. Letters to her exhibitions address are collected automatically, each saved whole with its attachments, and likely acceptances are flagged at the start of every working session. A person still reads each letter and drafts the change from it, every field tied to a line of the letter, and nothing reaches the site until it is approved. The email on the right shows the step we are automating; the works and prices in it are illustrative.
For And Now for Something New, Vol. 8 I’d like to submit Wild Duck III, Hedda Study 2, and Midwestern Dolls. Happy to do $5,200 on the Hedda for the show, the other two at catalog. Dates are Aug 1 through Sep 12; I can deliver the week before.
robot@ · draft 0142 · awaiting review · illustrative
exhibitions.json + lemieux-vol-8 + venue LeMieux Galleries + opens 2026-08-01 + closes 2026-09-12 pricing.json ~ wild-duck-iii → vol-8 ~ hedda-study-2 → vol-8 ~ price $6,000 → $5,200 ~ midwestern-dolls → vol-8 Inquiries for these three route to LeMieux until 2026-09-12.
Intake has to be free at the point of use, or it will not be used.
This is the part most content systems get backwards. They ask the owner to re-enter, into a form, an agreement she has just finished making in prose. That is extra work with a delayed payoff, so it gets skipped in month two, and by month four the record is fiction. A CC costs nothing and happens at the moment the fact becomes true.
And the job proposes rather than commits, the same rule the daily check follows, for the same reason. Anything reading an email will eventually misread a date, and one wrong date would otherwise propagate to ten surfaces before a person saw it. Both roads into the record will run through one review queue, and neither of them can write.
A journey, not a loop
The engine diagram is right about structure and wrong about time. Nothing here runs on a cycle. Events arrive when they arrive, out of order, from parties who are not coordinating with each other: a gallery replying on its own schedule, a courier, a buyer, a market. What the record has to survive is not a loop. It is a sequence nobody controls.
It begins with a negotiation. Paula and the gallery agree a list price, and the gallery takes a percentage of it. That number is now a shared object: what the gallery sells at, what she is paid against, and (if nothing keeps the two apart) what the next buyer treats as the going rate for a work that size.
Promotion has one baseline requirement: it has to raise the value of the works that sell.
Exposure bought by lowering the going rate is not promotion. It is a markdown with an opening reception. This is the reason the site exists at all.
So the site is not a portfolio. It is the canonical valuation of the entire archive, every linear inch priced by one rule, kept current with market conditions. Only once that exists can a show price be a local decision rather than a repricing.
A price agreed for a show is true of certain works, at one venue, between two dates. It is not true of the archive. The record holds it that way: the consignment price sits in pricing.json scoped to an exhibition with a run, and the archive valuation is untouched by it. The daily check watches the show price while the run lasts.
When the show closes, the scope ends and the works return to the price the rule gives them. The linear-inch rate is a separate, deliberate, archive-wide decision, made when the market moves, not when one show opens or closes.
The same record, ten places
04 · Presence



Ten surfaces, one record. Five are generated from it today; the business profile, the two social pages and the mailing list are next. Change a price in pricing.json and every one of them that is downstream of the build changes with it. Our build can’t write to some places: a gallery’s own listing, a marketplace, someone else’s post. Those are the ones that go wrong. So for the gallery listing, the facts flow the other way. A check reads it every morning and compares it with the record.
The half nobody builds
05 · The drift checkA single source of truth only tells you what you believe. It cannot tell you that you are wrong.
When one of Paula’s works is consigned to a gallery show, two prices now exist in the world: the one her site publishes and the one the gallery lists. They start equal. Galleries adjust prices, mark work sold, restructure their sites, and take listings down, usually without telling anyone, because there is nobody to tell.
So a job runs every day, fetches each consigned listing, and compares it to what the site publishes. It reports four things:
- SOLD
- A consigned work is marked sold.
- HOLD
- A consigned work is marked on hold.
- DRIFT
- The gallery’s price no longer matches what the site publishes.
- UNREAD
- The page 404’d or its structure changed. Never fail silently.
node scripts/gallery-watch.mjs · illustrative output
Gallery watch · 2026-08-04 06:00
Wild Duck III $8,400 available
Hedda, Study 2 $5,200 SOLD
Midwestern Dolls $6,800 available
2 item(s) need attention:
SOLD Hedda, Study 2: marked sold
at LeMieux for $5,200
Mark it unavailable on the
site and confirm terms.
DRIFT Midwestern Dolls: gallery
$6,800, site publishes $6,400
Update the exhibition price in
pricing.json.Two design decisions in that script matter more than the script.
It never acts on a gallery relationship. It prepares the decision and stops.
The job could update the price automatically. It does not, because the reason the two numbers disagree is a fact about a business relationship, and no scraper knows which number is correct. An automated check is a finder. A person is the judge. What the machine produces is a decision made ready, not a decision made.
And when a page cannot be parsed, it reports UNREAD rather than assuming nothing changed. A monitor that quietly degrades into always-passing is worse than no monitor, because it also produces confidence.
Every check is written to a table, so the same job that raises alerts is also the price history of each consignment: what a work was listed at, by whom, on which day.
The same job also reads the schedule’s own dates: a jury result that is overdue, a drop-off coming up, a show that closed with work still out, a consignment or online listing that has ended. Each one is emailed once, as a prompt. Once a work has sold, it is no longer watched.
Why ranking well is not the same as being quoted
06 · SEO & GEOSearch engine optimization gets a page ranked. Generative engine optimization gets a page quoted. These are now separate outcomes with separate mechanics.
Ahrefs looked at 15,000 queries and found that only 12 percent of the pages ChatGPT, Gemini and Copilot cite rank in Google’s top ten for the same query; for ChatGPT and Gemini alone it was under nine percent. Eight in ten cited pages did not rank for the query at all. Ranking is not a proxy for being quoted, and optimizing only for the first leaves the second to chance.
So the record produces three editions rather than one. The pages, for people. The structured data (VisualArtwork and Person JSON-LD, a sitemap) for crawlers. And a plain-text edition at /llms.txt for assistants: who she is, what the collections are, every work with year, medium and dimensions, the exhibition record, and a short note telling an agent where the canonical URLs live and who handles inquiries for work currently on a wall.
All three are generated from the same files in the same build. An assistant asked who Sara Paula Hoffman is now has a current, authoritative source to quote instead of assembling an answer from a faculty page, an older domain and a gallery post from 2023.
Three editions, one build
Generated from the same catalog that renders the pages, so it can never drift.
How to build one
07 · Six steps- 01
Inventory where you already appear
Before anything is built. List every property describing the business, mark which you control, and decide the canonical home. Paula had two live domains presenting the same artist; that question had to be settled before the record could mean anything. Her older domain now forwards to paulagallery.com.
- 02
Put the record in the repository
Structured, versioned, diffable. A price change should show up in a commit. If the record lives somewhere the build cannot read at build time, every surface downstream becomes a copy, and copies drift.
- 03
Let changes arrive from the work already happening
Find the moment the fact becomes true (an email, an invoice, a signed consignment) and read the record out of that. Anything that asks the owner to re-enter what they just wrote will be abandoned, and an abandoned intake is worse than none, because the record still looks maintained.
- 04
Generate all three editions
Pages, structured data, plain text. Same build, same source. If any edition is written by hand it will be the one that goes stale, and it will go stale invisibly.
- 05
Watch what you do not control
A daily job against the surfaces someone else owns. Report disagreement; do not resolve it. Record every check, so the monitor doubles as history.
- 06
Sign what travels
Every share render carries Paula’s seal. An image that turns up on a site you have never heard of still traces back to the record that produced it.
08 · What would prove this wrong
A method that can only confirm itself is not a method.
The claim is that consolidating to one record and checking it daily produces more inquiries and fewer wrong answers about the business. That claim is not yet settled. Paula’s site is new, and two works have sold, through two different galleries. Two sales are not a result.
We didn’t write down in advance what would count as working, and we should have. We’re writing it down now, dated October 2026: over the next twelve months, offers and gallery inquiries arriving through her site. The site records where visitors stop on the way to an offer. The watch table accumulates a price history we did not have before. If inquiries do not rise, if the drift check never catches anything a person would not have caught anyway, or if assistants keep quoting the older domain: those are the results that would sink it, and they get published here.
One honest caveat now: the drift check works because gallery pages happen to embed parseable fields. Sites that render prices only as images, or behind a login, defeat it. For those the method degrades to UNREAD every day, which is at least loud but is not a check.
Canonical Presence
How many places describe your business, and how many do you control?
We build the record, generate the surfaces, and leave you a job that tells you when the world stops agreeing with it.