Technical & Structure · 8 min read · September 24, 2026 · Hafsa Tariq, gaash.ai
A portfolio a crawler can read: captions, alt text and a page per shoot
In the HTML a crawler receives, each photograph is a file address plus whatever words you attached: a file name, alt text, a caption, the paragraph beside it. The picture cannot say which venue, which date or what was photographed. Give each wedding or project its own page, write those facts in visible text, and write alt text for someone who cannot see the image.
What does a crawler receive from a gallery page?
The HTML, and in it an img element for each photograph: an address such as /images/IMG_4821.jpg, an alt attribute if you wrote one, and whatever text sits on the page around it. The picture itself is a separate file. Whatever a system might make of the pixels, they cannot say which venue it was, which month, which package or who the people are to you. Those are words, and they have to be on the page.
Two gallery builds leave even less. A grid drawn by a script arrives as an empty container and a script tag, and the photographs and captions appear only once the script runs in a browser; OpenAI's crawler documentation describes no step in which its crawlers run scripts, and Google's JavaScript documentation describes rendering as a separate, deferred step. An embedded Instagram feed or post arrives as embed code that points to Instagram, and the captions you wrote there are not part of your page's text.
Our audit crawler did its crawling the same way, without running scripts. Across the 9,483 sites in our audit (40 trades, 90 metros, late August to early September 2026), 3.0% delivered their content only through JavaScript and came back as an empty page. That covers every trade; we publish no gallery or photographer cut of it. To see your own case, open a project page with scripts off: what is left is what a fetcher has. The free visibility check reads your site as it is served, and a person sends a written result within 48 hours.
| The gallery | What a fetcher receives | What to change |
|---|---|---|
| Images in the HTML, with alt text and captions under the ones that carry a fact | File names, alt text, captions and the page's paragraphs | Nothing; this is the target |
| Images in the HTML with camera file names and no alt text | Addresses like IMG_4821.jpg and nothing else | Rename on export, write alt text, add a paragraph and captions |
| A grid drawn by a script after the page loads | An empty container and a script tag | Serve the images and the text in the HTML from the server |
| A lightbox that shows captions only when a photo is opened | The captions only if they are in the HTML before the click | Put the caption in the page's text, not only in the lightbox |
| An embedded Instagram feed or post | Embed code and a link to Instagram | Keep it if you like it, and put the project's photos and words on your own page |
| Photographs set as CSS backgrounds | No image element and no alt attribute | Use img elements for photographs that carry content |
| A slideshow video of the day | A video file or a player | A paragraph under it saying what it shows |
One page per wedding or project, with the facts written out
A page called Weddings that holds every couple's photos in one grid can answer one question: do you photograph weddings. A page for one wedding can answer the questions couples ask: have you worked at our venue, in our season, in the style we want, on a day like ours. Give each wedding, session or commercial project you want to be found for a page of its own, with a title that says what it is and a short account in text.
The account is a paragraph or two, not a diary. It names the venue and the town, the month and year, the style in the words you use elsewhere, what you photographed, the hours of coverage and whether a second shooter came, and which package it was. For a business client it names the kind of company, the brief, what was delivered and where it was used, as far as the client allows. These are also the pages a venues list links to, which the ChatGPT article covers from the couple's side.
[Venue] wedding in [town], [month year]
[The couple's first names, with their permission, or "A September wedding"]
[One or two sentences: the day, the style, the light.]
Venue: [venue], [town]
Coverage: [hours] hours, [with or without] a second shooter
Photographed: [getting ready, ceremony, family portraits, couple's portraits, reception]
Package: [package name], from [price]
Vendors: [planner, florist and others, with their permission]
[A selection of photographs, each with alt text; a caption under the ones that carry a fact]
[Link: wedding prices] [Link: check a date]Ask before you publish. Couples, families and business clients decide whether their names and faces appear, and the page works without names, because the venue, the date and the style carry the facts. For photographs of children, ask the parents.
Captions say where and when; alt text says what is in the frame
The two do different jobs, and they should not repeat each other. A caption is visible text that places a photograph: "First look on the dock at [venue], [town], in late September light." Every reader sees it, and it puts the facts a couple searches for (the venue, the town, the season) beside the picture that proves them. Caption the photographs that carry a fact; a run of dance-floor frames does not need a caption each.
Alt text is the photograph's stand-in for a reader who cannot see it. The HTML standard counts a photograph in a gallery as a key part of the content and asks for alt text that can take its place. It also advises against copying the caption into the alt attribute, which hands a screen reader user the same sentence twice, and against opening with words like "photo of", since the image is already announced as an image. So describe what is in the frame: who, doing what, where in the picture, in what light.
Google's image guidance adds the search side: alt text should be descriptive and useful, and filling it with keywords risks the site being treated as spam. "Toronto wedding photographer best wedding photos Toronto" describes nothing in the frame and helps no reader.
| The photograph | Alt text that fails | Alt text that works |
|---|---|---|
| The couple's first look on a dock | "IMG_4821" | "On a wooden dock, one partner turns to see the other walking toward them, lake and pines behind" |
| Grandparents during the vows | "wedding photographer toronto documentary wedding" | "An older couple in the front row holds hands as the vows begin" |
| A team headshot | "headshot" | "A woman in a navy blazer, arms folded, smiling, against a pale gray backdrop" |
File names: the one line of text every image already carries
Each image arrives with a file name, and a camera's is a sequence number: IMG_4821.jpg, DSC_0042.jpg. Google's image guidance recommends short, descriptive names over generic ones and treats them as a light clue to the subject. A name like lakeside-first-look-muskoka-01.jpg says what a sequence number cannot.
Set your editing software to name files on export from a pattern: the subject or venue, the place, the moment, a number. Once the export preset exists it costs nothing per wedding. Leave files that are already published under their old names unless you can send the old addresses on with a 301 redirect, since other pages may link to them.
ImageObject markup, only for what the photograph and the page show
Structured data can repeat what the page says about a photograph, and should stop there. schema.org's ImageObject, written as JSON-LD in the example below, carries a contentUrl for the file, a caption, a creator, a dateCreated and a contentLocation, which schema.org defines as the place depicted. Use it for the photographs a page is about, filled only with what the page itself states. Google's introduction to structured data asks for markup that describes content the reader can see, and its guidelines add that correct markup does not guarantee it will show up in results.
{
"@context": "https://schema.org",
"@type": "ImageObject",
"contentUrl": "https://www.example.com/images/lakeside-first-look-muskoka-01.jpg",
"caption": "First look on the dock at [venue], [town], in late September light",
"creator": { "@type": "Person", "name": "[photographer's name]" },
"dateCreated": "[yyyy-mm-dd]",
"contentLocation": { "@type": "Place", "name": "[venue], [town]" }
}Two cautions. Leave out any field the page does not state; a contentLocation the caption never mentions is a claim only the markup makes. And do not count on the ImageObject nodes a site builder adds on its own: across the audit, most of the markup present described the website (WebSite, WebPage, BreadcrumbList, SearchAction, ImageObject) rather than the business.
Photographers' own published figure is about markup's absence: 32.7% of their sites carried no schema.org markup at all, against 17.8% across the whole sample. The node to write first is the business, as the photographers' hub sets out, and structured data for AI covers which types describe it.
Common questions
Does every photograph in a gallery need alt text?
Every image element needs an alt attribute; the HTML standard makes that the rule, with few exceptions. A photograph that carries the content gets a description of what it shows. A purely decorative image, such as a texture behind a heading, gets an empty alt attribute so a screen reader passes over it. For a run of similar frames, a short true description each is enough.
Should I name the couple on the wedding page?
Only if they agree, and the page does not depend on it. The venue, the town, the month and the style are the facts another couple searches for; first names add warmth, and surnames add little for anyone but the couple. Ask when you deliver the gallery, note the answer with the booking, and take a page down or remove the names whenever anyone asks.
Will a paragraph of text spoil the look of my portfolio?
It need not. A short account above the photographs and a caption under a few of them can be set small and quiet, and the photographs still lead. What cannot bend is where the words live: in the page's HTML as text, not inside an image, a lightbox script or a slideshow. Style them however you like, as long as they stay text.
My website builder is made for photographers. Is it doing this for me?
Check rather than assume. View the source of a project page, or open it with scripts off, and look for your alt text, your captions and your paragraph, then read the file names in the image addresses. If the builder draws the gallery with a script, ask whether it can serve images and text in the HTML; if not, put the project's words in a text block it does serve.
Sources
The JavaScript and markup figures are this site's own, from the audit named below, and cover all 40 trades; the 32.7% is the photographers' own published rate. What alt text is for, and what Google says about file names and markup, comes from the documents linked where they are used.
Sources: our audit of 9,483 small-business sites, with its method · HTML Standard, images and alt text · Google, image best practices · Google, JavaScript SEO basics · Google, introduction to structured data · Google, general structured data guidelines
Read on