Dodawanie metadanych IPTC do obrazków w PHP — dla SEO i Google Images
Jak wstrzyknąć IPTC do JPEG-ów bez bibliotek, dlaczego Google to czyta i kiedy daje znacznik Licensable.
Problem
Po przeskalowaniu obrazków przez GD (imagejpeg()) tracimy wszystkie metadane. To samo dotyczy zdjęć eksportowanych z większości narzędzi automatyzujących pipeline mediów. Pytanie brzmi: czy w ogóle warto je z powrotem wstrzykiwać, a jeśli tak — to które i jak?
Po co IPTC w obrazkach
Google oficjalnie czyta pola IPTC (Creator, Copyright, Credit Line, Web Statement) i wyświetla je w Google Images jako informacje o autorze i licencji. W połączeniu z odpowiednim schema.org ImageObject na stronie, obrazek dostaje znacznik Licensable w wynikach wyszukiwania grafiki — co realnie zwiększa CTR i ułatwia monetyzację.
EXIF (aparat, GPS, data) Google widzi, ale nie wykorzystuje jako sygnału rankingowego. ICC profile to czysto wizualna sprawa. Sensowny target to więc IPTC.
Najprostszy sposób — natywne iptcembed()
PHP ma wbudowaną funkcję iptcembed() od czasów PHP 4. Nie potrzeba composera, GD ani Imagicka:
<?php
function buildIptcBlock(array $data): string
{
$block = '';
foreach ($data as $tag => $value) {
$values = is_array($value) ? $value : [$value];
foreach ($values as $v) {
$v = (string)$v;
$len = strlen($v);
// 0x1C = marker IPTC, 0x02 = record 2 (application), tag, długość big-endian
$block .= chr(0x1C) . chr(0x02) . chr($tag)
. chr($len >> 8) . chr($len & 0xFF) . $v;
}
}
return $block;
}
$iptc = [
5 => 'Tytuł obrazka',
25 => ['słowo1', 'słowo2', 'słowo3'], // keywords — można powtarzać
80 => 'Autor / Firma', // By-line (Creator)
105 => 'Krótki nagłówek', // Headline
115 => 'Źródło', // Source
116 => '© 2026 Twoja Firma', // Copyright Notice
120 => 'Pełny opis obrazka.', // Caption/Abstract
];
$content = iptcembed(buildIptcBlock($iptc), 'input.jpg');
file_put_contents('output.jpg', $content);
Najważniejsze tagi IPTC (record 2)
| Tag | Nazwa | Co tu wpisać |
|---|---|---|
| 5 | Object Name | Tytuł obrazka |
| 25 | Keywords | Słowa kluczowe (powtarzalne) |
| 80 | By-line | Autor / Creator (Google to czyta) |
| 105 | Headline | Nagłówek |
| 110 | Credit | Komu przypisać zasługi |
| 115 | Source | Źródło |
| 116 | Copyright Notice | Notka © (Google to czyta) |
| 120 | Caption/Abstract | Opis |
Integracja z imagejpeg()
Realny przypadek: resize miniaturki, a potem doklejenie IPTC.
<?php
function resizeAndTagImage(
string $source,
string $dest,
int $maxWidth,
array $iptcData,
int $quality = 85
): bool {
[$w, $h] = getimagesize($source);
$ratio = $maxWidth / $w;
$newW = $maxWidth;
$newH = (int)($h * $ratio);
$src = imagecreatefromjpeg($source);
$dst = imagecreatetruecolor($newW, $newH);
imagecopyresampled($dst, $src, 0, 0, 0, 0, $newW, $newH, $w, $h);
imagejpeg($dst, $dest, $quality);
imagedestroy($src);
imagedestroy($dst);
$content = iptcembed(buildIptcBlock($iptcData), $dest);
if ($content === false) {
return false;
}
return file_put_contents($dest, $content) !== false;
}
Walidacja — czy się udało
Najszybsza weryfikacja bez wychodzenia z PHP:
$info = [];
getimagesize('output.jpg', $info);
if (isset($info['APP13'])) {
$iptc = iptcparse($info['APP13']);
print_r($iptc);
}
Klucze w tablicy wynikowej mają format 2#080 (record 2, tag 80 = By-line) itd.
Z poziomu shella:
$exiftool -IPTC:all output.jpgBy-line : Autor / FirmaCopyright Notice : © 2026 Twoja FirmaCaption-Abstract : Pełny opis obrazka.Keywords : słowo1, słowo2, słowo3
Czego nie robić
Wpychanie keywords w IPTC pod kątem stuffingu słów kluczowych — Google to ignoruje od lat i może traktować jako sygnał spamerski. IPTC w obrazkach to nie meta keywords w HTML — wypełniaj realnie i tylko tym, co opisuje obrazek.
Zachowywanie GPS w EXIF zdjęć produktowych, portretowych czy wnętrz prywatnych — to wyciek danych. Jeśli już dokleisz EXIF, GPS wytnij osobno.
Co się dzieje pod spodem
JPEG to kontener segmentów. Każdy segment zaczyna się od markera 0xFF + identyfikator. IPTC siedzi w segmencie APP13 (0xFFED) z identyfikatorem Photoshop 3.0\0. EXIF leży w APP1 (0xFFE1). ICC profile w APP2.
iptcembed() szuka pozycji za nagłówkiem JPEG (SOI + ewentualnie APP0/JFIF) i wstawia tam swój APP13 z surowymi rekordami IPTC IIM (każdy zaczyna się od 0x1C, potem record number, dataset number, długość, wartość). Dlatego można to zrobić bez parsowania całego pliku — wystarczy zlokalizować odpowiednie miejsce i wstrzyknąć blok bajtów.
To samo można osiągnąć pisząc ręcznie po segmentach JPEG, ale po co, skoro PHP daje gotowca.