15 posts 61 tags 7 domains

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
<?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)

TagNazwaCo tu wpisać
5Object NameTytuł obrazka
25KeywordsSłowa kluczowe (powtarzalne)
80By-lineAutor / Creator (Google to czyta)
105HeadlineNagłówek
110CreditKomu przypisać zasługi
115SourceŹródło
116Copyright NoticeNotka © (Google to czyta)
120Caption/AbstractOpis

Integracja z imagejpeg()

Realny przypadek: resize miniaturki, a potem doklejenie IPTC.

php
<?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:

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:

bash
$exiftool -IPTC:all output.jpg
By-line : Autor / Firma
Copyright Notice : © 2026 Twoja Firma
Caption-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.