> ## Documentation Index
> Fetch the complete documentation index at: https://algolia.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Generate a sitemap from an Algolia index

> Learn how to generate sitemaps from your Algolia indices dynamically.

export const Records = () => <Tooltip tip="A record is a searchable object in an Algolia index. Each record consists of named attributes." cta="Algolia records" href="/doc/guides/sending-and-managing-data/prepare-your-data#algolia-records">
    records
  </Tooltip>;

export const Index = () => <Tooltip tip="An Algolia index is a searchable dataset that consists of records and configuration settings. These settings define how the records are searched and ranked.">
    index
  </Tooltip>;

export const Application = () => <Tooltip tip="An Algolia application is a self-contained environment with its own indices, configuration, and API keys. Applications don't share data or settings with each other.">
    application
  </Tooltip>;

A [sitemap](https://www.sitemaps.org/index.html) is an XML file that describes all pages of your website that are available for crawling by a search engine.
Sitemaps contain the URLs of your pages along with metadata,
such as when a page was last updated,
how often a page is updated,
or how important a page is relative to other pages.
Sitemaps play a significant role in search engine optimization (SEO),
especially when you're using Algolia in your frontend.

Because facets are flexible, Algolia can power navigation in addition to search results pages,
which lets you implement dynamic category pages based on the data in your <Index />.
These are great candidates to add to your sitemap.

## Before you begin

This tutorial assumes that you installed [Node.js](https://nodejs.org/en/) in your environment,
and you understand how to create and run Node.js scripts.

You also need an Algolia account. If you don't have one already,
you can [create an account](https://dashboard.algolia.com/users/sign_up) for free.

### Dataset

For this tutorial, you'll use an ecommerce dataset where each result is a product.
All <Records /> have a `categories` attribute with one or more categories.

[Download the dataset](https://github.com/algolia/datasets/blob/master/ecommerce/bestbuy_seo.json) and import it into your Algolia <Application />.
For more information, see [Import with the dashboard](/doc/guides/sending-and-managing-data/send-and-update-your-data/how-to/importing-from-the-dashboard).

### Install dependencies

Install the [`algolia-sitemap`](https://github.com/algolia/algolia-sitemap) as a dependency.
This helper library lets you dynamically generate sitemaps from your Algolia indices.

```sh Command line icon=square-terminal theme={"system"}
npm install algolia-sitemap
```

## Create a sitemap of all the records in your index

First, create a sitemap with all your products to let search engines know where to find them.
You need your Algolia application ID and your [API key](https://dashboard.algolia.com/account/api-keys/).
The API key must have [`browse` permission](/doc/guides/security/api-keys#access-control-list-acl).

```js JavaScript icon=code theme={"system"}
// sitemap.js
const sitemap = require("algolia-sitemap");

// You need an API key with `browse` permission
const algoliaConfig = {
  appId: "ALGOLIA_APPLICATION_ID",
  apiKey: "ALGOLIA_API_KEY",
  indexName: "YourIndexName",
};

sitemap({
  algoliaConfig,
  // ...
});
```

To the `sitemap` function, you need to add a `hitsToParams` callback function.
This function turns a record from your index into a sitemap entry.
The return value of the `hitsToParams` function must be an object with attributes
that match an `<url>` entry of a sitemap file:

* `loc` (required): the URL of the page for the record
* `lastmod`: the last modified date (ISO 8601)
* `priority`: the priority of this page compared to other pages on your site (between 0 and 1)
* `changefreq`: describes how often the page is likely to change
* `alternates`: alternate versions of this link
* `alternates.languages`: an array of enabled languages for this link
* `alternates.hitToURL`: a function that transforms a language into a URL

To learn more, see [Sitemaps XML format](https://www.sitemaps.org/protocol.html).

In this tutorial, you'll create a simple sitemap, only specifying the `loc` attribute.

```js JavaScript icon=code theme={"system"}
// sitemap.js
// Turn a record into a sitemap entry
function hitToParams({ url }) {
  return { loc: url };
}

sitemap({
  algoliaConfig,
  hitToParams,
  // The URL of the sitemaps directory
  sitemapLoc: "https://example.com/sitemaps",
  // The directory with all sitemaps (default: `sitemaps`)
  outputFolder: "sitemaps",
});
```

In your project directory, create a `sitemaps/` directory.
Now, you can run the `sitemap.js` script:

```sh Command line icon=square-terminal theme={"system"}
node sitemap.js
```

The `/sitemaps` directory now has two types of files:

* The `sitemap-index.xml` file with links to each sitemap file
* The `sitemap.0.xml` file with links to your products

You can validate your sitemaps with [external tools](https://www.xml-sitemaps.com/validate-xml-sitemap.html).
To inspect the sitemap, you can use a tool like [`xmllint`](https://xmllint.com/).

```sh Command line icon=square-terminal theme={"system"}
xmllint --format sitemaps/sitemap.0.xml
```

## Create a sitemap for categories

You should add your category pages to the sitemap.
If you're using the sample dataset, use the `categories` attribute for the URL:

```json JSON icon=braces theme={"system"}
{
  "categories": ["Mobile Phones", "Phones & Tablets"]
}
```

In this example, the product belongs to two categories.
Usually, category pages have URLs like the following: `https://example.com/{CATEGORY_NAME}`.

You need to modify the `hitToParams` callback function to return an array of all categories that belong to a given record.
Since categories apply to many records, you need to make sure to add them to your sitemaps only once.
With ES6, you can use a [`Set`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set).

```js JavaScript icon=code theme={"system"}
// sitemap.js
// Turn categories into sitemap entries
const alreadyAdded = {};

function hitToParams({ categories }) {
  const newCategories = categories.filter(
    (category) =>
      category !== null && category !== undefined && !alreadyAdded[category],
  );

  if (!newCategories.length) return;

  const locs = newCategories.map((category) => {
    alreadyAdded[category] = category;
    return { loc: `https://example.com/${encodeURI(category)}` };
  });

  return locs;
}
// ...
```

Check each record to see if it contains categories that you didn't yet add to the sitemap, and add them.
This lets you save all your category pages to your sitemap.

## Create a sitemap for categories and all records

You can modify the code for adding category pages to your sitemap to create a combined sitemap for both records and categories.

```js JavaScript icon=code theme={"system"}
// sitemap.js
// ...
function hitToParams({ categories, url }) {
  const newCategories = categories.filter(
    (category) =>
      category !== null && category !== undefined && !alreadyAdded[category],
  );

  if (!newCategories.length) return;

  const locs = [];

  newCategories.forEach((category) => {
    alreadyAdded[category] = category;
    alreadyAdded[url] = url;

    locs.push(
      ...[{ loc: `https://example.com/${encodeURI(category)}` }, { loc: url }],
    );
  });
  return locs;
}
// ...
```

## Notify search engines of sitemap changes

Finally, you can let search engines know that your sitemap has changed.
Most search engines have a `ping` mechanism to inform them of a new sitemap,
so you can perform this directly from your script.

```js JavaScript icon=code theme={"system"}
const endpoints = [
  "http://www.google.com/webmasters/sitemaps/ping?sitemap=http://example.com/sitemap.xml",
  "http://www.bing.com/webmaster/ping.aspx?siteMap=http://example.com/sitemap.xml",
];

Promise.all(endpoints.map(fetch)).then(() => {
  console.log("Done");
});
```

For more information, see:

* [Submit your sitemap to Google](https://developers.google.com/search/docs/crawling-indexing/sitemaps/build-sitemap)
* [Bing sitemaps](https://www.bing.com/webmasters/help/Sitemaps-3b5cf6ed)
