Спутник к В свойствах PDF должен значиться ваш бренд, а не чужой инструмент — та статья обосновывала, почему вообще стоит заботиться о метаданных PDF. Эта — рабочее руководство: для чего каждое поле в спецификации PDF, кто его читает, типичные ошибки и как убедиться, что ваш вывод действительно отгрузил то, что вы задумали.
gPdf экспонирует шесть стандартных полей, которые спецификация PDF определяет для метаданных уровня документа. Они живут под settings.metadata в JSON DocumentRequest. Каждое поле опционально — если вы его не задаёте, gPdf откатывается либо на default_metadata токена (фича Enterprise-политики), либо на системный default.
{
"settings": {
"metadata": {
"title": "...",
"language": "...",
"author": "...",
"subject": "...",
"creator": "...",
"producer": "..."
}
}
}
Дальше — по разделу на каждое поле. Каждый раздел следует одной форме: что это за поле, где оно всплывает, типичные ошибки, правило большого пальца. Порядок — что заполнять в первую → во вторую → … → в последнюю очередь.
title — что это за документ
Спецификация PDF описывает это как «заголовок документа».
Где всплывает:
- Заголовок окна в просмотрщиках PDF (Adobe Reader, Preview, Foxit, PDF-просмотрщик Chromium — все его показывают).
- Вкладка браузера, когда PDF открывается inline (
Content-Disposition: inline). - Индексы поиска — Spotlight, Outlook, SharePoint, full-text индексатор Google Drive — все читают
titleи придают ему большой вес.
Типичные ошибки:
- ❌ Делать title равным имени файла.
invoice-20260318.pdf— это имя файла. Title должен быть тем, что читает человек, напримерInvoice INV-2026-3401. Имя файла и title — разные вещи; имя файла для файловых систем, title — для просмотрщиков и поиска. - ❌ Оставлять title пустым. Просмотрщики откатываются на имя файла. Результат читается как автосгенерированный и машинно-выданный.
- ❌ Добавлять бренд в title.
Acme Logistics — Invoice INV-2026-3401захламляет заголовок окна. Бренду место вauthor, а не вtitle.
Правило большого пальца: title должен совпадать с H1 отрисованной страницы. Если верхняя строка вашего шаблона счёта — «Invoice INV-2026-3401», это и есть title.
language — для доступности, поиска и комплаенса
language — это языковая метка BCP-47: en, de, zh-Hans, pt-BR, ar-SA. Задавайте её для каждого документа. Из шести полей у него самые конкретные downstream-последствия при наименьшей стоимости внедрения — поэтому оно на позиции 2, а не закопано ниже.
Где всплывает:
- Скринридеры — JAWS, NVDA, VoiceOver используют её, чтобы выбрать правильный набор фонем. Английский скринридер, читающий PDF с
language: "de", будет корректно произносить немецкие слова; без метки просодия выходит неправильной. - Поисковые системы и индексаторы — влияет на то, какие правила стемминга и список стоп-слов локали применяются. Счёт с
language: "zh-Hans"индексируется с китайской сегментацией; отсутствие метки часто откатывается на английский, и индекс становится непригоден. - Соответствие PDF/A — PDF/A-2a и PDF/A-3a (профили доступности) требуют языковую метку. Без неё валидация veraPDF проваливается.
Типичные ошибки:
- ❌ Оставлять незаданным. По умолчанию используйте «локаль получателя», а не «default платформы». Большинство «протекающих» стеков просто не пишут это поле; результат — скринридеры, которые произносят неправильно, и поисковые индексы, которые неправильно стеммируют.
- ❌ Использовать строку не по BCP-47 вроде
"english"или"EN-US". Спецификация PDF ожидает теги RFC 5646:en,en-US,de,pt-BR. - ❌ Жёстко зашивать default платформы (например, всегда
"en") без учёта реального языка содержимого документа. Счёт на португальском, помеченный как"en", хуже непомеченного — он активно вводит индексатор в заблуждение.
Правило большого пальца: метка должна совпадать с реальным языком содержимого. Для клиента в Бразилии, получающего счёт на португальском, задайте "language": "pt-BR", а не "en". Для многоязычных документов выберите доминирующий язык и используйте атрибут Lang на отдельных элементах содержимого для остального — это фича доступности tagged-PDF, отдельная от поля language уровня документа.
author — кому принадлежит документ
В спецификации PDF author — это «имя человека или организации, создавшей документ». Для бизнес-PDF, отгружаемых получателям, ответ почти всегда — организация — но правильная форма реально зависит от контекста.
Где всплывает:
- Диалог свойств в каждом просмотрщике PDF, заметно подписанный как «Author».
- Индексаторы DMS / архивов, часто используется как фильтр.
- XMP-поток метаданных PDF/A, где он переносится в долгосрочные архивы.
Типичные ошибки:
- ❌
"author": "[email protected]"— случайно сливает почту оператора в каждый PDF, попадает в каждый поисковый индекс, становится долгосрочной PII-проблемой. - ❌
"author": "PDF Generator Service"— внутреннее имя инструмента; ничего не значит для получателя. - ❌ Пусто — Preview и большинство просмотрщиков буквально показывают «(no author)» в диалоге свойств, что читается как «никому не принадлежит».
Формы, которые работают:
- ✅
"author": "Acme Logistics, Inc."— простая организация. - ✅
"author": "Acme Logistics — Billing"— организация + отдел, для документов, идущих на конкретный стол. - ✅
"author": "Bridge Capital Partners — Fund III"— полезно в финансах/юриспруденции, где атрибуция к конкретной сущности. - ✅
"author": "Maria López, RICS Surveyor"— для одноавторных публикаций (отчётов, оценок, юридических заключений), где личность ЕСТЬ редакционная атрибуция.
Правило большого пальца: author — сущность, с которой получатель должен ассоциировать документ. В multi-tenant SaaS, где платформа генерирует PDF от имени клиентов, author должен быть именем организации клиента, а не именем платформы. (Имя платформы место в creator — см. ниже.) Для консалтинговых / издательских / юридических контекстов, где личности и есть бренд, личности подходят.
subject — какого типа этот документ
subject — это краткое-описание-документа. Просмотрщики не выводят его на видное место — большинство пользователей никогда его не увидят, если не откроют диалог свойств. Но системы документооборота, архивные системы и правило-ориентированный роутинг почты/файлов им пользуются.
Где всплывает:
- Диалог свойств, вторичная позиция.
- Правила роутинга DMS, логика бакетинга в архиве.
- XMP-поток метаданных (PDF/A).
Типичные ошибки:
- ❌
"subject": "Invoice for Acme on 2026-03-18 for $4,532.10"— это описание экземпляра документа, а не типа. Место — вtitle. - ❌ Пусто — теряете бесплатный «крючок» для роутинга downstream-системами.
- ❌ Мешать классы непоследовательно (
"Invoice"vs"Invoice/2026-03"vs"Monthly invoice") — фильтры DMS не могут бакетить по движущейся цели.
Формы, которые работают:
- ✅
"subject": "Invoice" - ✅
"subject": "Monthly account statement" - ✅
"subject": "Shipping label — 4×6 thermal" - ✅
"subject": "Q3 2026 board pack"
Правило большого пальца: правильная гранулярность — класс документа, а не экземпляр. DMS с тысячами входящих PDF может роутить по subject, если вы дадите ему стабильный словарь. Выберите конечное множество классов для своей платформы и никогда не отклоняйтесь — каждый счёт, который генерирует ваша платформа, должен иметь ровно "subject": "Invoice".
creator vs producer — самая часто путаемая пара
Здесь большинство команд перестаёт читать спецификацию PDF и начинает гадать. Спецификация точна; два поля означают разное.
creator— приложение, произведшее исходный контент (upstream-система, решившая, что должно быть в документе).producer— приложение, произведшее байты PDF (рендеринг-движок, превративший этот контент в PDF-файл).
Для биллинговой SaaS-платформы, генерирующей счета через JSON-to-PDF API вроде gPdf:
creator= биллинговая SaaS-платформа со своей версией. Это приложение решило, что это будет счёт Acme на $4 532,10.producer= рендерер. По умолчанию это «gPdf». Но поскольку слой рендеринга — это инфраструктура, выбранная SaaS, SaaS вправе выставитьproducerв имя собственной платформы — её платформа в реальном смысле произвела байты PDF, делегировав gPdf как инфраструктуре.
{
"creator": "Acme Billing Platform v7.2",
"producer": "Acme Billing Platform"
}
Где всплывают:
- Диалог свойств, оба подписаны.
- Вывод
pdfinfo, бок о бок. - XMP-поток PDF/A (в PDF/A оба поля должны быть непустыми).
Типичные ошибки:
- ❌
creatorвыставлен в строку user-agent Chromium / Mozilla. Случается, когда PDF-стек на headless-браузере автоматически прокидывает User-Agent вcreator. Это версия браузера, а не источник правды. Переопределите. - ❌
producerоставлен как имя дефолтного рендерера. Большинство команд никогда его не переопределяют, поэтому каждый PDF говорит «Skia/PDF m120» или «wkhtmltopdf» — см. статью про white-label, почему это важно в B2B. - ❌ Класть одно и то же значение в оба. Допустимо, но расточительно — два поля существуют именно для того, чтобы просмотрщик мог отличить «исходное приложение» от «рендеринг-движка». Используйте их.
Правило большого пальца: creator — имя вашего приложения с версией (например, "Acme Billing Platform v7.2"); producer — бренд или имя платформы без версии (например, "Acme Billing Platform"). Оба должны быть значениями, которые получатель узнал бы.
Пустые поля, per-token defaults, downstream-сюрпризы
Три детали реализации, которые стоит знать перед отгрузкой:
- Пустые строки или строки только из пробелов трактуются как не переданные. Отправить
"title": ""— то же, что не указатьtitle— это не пишет пустую строку в PDF, а проходит цепочку фолбэка (default токена → default системы). Это причина наиболее распространённого отчёта о баге «я задал, не сработало». - Политики токена могут вырезать или дефолтить поля метаданных. Multi-tenant SaaS, использующий gPdf, может задать
default_metadataдля каждого API-токена, чтобы каждый PDF, генерируемый этим токеном, нёсauthorиproducerклиента, не полагаясь на то, что каждый разработчик задаст их в каждом запросе. Дефолт на уровне токена — правильный слой принуждения для «каждый PDF Acme должен говорить Acme». - Downstream-пайплайны могут переписать ваши метаданные. Инструменты, постобрабатывающие PDF после возврата gPdf — Ghostscript без явных флагов сохранения метаданных, некоторые корпоративные DRM-инструменты, некоторые «оптимизаторы PDF» — могут перезаписать Producer собственным именем и отменить только что заданный брендинг. Проверяйте против реального production-пайплайна, а не только против сырого ответа gPdf.
Проверка ваших метаданных
После внедрения вышеописанных изменений три быстрых способа убедиться, что PDF действительно отгрузил задуманное:
Командная строка (macOS / Linux, требуется poppler-utils):
$ pdfinfo your-output.pdf | head -10
Title: Invoice INV-2026-3401
Subject: Monthly invoice — 2026-03
Author: Acme Logistics, Inc.
Creator: Acme Billing Platform v7.2
Producer: Acme Billing Platform
Language: en
Acrobat / Adobe Reader: Файл → Свойства → вкладка Описание. Все шесть полей появляются, Title показывается в заголовке окна просмотрщика наверху.
Preview на macOS: ⌘+I (Получить информацию). Панель инспектора «PDF» показывает те же поля.
Если какое-то поле появляется пустым, бланковым или с именем инструмента, которое вы не задавали, пройдитесь по телу запроса заново — самая частая причина — отправка "" (пустой строки), которую API трактует как «не передано» и проходит по цепочке фолбэка до значения по умолчанию. Вторая по частоте причина — downstream-пайплайн (Ghostscript, DRM, оптимизатор), переписывающий поле после возврата gPdf; тестируйте против production, а не только против сырого ответа рендера.
Метаданные в архивировании PDF/A
Если вы рендерите для долгосрочного архивирования с settings.profile: "pdfa-2b" (или -2a, -3a, -3b), метаданные перестают быть опциональными и становятся несущими:
- Поле
producerне может быть пустым в файле, соответствующем PDF/A — как минимум отгружается системный default. languageобязателен для профилей доступности (PDF/A-2a, PDF/A-3a). Без него валидация veraPDF проваливается напрямую.- XMP-поток метаданных, который требует PDF/A, генерируется автоматически из шести вышеперечисленных полей; вам не нужно конструировать его самостоятельно.
title,author,subject,creator,producerиlanguage— все попадают в XMP-поток, так что индексатор метаданных downstream-архива (Preservica, Archivematica) может строить свой каталог из них без повторного парсинга тела документа.
Для архивного документа брендированные метаданные — не просто полировка бренда, а часть долговечности артефакта. Немецкая таможня, бразильская налоговая или любой долгосрочный архив, который откроет ваш PDF через десять лет, увидит то, что было в этих полях в день рендера. Задать их явно во время рендера — единственный шанс, который у вас есть.
Чего gPdf (ещё) не экспонирует
Чтобы быть честным про текущую поверхность: спецификация PDF также определяет Keywords (свободные поисковые термины) и XMP-поток метаданных, поддерживающий произвольные пользовательские key-value пары. gPdf не экспонирует ни то, ни другое в текущем API.
Если вам нужно прятать произвольные бизнес-данные внутри PDF (UUID заказа, код склада, версию шаблона), сегодняшние обходные пути:
- Задавать
subjectв виде структурированной короткой строки, которую парсят downstream-системы. - Хранить бизнес-данные в собственной базе, индексированной по имени файла или хешу содержимого.
- Подождать — пользовательские поля XMP в roadmap, и когда они появятся, они будут правильным ответом для скрытого машино-читаемого контекста workflow.
Смешивать «брендированные метаданные» (шесть стандартных полей, доступных сейчас) с «пользовательскими бизнес-метаданными» (пользовательские поля XMP, в будущем) — самый простой способ переобещать то, что возможно сегодня. Стоит держать их раздельно в собственном планировании.
Полный пример
Биллинговая SaaS-платформа (Acme Billing Platform), генерирующая счёт для немецкого клиента (Müller Versand GmbH), готовая к архивированию как PDF/A:
{
"settings": {
"profile": "pdfa-3b",
"metadata": {
"title": "Rechnung RE-2026-0412",
"language": "de",
"author": "Müller Versand GmbH",
"subject": "Monatsrechnung — März 2026",
"creator": "Acme Billing Platform v7.2",
"producer": "Acme Billing Platform"
}
}
}
pdfinfo по получившемуся PDF:
$ pdfinfo invoice-2026-0412.pdf | head -10
Title: Rechnung RE-2026-0412
Subject: Monatsrechnung — März 2026
Author: Müller Versand GmbH
Creator: Acme Billing Platform v7.2
Producer: Acme Billing Platform
Language: de
Title на немецком, author — Müller Versand (GmbH-сущность клиента, получатель документа), creator — Acme Billing Platform (редакционная система, решившая, что положить на страницу), producer — бренд Acme Billing Platform, язык корректно помечен для немецкого скринридера и для немецкого full-text индексатора, который позже подхватит это в DMS Müller. Профиль PDF/A-3b означает, что этот набор метаданных также сериализуется в XMP-поток для долгосрочного архивирования.
Ничто в свойствах файла не называет gPdf, Chromium или какой-либо инструмент, который клиент не выбирал. Что и есть суть.
Минимально возможное улучшение
Если вы уже делаете POST на /api/v1/pdf/render, и в вашем текущем вызове нет settings.metadata, минимальное улучшение — три строки, добавленные в JSON, который вы уже отправляете:
{
"pages": [...],
"settings": {
+ "metadata": {
+ "author": "Your customer's organisation",
+ "producer": "Your platform"
+ }
}
}
Два поля, один новый ключ. Проверяется pdfinfo за секунды. После того как это приземлится, заполните title, language, subject и creator, когда будет время.
Где это приземляется
- §4.14.2 Metadata — API-справочник по этим полям.
- White-label PDF (статья-спутник) — почему и кейс B2B SaaS.
- PDF/A и Factur-X для инженеров — актуально, если ваша история метаданных включает долгосрочное архивирование.