Skip to content

Set document metadata (title, author, language)

Set the Portable Document Format (PDF) metadata fields: title, author, subject, keywords, and creator. Set the document language in the same flow. These fields populate the document information and the document-level metadata. PDF readers show this data in their “Properties” panel, and search and cataloging tools can index it. This recipe follows examples/16-metadata.php.

Terminal window
composer require nextpdf/core:^3

Metadata is general information about a document (ISO 32000-2 §14.3). PDF 2.0 stores it in two places: the legacy document information dictionary and a document-level Extensible Metadata Platform (XMP) metadata stream. In PDF 2.0, most information-dictionary fields, including Author, are explicitly optional and deprecated in favor of XMP.

The HasMetadata setters update the engine’s metadata model, and the writer emits the matching entries. setLanguage() sets the catalog /Lang, which assistive technology uses. The profile is structural because the document carries a trailer /ID and a metadata date. The post-pass normalizes both before comparing two runs.

NextPDF\Core\Concerns\HasMetadata (mixed into Document):

  • setTitle(string $title): static
  • setAuthor(string $author): static
  • setSubject(string $subject): static
  • setKeywords(string $keywords): static
  • setCreator(string $creator): static
  • setLanguage(string $lang): static — Best Current Practice (BCP) 47 tag (en, zh-Hant-TW, ja)
  • isTaggedPdfEnabled(): bool — read-only accessor for the active tagged mode
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->setTitle('Quarterly Report Q1 2026');
$doc->setAuthor('Reporting Team');
$doc->setSubject('Financial summary');
$doc->setKeywords('finance, quarterly, report');
$doc->setCreator('NextPDF Core');
$doc->setLanguage('en');
$doc->addPage();
$doc->setFont('helvetica', '', 12);
$doc->cell(0, 10, 'See File > Properties for the metadata.', newLine: true);
$doc->save(__DIR__ . '/with-metadata.pdf');
echo "Wrote with-metadata.pdf\n";

The full example below mirrors examples/16-metadata.php and writes to NEXTPDF_COOKBOOK_OUTPUT for the harness.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$metadata = [
'Title' => 'NextPDF Metadata Example',
'Author' => 'NextPDF Documentation Team',
'Subject' => 'Demonstrating PDF 2.0 document metadata fields',
'Keywords' => 'nextpdf, pdf, metadata, document-properties, php',
'Creator' => 'NextPDF Core v3.0',
'Language' => 'en',
];
$doc = Document::createStandalone();
$doc->setTitle($metadata['Title']);
$doc->setAuthor($metadata['Author']);
$doc->setSubject($metadata['Subject']);
$doc->setKeywords($metadata['Keywords']);
$doc->setCreator($metadata['Creator']);
$doc->setLanguage($metadata['Language']);
$doc->addPage();
$doc->setFont('helvetica', 'B', 20);
$doc->cell(0, 14, 'Document Metadata', newLine: true);
$doc->ln(4);
$doc->setFont('helvetica', '', 11);
$doc->cell(0, 8, 'The following fields are embedded in this PDF.', newLine: true);
$doc->cell(0, 8, 'Open File > Properties in your reader to verify.', newLine: true);
$doc->ln(6);
$doc->setFont('helvetica', 'B', 11);
$doc->cell(40, 9, 'Field', border: true);
$doc->cell(0, 9, 'Value', border: true, newLine: true);
foreach ($metadata as $field => $value) {
$doc->setFont('helvetica', 'B', 10);
$doc->cell(40, 9, $field, border: true);
$doc->setFont('helvetica', '', 10);
$doc->cell(0, 9, $value, border: true, newLine: true);
}
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT');
$doc->save($out !== false ? $out : __DIR__ . '/metadata.pdf');
echo "Wrote document with metadata\n";

Expected output:

Wrote document with metadata
  • PDF 2.0 deprecates the Info dictionary fields. Author and the other information-dictionary entries are optional and deprecated in PDF 2.0. For a PDF 2.0 consumer, the XMP stream is authoritative metadata. NextPDF emits both for compatibility, so do not assume a strict PDF 2.0 reader will surface the Info fields.
  • Language is BCP 47. Use zh-Hant-TW, not zh_TW or Chinese. An invalid tag is stored verbatim and may be ignored by assistive technology. The engine validates the tag with fail-fast behavior only when tagged-PDF strict mode is enabled.
  • setKeywords() takes a single string. Pass comma-separated terms. The engine does not split a PHP array for you.
  • Tagged-PDF interaction. When tagged PDF is enabled later, an explicit setLanguage() call made first is preserved. The structural language is only a fallback when none was set.
  • Dates are managed by the engine. Creation and modification timestamps come from the engine’s clock, and the reproducibility harness pins them. That is why the profile is structural rather than bitwise.

Setting metadata is a constant-time field assignment and has no rendering cost. It stays well inside the 1000 ms / 64 MB budget.

Metadata is stored in cleartext and is easy to extract. Do not place secrets, internal identifiers, or personal data you would not publish in the title, author, subject, keywords, or creator fields. Those fields travel with the file and are indexed by search tools. Scrub metadata before you distribute a document derived from an internal template.

StatementSpecClausereference_id
Metadata is general information about a document.ISO 32000-2§14.3
The Info dictionary Author entry is optional and deprecated in PDF 2.0.ISO 32000-2§14.3
A document-level XMP metadata stream may be attached to the document.ISO 32000-2§14.3

NextPDF emits the metadata structures described by the cited clauses. It does not assert blanket ISO 32000-2 conformance.