URL and title patterns
5 min read
The step URLs and titles of the task editor builds each page's address and title from the row's data. It has three fields: Parent path, Page URL and Page title. Each is a template: plain text with {{ variables }} in it.
The three fields
Field | Help text in the editor | Example |
|---|---|---|
Parent path | "Optional folder in front of every page, e.g. “cities” or “{{ pseo.src.cities.country }}”." |
|
Page URL | "Must be different for every page — usually a name column. Converted to a clean, lowercase URL." |
|
Page title | "Used as the page heading and in search results. Leave empty to use the URL." |
|
The final path is parent path + page URL. With the examples above, the row Lyon becomes /guides/lyon/, titled "Best hotels in Lyon".
All three accept up to 500 characters; line breaks are removed.
Variables
Variable | Meaning |
|---|---|
| A column of the page's row ( |
| In combination mode, the second use of the same source ( |
| The language code of the page (multilingual tasks), otherwise empty. |
| The generated page itself. Available in page content, SEO templates and structured data, not inside the URL and title patterns (they are what those patterns produce). |
Click a variable chip under the field to insert the variable into the field you edited last.
Filters and functions
Variables can be shaped with filters after a pipe: {{ pseo.src.cities.name | upper }}. The ones you will use most:
Filter | Example | Result for |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Others include trim, join, length, count, first, last, date and if_empty. An unknown filter name does nothing (the value is passed through unchanged), so a typo such as number_format silently prints the raw value.
Functions are written with the fn. prefix: {{ fn.year() }} prints 2026, {{ fn.now() | date("Y") }} too, {{ fn.if(pseo.src.cities.summary, "has", "none") }}. Without the prefix a function prints nothing.
An unknown column or an empty value resolves to an empty string.
How a URL is cleaned
The path is built in this order and every segment is cleaned like a WordPress slug:
Step | Example |
|---|---|
Parent path and URL are resolved and joined |
|
Split at |
|
Each segment: lowercase, accents removed, spaces and symbols become |
|
Empty segments are dropped |
|
Results from the test data:
Value | Path |
|---|---|
|
|
|
|
|
|
|
|
Things to know:
- Slashes in data create folders. If a column can contain
/, filter it:{{ pseo.src.cities.name | slug }}giveskoln-cologne. - Lowercasing before cleaning can leave encoded characters. For example
{{ pseo.src.cities.name | lower }}onİstanbulproducesi%cc%87stanbul(a combining dot). Use the plain value or| sluginstead of| lowerin URLs; the URL cleaning already lowercases. - A path longer than 512 characters gives no page for that row.
- An empty result gives no page. A row whose URL pattern resolves to nothing (for example an empty
summaryused as the slug) is skipped silently. The preview shows how many pages result. - Case and trailing slash do not matter when visiting.
/guides/LYONand/guides/lyon/both show the page. Generated URLs, canonical URLs and sitemaps use the lowercase form with the site's trailing-slash setting. Paged requests (/guides/lyon/page/2/) are not served. - The path of the template page itself is separate and stays what it is.
Titles
The title is the page heading (the template's title is replaced by it) and the starting point of the SEO title. It is resolved as plain text: HTML in data is stripped. An empty title falls back to the last URL segment with dashes turned into spaces and capitalized (new-york-city → New York City).
You can change the title of single pages by hand in the page editor and the next run keeps it.
Duplicates
Two rows that resolve to the same URL cannot both have a page. The first row (lowest row ID) keeps the URL, the others get no page, and the run reports them: "1 row skipped: another generated page uses its URL." In the test table two rows named Lyon (France and Canada) produced one page and one skipped row. The task's SEO health also warns: "1 row got no page because its URL is already used by another generated page."
Fix it by making the URL unique: add a second column, for example {{ pseo.src.cities.name }}-{{ pseo.src.cities.country }}.
Changing a pattern later
When you change the URL pattern (or a row's data changes a URL) and run the task:
- the page keeps its identity and moves to the new URL;
- the old URL answers
301and redirects to the new one (status Moved); - a URL that you changed by hand for a page is kept; "Use generated" in the page editor brings the pattern's URL back at the next run.
Redirects from old URLs stay as long as the page exists.
Preview
Below the fields a Preview lists the first pages for the current settings: URL, title and flags. It shows "About 120 pages will be generated.", and warns when:
- "An existing post already uses this URL; it will be shown instead." (the generated page would be hidden, see Serving pages),
- "Your plan allows 4,880 more pages; generation stops there." (see Limits and plans).
Missing input is explained as "Choose the data and enter a page URL to see the first pages."
Still stuck? Contact support