Carousel Structured Data: ItemList Markup Explained

Carousel structured data is a list of links, expressed as schema.org ItemList markup, that tells Google your page is a collection of things which each have their own page. For a small set of content types, Google can then show those items as a horizontally scrolling carousel in search results. The markup does not build the carousel on your own page, and it does not guarantee one in search. It makes a summary page eligible.
The mechanics are simple, which is why the mistakes are so common. People add ItemList to pages where it does nothing, nest full product or recipe data inside it, or point every item at the same URL. This guide covers what a valid carousel needs, the difference between a summary page and an all-in-one page, which content types are supported, and the errors worth checking before you blame Google for not showing anything.
What a Host Carousel Actually Is
Google uses the term host carousel for a carousel that is hosted by one page and contains items that live on other pages of the same site. A searcher sees a row of cards, each with an image and a title, and clicking a card goes to that item's own page. The page that supplied the list is the host. Your markup is the instruction that says which URLs belong in the row and in what order.
This is different from the other meaning of carousel, the image slider on your homepage. A slider is a front-end widget and has nothing to do with structured data. Adding schema to a slider does not make search results carousel-like, and a carousel in search does not require any slider on your page. The two share a word and nothing else.
It is also different from ordinary rich results. A recipe page marked up with Recipe schema can earn a rich result on its own. A carousel is about the relationship between a list page and several item pages. The list page carries a thin layer of markup, the item pages carry the detailed markup, and the two together are what Google reads.
Summary Page Versus All-in-One Page
There are two ways to structure a collection. The first is the summary page approach. You have a page, such as a category listing or a top ten roundup, that shows short teasers for several items. Each teaser links to a separate page with the full content. The ItemList on the summary page contains one entry per item, and each entry holds only a position and the URL of the item's own page. The detailed markup lives on those item pages.
The second is the all-in-one-page approach, where a single page holds the complete content for every item and there are no separate item pages. In that case the list entries point at anchors within the same page, and the detail for each item sits on that one URL. Google has documented both patterns, but the documentation states which content types work with which, so check the current carousel guidance for your type rather than assuming both are open to you.
For most sites the summary page pattern is the natural one, because most collections really do have separate pages: a category of recipes, a catalogue of courses, a directory of restaurants. Forcing an all-in-one structure onto content that already has individual URLs tends to create a long page and dilutes the signals that the individual pages would have carried.
One rule applies to both: the list has to reflect something a visitor can actually see. If the ItemList names ten items, those ten items should be visible on the page, in roughly that order, with links a person can click. Markup describing a list that does not exist on the page is the kind of mismatch that gets structured data ignored.
Which Content Types Can Appear in a Carousel
The carousel feature is not open to any item you can think of. Google documents it for a short list of types, and the list has been described as a beta feature, so it can change. At the time of writing, the documented types are courses, movies, recipes and restaurants. Confirm the current list in Google's carousel documentation before building anything, because eligibility is decided by that page and not by this article.
The type matters in two ways. First, every item in one list should be the same type. A carousel of recipes should contain recipes only, and mixing a recipe, a course and a restaurant into one ItemList makes the list ambiguous. Second, each destination page must carry valid markup for that type. A summary page full of links to recipe pages is only useful if those pages are themselves valid Recipe pages.
If your content is not one of the supported types, ItemList on its own will not produce a carousel. You can still add it, since it is valid schema.org and describes the page honestly, but treat it as descriptive markup with no promised visual result. Do not rewrite content to fit a supported type for the sake of a carousel. A product category is not a restaurant, and pretending otherwise is a misrepresentation that invites a manual action for spammy structured data.
Anatomy of a Valid ItemList
The markup has three layers. The outer object is an ItemList. Inside it is an itemListElement array. Each member of that array is a ListItem with a position number and a url. That is the whole requirement on the summary page. Below is the shape, written in JSON-LD, which is the format Google recommends.
{ "@context": "https://schema.org", "@type": "ItemList", "itemListElement": [ { "@type": "ListItem", "position": 1, "url": "https://example.com/recipes/lentil-soup" }, { "@type": "ListItem", "position": 2, "url": "https://example.com/recipes/tomato-soup" } ] }
Several details matter. Positions start at one and increase without gaps, and they should match the visible order. The urls are absolute, canonical addresses of the item pages, not redirects and not URLs with tracking parameters. Every url in the list must be unique. And the url should be the page that carries the item's own structured data, because Google reads the destination to understand what the card represents.
Notice what is absent. The summary page does not need to repeat the recipe's ingredients, the course's provider or the movie's director inside the list. Keep the summary page lean, because duplicating full markup for every item onto the list page creates a large block of data that has to be kept in sync with the real pages. If the two drift apart, you have created a consistency problem for no benefit.
Common Implementation Errors
Most failures fall into a handful of patterns. They are worth checking in order, because the first few account for the majority of invalid lists and none of them need anything more than a careful read of your own source.
- Every item pointing at the same URL. A template bug that outputs the current page URL, or a fixed fallback, for each ListItem. The list then contains duplicates and the destinations are meaningless.
- Positions that repeat, skip, or start at zero. A loop counter that begins at zero is the classic cause. Start at one and keep the sequence continuous.
- Item URLs that redirect or are non-canonical. Linking to a parameterised or redirecting address means the destination Google evaluates is not the URL you declared. Use the final canonical address.
- Mixed content types in one list. Recipes alongside articles, or courses alongside category pages, break the assumption that the list is a uniform set of items.
- Markup for content that is not on the page. An ItemList describing items hidden behind tabs that never load, or injected only for crawlers, does not match what visitors see.
- Missing or invalid markup on the destination pages. The summary page can be perfect and still get nothing, because the item pages themselves are not eligible for their type.
- Malformed JSON. A trailing comma, an unescaped quote in a title, or a curly quote pasted from a document will invalidate the whole block, and a whole-block failure often shows up as no detected items rather than a helpful message.
Pagination, Filters and Long Lists
Real collection pages are rarely a tidy list of ten. A category may run across several paginated pages, and a listing may be filterable by cuisine, level or price. Each situation raises a question about what to mark up.
For pagination, the conservative approach is to mark up only the items actually shown on each page, with positions that reflect that page or continue the overall count consistently. Do not try to list the entire catalogue on page one inside markup while the visible page shows twenty items. Keep the markup honest: it describes what this URL displays.
For filters, avoid producing a new ItemList for every filter combination if those combinations are not pages you want indexed. If the filtered view is a crawlable, canonical page in its own right, it can carry its own list. If it is a parameter variation that canonicalises back to the main listing, the markup should be treated the same way as the page itself, and the canonical declaration is what decides which version Google considers.
Client-side rendering adds a wrinkle. If your list is generated by JavaScript after load, the JSON-LD has to be present in the rendered HTML that Google processes. That is usually fine, but it is worth confirming with a rendered-page test rather than assuming, particularly when the list arrives from an API after a delay.
Testing and Monitoring Your Carousel Markup
Start with the Rich Results Test. Enter the summary page URL or paste the code, and look at which items it detects. A correctly formed list is reported as a carousel with the expected number of items. If it reports zero, read the warnings about missing fields first, then check the raw JSON for syntax problems. The Schema Markup Validator is useful as a second opinion on general schema.org correctness, though it does not judge Google's specific eligibility rules.
Then test the destinations. Run the Rich Results Test on a few of the item pages as well, since the carousel depends on them. Checking one or two per template is usually enough, because errors tend to come from the template and appear on every page that uses it.
After deployment, Search Console reports structured data by type, and supported carousel types show up under their own enhancement reports. Watch for new errors after template changes, which is when lists most often break. Remember that a valid report means the markup is readable, not that a carousel will appear. Google decides per query and per searcher whether to show one, and you cannot force it.
Finally, expect a delay. After fixing markup, the pages must be recrawled before anything changes in the reports. Requesting indexing for the summary page can speed that up, but patience is part of the process.
A Pre-Launch Checklist
Before you ship a summary page with ItemList markup, run through the decisions in order. Each one is quick, and together they catch most of the problems described above.
- Confirm your content type is on the current supported list in Google's carousel documentation.
- Decide between summary page and all-in-one page, and default to the summary page when items have their own URLs.
- Make every ListItem carry a continuous position starting at one and a unique, canonical, absolute url.
- Keep the list uniform: one content type per ItemList.
- Verify that each destination page has valid markup of its own for that type.
- Ensure the listed items are visible on the page in the same order as the markup.
- Validate the JSON, then run the Rich Results Test on both the summary page and a sample of item pages.
- Monitor the Search Console enhancement reports after launch and after every template change.
Frequently asked questions
Does ItemList markup guarantee a carousel in search results?
No. It makes a summary page eligible for supported content types, but Google decides whether to show a carousel for a given query. Valid markup is necessary, not sufficient.
Do I need to repeat full Recipe or Course data inside the ItemList?
No. On a summary page each entry needs a position and the URL of the item page. The detailed markup belongs on the item pages themselves, where it describes the content people see there.
Can I use ItemList for product category pages?
You can add it as descriptive markup, since it is valid schema.org. But do not expect a carousel unless your content type appears in Google's current carousel documentation, and do not relabel products as another type to qualify.
Should the markup be JSON-LD?
JSON-LD is the format Google recommends, and it is the easiest to generate from a template and to keep out of the visible HTML. Microdata and RDFa can express the same structure, but they are harder to maintain.