
Short answer: Pimcore does not give your data objects a public RSS feed on its own, but a feed is a small Symfony controller away. List the published objects of your news class, newest first, map each one to an item with an absolute link, a stable identifier, a summary and a publication date, escape every value, return the RSS content type with a cache validator and test the live address. Then paste that address into an auto-poster, so that each new article reaches your social channels without anyone sharing it by hand.
Pimcore combines a content management system with digital asset management, product information and commerce, and it is built on Symfony. Editors work with documents, assets and data objects, and developers decide how each of them appears on the website. That freedom has a consequence for feeds. No component can guess how your pages are addressed or which class holds your news, so the feed is part of your own bundle or application code. This guide shows a controller, the choices that are specific to Pimcore, such as published state and link generators, and a test routine that catches the usual mistakes.
Most Pimcore projects keep articles in one of two places. Some use documents, which are pages in a tree with editables, and some use data objects, which are records of a class that you define with fields. For a feed, data objects are easier, because they have typed fields such as a title, a summary and a publication date, and a listing class can query and sort them. Documents also work, but you would read editable values one by one, and the result depends on how each template was built.
The examples below assume a class called NewsArticle with these fields: a title, a summary, a slug, a publication date and an optional image. Your class names and getters follow your own class definition, so check them in the class editor before you copy anything.
| Feed element | Source in Pimcore | Rule |
|---|---|---|
| Title | a text field of the class | Plain text, no markup |
| Link and identifier | the link generator or a slug field | Absolute, https, never changes |
| Publication date | a date field that you add | Set once by the editor |
| Description | a summary field | One or two complete sentences |
| Image | an image field with a thumbnail | Absolute address with type and size |
Every data object carries system dates, such as the creation date and the modification date. They describe what happened in the database, not what the editor intended. If someone corrects a typo and saves the object, the modification date moves, and a feed that used it would put the item at the top again. An auto-poster would see a new entry and share the article a second time. Add a date field to the class, let the editor fill it in once when the article goes live and use only that field in the feed. The causes of repeated posts are explained in why a feed auto-posts the same article twice.
The controller below extends the frontend controller that Pimcore provides, reads the published objects and builds the XML. Place it in your application and register the route in the way your project registers others.
<?php
// src/Controller/FeedController.php
namespace App\Controller;
use App\Model\DataObject\NewsArticle;
use Pimcore\Controller\FrontendController;
use Pimcore\Model\DataObject;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
class FeedController extends FrontendController
{
private const SITE = 'https://example.com';
#[Route('/feed.xml', name: 'site_feed', methods: ['GET'])]
public function feed(Request $request): Response
{
DataObject::setHideUnpublished(true);
$list = new NewsArticle\Listing();
$list->setOrderKey('publishDate');
$list->setOrder('DESC');
$list->setLimit(20);
$items = '';
$newest = null;
foreach ($list as $article) {
$date = $article->getPublishDate();
if ($date === null) {
continue;
}
$newest = $newest ?? $date;
$url = self::SITE . '/news/' . $article->getSlug() . '/';
$items .= '<item>'
. '<title>' . $this->x($article->getTitle()) . '</title>'
. '<link>' . $this->x($url) . '</link>'
. '<guid isPermaLink="true">' . $this->x($url) . '</guid>'
. '<pubDate>' . $date->format(DATE_RSS) . '</pubDate>'
. '<description>' . $this->x($article->getSummary()) . '</description>'
. '</item>';
}
$xml = '<?xml version="1.0" encoding="UTF-8"?>'
. '<rss version="2.0"><channel>'
. '<title>Example Journal</title>'
. '<link>' . self::SITE . '</link>'
. '<description>News and guides from Example Journal.</description>'
. '<lastBuildDate>' . ($newest ? $newest->format(DATE_RSS) : gmdate(DATE_RSS, 0)) . '</lastBuildDate>'
. $items
. '</channel></rss>';
$response = new Response($xml, 200, ['Content-Type' => 'application/rss+xml; charset=utf-8']);
$response->setEtag(sha1($xml));
$response->setPublic();
$response->setMaxAge(300);
$response->isNotModified($request);
return $response;
}
private function x(?string $value): string
{
return htmlspecialchars((string) $value, ENT_XML1 | ENT_QUOTES, 'UTF-8');
}
}The listing hides unpublished objects, so a draft never reaches the feed. The channel date comes from the newest article and not from the clock, so the file stays identical when nothing was published and the validator does not change. The escape function matters because a single ampersand in a title would otherwise make the whole document invalid. See why special characters break feeds.
The example builds the address from a constant and a slug, which is simple and works for many sites. Pimcore also lets a class define a link generator, a service that turns an object into the address of its page. If your site uses one, call it in the feed, so that the page and the feed can never disagree about a path. A mismatch is a quiet problem. The feed shows an address that redirects or returns a missing page, and social networks display an empty preview.
Always output absolute addresses with the https scheme. Relative paths work in a browser, but an auto-poster that reads the feed has no page to resolve them against. If the site runs on several domains, choose one canonical domain for the feed and keep it fixed.
The controller sets the content type, a public cache lifetime of five minutes and an ETag that is a hash of the finished document. When a client sends the same value back, the call to isNotModified turns the answer into a 304 status with no body. This saves work for your server and for every tool that polls the feed. The mechanism is described in the guide to ETags and conditional requests, and the meaning of each status in the guide to feed status codes.
If your project uses Pimcore’s output cache or a reverse proxy, check that it respects these headers and that a published article clears the cached feed. Otherwise the feed may lag behind the website by hours, and readers will notice that your social posts arrive late. Background on this problem is in why auto-posted content sometimes lags.
Pimcore projects often serve several languages or several sites from one installation. Build one feed per language and per site, each with its own address and its own channel title. Pass the locale to the getters, so that the title and the summary come from the right language. A feed that mixes translations makes an auto-poster share the same story several times in different languages, and followers see that as spam. If your sites share a class, add a condition to the listing that selects objects for the current site. See the guide to multilingual feeds for more on this.
An auto-poster builds a better post when the entry has a picture. If your class has an image field, add an enclosure with an absolute address, a MIME type and a length in bytes. Pimcore can generate thumbnails from a named configuration, so create one for social use at a size that suits the networks, and reference its public address in the feed. Do not point to the original upload, because it may be several megabytes and may be in a format that social networks refuse. Tell editors that the image is part of the article and not decoration, and make the field required if you want every post to have one.
A feed is a public address that anyone can call, so keep it light. Limit the listing to twenty items, ask only for the fields you need and avoid loading related objects, because each relation adds a query. Do not expose internal notes, editor comments or fields that you use for workflow. If a class stores private data next to public text, write the mapping by hand, field by field, instead of looping over everything the object contains. Finally, log failures. A feed that returns an error for an hour at night is easy to miss, and the first sign may be that your social channels stay silent for a day.
Request the route on your development environment and then on the live address, because only the live address passes through your hosting, your certificate and any proxy in front of it.
curl -i https://example.com/feed.xml
curl -i -H 'If-None-Match: "paste-the-etag-here"' https://example.com/feed.xmlA longer routine is in the feed validation guide, and a shorter one in debugging a feed with curl.
PostRSS has been publishing RSS and Atom feeds to social networks since 2014. Paste the address of your feed, connect your accounts and choose how each post is built from the title, the description or the page title. PostRSS checks the feed as often as every minute and shares each new entry, with its image and link, to the channels you choose among 66 supported networks, messengers, team chats and blogs, including LinkedIn, X, Bluesky, Mastodon and Telegram. Keyword filters, UTM parameters and posting windows let you tune each channel. See the PostRSS features page and the plan limits on the pricing page. More developer guides are under the Technical Guide tag.
A Pimcore feed is a short controller that you own. List the published objects of your news class, sort them by a publication date that editors set once, build absolute links from a slug or a link generator, escape the text, send the correct content type and a validator, and test the live address. Keep one feed per language and refresh the cache when an article goes live. Once the address is stable, connect it to an auto-poster, and every article your editors publish reaches your readers and your social channels without extra work.
No. Pimcore leaves the public output to your own code, so you write a controller that reads the objects of your class and builds the feed from them.
A date field that your editors fill in once when the article goes live. System dates change when an object is saved again, and that can make an auto-poster share the article twice.
Hide unpublished objects in the listing before you query it, then check on the live address that a draft does not appear.
Yes. Create one route for each language, site or category, each with its own address and channel title, so that every audience receives the right posts.
Yes. PostRSS reads any valid RSS or Atom address that is reachable without a login. Paste the address, connect your channels and new articles are shared as soon as they appear.
What changed in the networks, what broke, and how to fix it before it costs you reach.
Створено Internet Solutions — командою PostRSS. Кожен продукт заощаджує ваш час по-своєму.