Google Vehicle Listings
Ivan Belovari
Google Vehicle Listings ist eine von Google angebotene Plattform bzw. Funktion, die es Autohändlern ermöglicht, ihre Fahrzeugangebote direkt in den Google-Suchergebnissen und auf Google Maps zu präsentieren. Das Ziel ist es, die Sichtbarkeit von Fahrzeugen im Internet zu erhöhen und potenziellen Kunden eine einfache Möglichkeit zu bieten, nach Autos zu suchen und diese zu vergleichen.
Inhaltsverzeichnis
Erstellung von einem Google Vehicle Listings Konto
Diese Anleitung beschreibt die Schritte zur Einrichtung eines Google Vehicle Listings-Kontos für ein Autohaus, einschließlich der Verwaltung von Fahrzeugdaten und der Einhaltung von Google-Richtlinien.
Voraussetzungen
Bevor du dein Google Vehicle Listings-Konto einrichtest, stelle sicher, dass folgende Voraussetzungen erfüllt sind:
- Google-Konto: Du benötigst ein aktives Google-Konto, um dich bei https://carcenter.webapps.google.com/ anzumelden.
- Google My Business: Dein Autohaus sollte in Google My Business registriert sein und als „Car Dealership“ kategorisiert werden. Dabei ist keine direkte Eingabe von Zugangsdaten zu Google My Business erforderlich.
- Place ID: Stelle sicher, dass du die richtige Place ID deines Autohauses hast. Diese wird benötigt, um dein Unternehmen mit Google Vehicle Listings zu verknüpfen. Wie du die Place ID findest, erfährst du im Abschnitt „Plugin Backend“.
- Geschäftsdaten: Alle relevanten Informationen zu deinem Autohaus und deinem Fahrzeugbestand sollten bereitliegen, da du diese während des Registrierungsprozesses eingeben musst.
- Richtlinienverständnis: Mache dich mit den Richtlinien und Anforderungen von Google Vehicle Listings vertraut, um sicherzustellen, dass du die Daten korrekt und vollständig eingibst.
Konto erstellen
- Registrierung:
Besuche https://carcenter.webapps.google.com/ und melde dich mit deinem bestehenden Google-Konto an oder erstelle ein neues. - Daten eingeben:
Nach der Anmeldung wirst du aufgefordert, alle erforderlichen Daten zu deinem Autohaus und den Fahrzeugen vollständig und korrekt einzugeben. Achte darauf, dass du alle Felder ordentlich ausfüllst und die vorgegebenen Richtlinien beachtest.
Übermittlung von Daten von Rosebud an GVL
Das von mir entwickelte Plugin dient als Schnittstelle zwischen unserem internen Rosebud-System, in dem Fahrzeugdaten verwaltet werden, und Google Vehicle Listings (GVL). Es sorgt dafür, dass die aktuellsten Fahrzeuginformationen automatisch und reibungslos an GVL übermittelt werden.
Wie funktioniert das Plugin?
Datenextraktion aus Rosebud:
Das Plugin greift auf die Fahrzeugdaten in unserem Rosebud-System zu. Diese Daten umfassen alle relevanten Informationen zu Fahrzeugen wie Modell, Baujahr, Preis und Bilder.Datenaufbereitung:
Nachdem das Plugin die Daten aus Rosebud abgerufen hat, bereitet es diese in dem Format auf, das von Google Vehicle Listings benötigt wird. Dies kann bedeuten, die Daten in eine bestimmte CSV Struktur zu bringen und sie an die Vorgaben von GVL anzupassen.Übertragung via FTP:
Die aufbereiteten Daten werden anschließen automatisch in einen festgelegten FTP-Ordner hochgeladen. Dieser Ordner dient als Übergabepunkt für Google Vehicle Listings. GVL greift regelmäßig auf diesen Ordner zu, um die neuesten Daten abzurufen und die Fahrzeuglisten entsprechend zu aktualisieren.
Das Plugin verbindet unser internes Rosebud-System mit Google Vehicle Listings durch einen automatisierten, täglichen Datentransfer um 8 Uhr morgens. Es extrahiert, bereitet auf und überträgt die Fahrzeugdaten zuverlässig über einen FTP-Ordner an GVL. Dadurch bleiben die Fahrzeuglisten stets aktuell, was die Sichtbarkeit unserer Angebote erhöht und den Prozess für uns und für potenzielle Käufer optimiert.
Plugin Backend
Google Place IDs
Die Place IDs sind für die Vehicle Listings unbedingt erforderlich,
herausfinden kann man sie über
https://developers.google.com/maps/documentation/javascript/examples/places-placeid-finder
Die Standorte werden automatisch aus dem Rosebud System importiert, es ist möglich,
für mehrere Standorte die gleiche Place ID zu benutzen
Stand Januar 2024 sind werden nur die Meilen als Einheit für den Kilometerstand angenommen
SFTP Server Daten:
Findet man unter https://carcenter.webapps.google.com/feed > Feed Credentials
Automatisches Hochladen zum FTP
Der automatische Upload funktioniert über
ein Cronjob.
Diese funktion kann hier eingeschaltet werden.
Ziemlich selbsterklärend.
Die Struktur der CSV Datei
Die einzelnen Felder im CSV-Header für Google Vehicle Listings folgen den Vorgaben der Feed-Spezifikation von Google Vehicle Listings. Im Folgenden erkläre ich jedes Feld aus deinem Header, was es bedeutet und in welchem Format bzw. Datentyp es in der Regel erwartet wird. Da die Spezifikationen Änderungen unterliegen können, dienen diese Angaben als allgemeine Richtlinie basierend auf den bekannten Anforderungen. Für die aktuellsten Details sollte immer die offizielle Dokumentation konsultiert werden.
Hier ist eine tabellarische Darstellung der Felder, ihrer Bedeutung und des erwarteten Formats gemäß den Spezifikationen von Google Vehicle Listings:
| Attribut | Erforderlich | Datentyp | Beschreibung | Anmerkungen |
|---|---|---|---|---|
| vin | Erforderlich | String | Fahrzeugidentifikationsnummer, eine eindeutige alphanumerische Kennzeichnung für das jeweilige Fahrzeug. Hinweis: Muss dem NHTSA-Standard entsprechen. |
Wird auf Google angezeigt. |
| id | Optional | String | Eine interne Artikelnummer, die für jedes Fahrzeug eindeutig ist. | Nicht bei Google angezeigt, dient zur Verbesserung der Datenqualität. |
| store_code | Erforderlich | String | Eine interne Kennung, die für jeden Autohändler eindeutig ist. | Nicht bei Google angezeigt, dient zur Verbesserung der Datenqualität. |
| place_id | Optional | String | Die Orts-ID des Unternehmensprofils des Autohauses. | Nicht bei Google angezeigt, dient zur Verbesserung der Datenqualität. |
| maps_url | Optional | URL | Google Maps-URL des Unternehmensprofils des Autohauses. | Nicht bei Google angezeigt, dient zur Verbesserung der Datenqualität. |
| dealership_name | Erforderlich | String | Vollständiger Name des Autohauses. | Wird auf Google angezeigt. |
| dealership_address | Erforderlich | String | Vollständige Adresse des Autohauses, inkl. Stadt, Postleitzahl und Land. | Wird auf Google angezeigt. |
| tracking_phone_number | Optional | Telefonnummer | Für die Fahrzeugeinträge verwendete Telefonnummer. | Wird auf Google angezeigt. |
| image_link | Empfohlen | URL | Das Hauptbild des Fahrzeugs. | Wird auf Google angezeigt. |
| additional_image_link | Empfohlen | URL, wiederholt | Zusätzliche Bilder für das Fahrzeug. | Wird auf Google angezeigt. |
| link | Empfohlen | URL | Link zur Fahrzeugdetailseite (VDP). | Wird auf Google angezeigt. |
| date_in_stock | Optional | Datum | Datum, an dem das Fahrzeug zum ersten Mal zum Verkauf stand (ISO 8601, z. B. 2020-01-31). | Nicht bei Google angezeigt, dient zur Verbesserung der Datenqualität. |
| price | Erforderlich | Preis | Der endgültige Sonderangebotspreis für das Fahrzeug (ISO 4217, z. B. 10499 USD). | Wird auf Google angezeigt. |
| vehicle_msrp | Empfohlen | Preis | UVP für ein neues Fahrzeug in der aktuellen Konfiguration (ISO 4217). | Wird auf Google angezeigt. |
| condition | Erforderlich | String | Zustand des Fahrzeugs: neu oder gebraucht. Erlaubte Werte: n/new (Neu), u/used (Gebraucht). |
Wird auf Google angezeigt. |
| certified_pre_owned | Optional | Boolesch | Gibt an, ob das Fahrzeug zertifiziert gebraucht ist. Erlaubte Werte: 1/y/yes, 0/n/no. |
Wird auf Google angezeigt (nur für Gebrauchtwagen). |
| make | Erforderlich | String | Hersteller des Fahrzeugs, z. B. Toyota. | Wird auf Google angezeigt. |
| model | Erforderlich | String | Modell des Fahrzeugs, z. B. Civic. | Wird auf Google angezeigt. |
| trim | Erforderlich, sofern verfügbar | String | Ausstattungsvariante des Modells, z. B. S, SV oder SL. | Wird auf Google angezeigt. |
| year | Erforderlich | Int | Modelljahr im Format YYYY. | Wird auf Google angezeigt. |
| mileage | Erforderlich für gebrauchte Fahrzeuge | Ganzzahl + Einheit | Laufleistung des Fahrzeugs (z. B. 2333 oder 52,777 miles). | Wird auf Google angezeigt. Standard: Meilen. |
| exterior_color | Empfohlen | String | Vom OEM angegebene Außenfarbe, z. B. White, Platinum. | Wird auf Google angezeigt. |
Plugin Code
'miles'
));
}
add_action('admin_init', 'autoactiva_vehicle_feed_register_settings');
/**
* ==========================
* 2) Menüpunkt unter "Einstellungen"
* ==========================
*/
function autoactiva_vehicle_feed_add_admin_menu()
{
add_options_page(
'Autoactiva Vehicle Feed',
'Autoactiva Vehicle Feed',
'manage_options',
'autoactiva-vehicle-feed',
'autoactiva_vehicle_feed_settings_page'
);
}
add_action('admin_menu', 'autoactiva_vehicle_feed_add_admin_menu');
/**
* ==========================
* 3) Rendering der Einstellungsseite
* ==========================
*/
function autoactiva_vehicle_feed_settings_page()
{
if (! current_user_can('manage_options')) {
return;
}
// Hole den aktuellen Wert der Checkbox (Default 'no')
$auto_upload_enabled = get_option('autoactiva_vehicle_feed_auto_upload_enabled', 'no');
// Hole die bevorzugte Einheit (Default 'miles')
$unit = get_option('autoactiva_vehicle_feed_unit', 'miles');
// Aktion auswerten (CSV oder CSV + SFTP)
if (isset($_POST['autoactiva_action']) && check_admin_referer('autoactiva_vehicle_feed_action', 'autoactiva_vehicle_feed_nonce')) {
$action_type = sanitize_text_field($_POST['autoactiva_action']);
if ($action_type === 'create_csv') {
// Nur CSV
$export_result = autoactiva_vehicle_feed_run_export(false);
if ($export_result === true) {
echo 'CSV wurde erfolgreich erstellt.
';
} else {
echo 'Fehler beim Erstellen der CSV: ' . esc_html($export_result) . '
';
}
} elseif ($action_type === 'export_vehicle_listings') {
// CSV + SFTP
$export_result = autoactiva_vehicle_feed_run_export(true);
if ($export_result === true) {
echo 'Export zu Vehicle Listings (SFTP) wurde erfolgreich durchgeführt.
';
} else {
echo 'Fehler beim Export zu Vehicle Listings: ' . esc_html($export_result) . '
';
}
}
}
?>
Autoactiva Vehicle Feed – Einstellungen
Manueller Export
CSV erstellen: Erzeugt nur die CSV im uploads-Ordner.
Export zu Vehicle Listings durchführen: Erzeugt die CSV und lädt sie via SFTP hoch (mit den oben gespeicherten Zugangsdaten).
array('publish'),
'limit' => -1,
);
$products = wc_get_products($args);
if (! $products) {
return 'Keine Produkte gefunden.';
}
// CSV-Header
$header = array(
'store_code',
'place_id',
'id',
'post_id',
'VIN',
'year',
'make',
'model',
'trim',
'exterior_color',
'interior_color',
'mileage',
'fuel_efficiency',
'fuel',
'ev_range',
'ev_battery',
'co2_emission',
'condition',
'price',
'dealership_name',
'dealership_address',
'link',
'image_link',
'additional_image_link',
'vehicle_option',
'vehicle_fulfillment',
'legal_disclaimer'
);
// CSV-Datei erstellen
$fp = fopen($local_file_path, 'w');
if (! $fp) {
return "Konnte CSV nicht erstellen unter: $local_file_path";
}
// Kopfzeile in CSV
fputcsv($fp, $header);
// Beispiel-Store-Code (ggf. dynamisch anpassbar)
$store_code = '1';
// Einheitseinstellung abfragen
$unit = get_option('autoactiva_vehicle_feed_unit', 'miles');
// Produkte durchgehen
foreach ($products as $product) {
$product_id = $product->get_id();
// Attribute abfragen
$pa_vinfull = $product->get_attribute('pa_vinfull');
$pa_erstzulassung = $product->get_attribute('pa_erstzulassung');
$pa_marke = $product->get_attribute('pa_marke');
$pa_modell = $product->get_attribute('pa_modell');
$pa_trim = $product->get_attribute('pa_trim');
$pa_farbe = $product->get_attribute('pa_farbe');
$pa_innenfarbe = $product->get_attribute('pa_innenfarbe');
$pa_kilometerstand = $product->get_attribute('pa_kilometerstand');
$pa_kraftstoff = $product->get_attribute('pa_kraftstoff');
$pa_fahrzeugzustand = $product->get_attribute('pa_fahrzeugzustand');
$pa_autohaus = $product->get_attribute('pa_autohaus');
$pa_adresse = $product->get_attribute('pa_adresse');
// Optionale Attribute
$pa_vehicle_option = $product->get_attribute('pa_vehicle_option');
$pa_vehicle_fulfillment = $product->get_attribute('pa_vehicle_fulfillment');
$pa_legal_disclaimer = $product->get_attribute('pa_legal_disclaimer');
// VIN
$vin = $pa_vinfull ? $pa_vinfull : '';
// Jahr aus "08.2021" extrahieren
$year = '';
if (!empty($pa_erstzulassung)) {
$year = substr($pa_erstzulassung, -4);
}
// Kilometerstand bearbeiten
$mileage = '';
if (!empty($pa_kilometerstand)) {
// Entfernung von Einheiten (z.B. " km")
$pa_kilometerstand = str_ireplace(array(' km', 'km'), '', $pa_kilometerstand);
// Als Zahl parsen
$km_value = floatval(trim($pa_kilometerstand));
if ($unit === 'miles') {
// Umrechnung in Meilen
$value = $km_value * 0.621371;
$value = round($value, 2);
$mileage = $value . ' miles';
} else {
// Kilometer beibehalten
$value = round($km_value, 2);
$mileage = $value . ' km';
}
}
// Fahrzeugzustand
$condition = 'used';
if (strtolower($pa_fahrzeugzustand) === 'neuwagen') {
$condition = 'new';
}
// Preis
$price = $product->get_price() . ' ' . get_woocommerce_currency();
// Fuel, EV-Daten, CO2 etc. (nicht genutzt)
$fuel_efficiency = '';
$ev_range = '';
$ev_battery = '';
$co2_emission = '';
$fuel = $pa_kraftstoff;
// Place ID zum Autohaus-Namen
$place_id = get_place_id_by_dealership($pa_autohaus);
// Links
$link = get_permalink($product_id);
// Bilder
$image_id = $product->get_image_id();
$image_link = $image_id ? wp_get_attachment_url($image_id) : '';
$gallery_ids = $product->get_gallery_image_ids();
$additional_image_link = array();
if (! empty($gallery_ids)) {
foreach ($gallery_ids as $gid) {
$additional_image_link[] = wp_get_attachment_url($gid);
}
}
$additional_image_link_str = implode(',', $additional_image_link);
// CSV-Zeile
$data = array(
$store_code,
$place_id,
$product_id,
$product_id,
$vin,
$year,
$pa_marke,
$pa_modell,
$pa_trim,
$pa_farbe,
$pa_innenfarbe,
$mileage,
$fuel_efficiency,
$fuel,
$ev_range,
$ev_battery,
$co2_emission,
$condition,
$price,
$pa_autohaus,
$pa_adresse,
$link,
$image_link,
$additional_image_link_str,
$pa_vehicle_option,
$pa_vehicle_fulfillment,
$pa_legal_disclaimer
);
fputcsv($fp, $data);
}
fclose($fp);
// Wenn kein SFTP gewünscht, fertig
if (! $do_sftp) {
return true;
}
// SFTP nur, wenn Daten vorhanden
if (empty($sftp_server) || empty($sftp_user) || empty($sftp_password)) {
return 'SFTP-Daten sind unvollständig. Kein Upload.';
}
// Ziel-Dateiname auf dem SFTP-Server
$remote_file_path = 'woocommerce_export.csv';
// cURL-Upload
$upload_res = autoactiva_vehicle_feed_sftp_upload(
$sftp_server,
(int) $sftp_port,
$sftp_user,
$sftp_password,
$local_file_path,
$remote_file_path
);
if ($upload_res === true) {
return true;
} else {
return $upload_res; // Fehlermeldung
}
}
/**
* ==========================
* 6) SFTP-Upload mit cURL
* ==========================
*
* @param string $server SFTP-Server
* @param int $port Port
* @param string $user Benutzername
* @param string $pass Passwort
* @param string $local Pfad zur lokalen Datei
* @param string $remote Zielpfad auf dem SFTP-Server
*
* @return true|string true = Erfolg, string = Fehlermeldung
*/
function autoactiva_vehicle_feed_sftp_upload($server, $port, $user, $pass, $local, $remote)
{
if (! function_exists('curl_init')) {
return 'cURL ist nicht verfügbar oder nicht aktiviert.';
}
// Lokale Datei öffnen
$fp = @fopen($local, 'r');
if (! $fp) {
return "Konnte lokale Datei nicht öffnen: $local";
}
// SFTP-URL
$url = "sftp://{$server}:{$port}/{$remote}";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERPWD, "{$user}:{$pass}");
curl_setopt($ch, CURLOPT_UPLOAD, 1);
curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_SFTP); // SFTP-Protokoll aktivieren
curl_setopt($ch, CURLOPT_INFILE, $fp);
curl_setopt($ch, CURLOPT_INFILESIZE, filesize($local));
// Timeouts
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_TIMEOUT, 300);
// SSL-Überprüfung ggf. anpassen
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
// Upload ausführen
$result = curl_exec($ch);
$err_no = curl_errno($ch);
$err_msg = curl_error($ch);
curl_close($ch);
fclose($fp);
if ($result === false || $err_no) {
return "Fehler beim SFTP-Upload: [{$err_no}] {$err_msg}";
}
// Upload erfolgreich
return true;
}
// ---(C) Cron-Intervall definieren + Hook auf Option-Update---
function autoactiva_vehicle_feed_add_cron_schedules($schedules)
{
if (!isset($schedules['every_24_hours'])) {
$schedules['every_24_hours'] = array(
'interval' => 24 * 60 * 60, // 24 Stunden
'display' => __('Alle 24 Stunden (täglich)'),
);
}
return $schedules;
}
add_filter('cron_schedules', 'autoactiva_vehicle_feed_add_cron_schedules');
add_action('update_option_autoactiva_vehicle_feed_auto_upload_enabled', 'autoactiva_vehicle_feed_update_auto_upload_schedule', 10, 2);
function autoactiva_vehicle_feed_update_auto_upload_schedule()
{
$enabled = get_option('autoactiva_vehicle_feed_auto_upload_enabled', 'no');
if ($enabled === 'yes') {
// Einplanen, falls nicht bereits geplant
if (!wp_next_scheduled('autoactiva_vehicle_feed_daily_cron_event')) {
// Zeitpunkt: heute um 08:00 oder morgen um 08:00 (falls heute schon vorbei ist)
$today_8am = strtotime(date('Y-m-d') . ' 08:00:00');
if (time() > $today_8am) {
$scheduled_time = strtotime('tomorrow 08:00');
} else {
$scheduled_time = $today_8am;
}
wp_schedule_event($scheduled_time, 'every_24_hours', 'autoactiva_vehicle_feed_daily_cron_event');
}
} else {
// Deaktivieren: Cron-Event löschen
$timestamp = wp_next_scheduled('autoactiva_vehicle_feed_daily_cron_event');
if ($timestamp) {
wp_unschedule_event($timestamp, 'autoactiva_vehicle_feed_daily_cron_event');
}
}
}
// ---(D) Die eigentliche Cron-Callback-Funktion---
add_action('autoactiva_vehicle_feed_daily_cron_event', 'autoactiva_vehicle_feed_daily_cron_callback');
function autoactiva_vehicle_feed_daily_cron_callback()
{
// Automatisch SFTP-Upload ausführen
autoactiva_vehicle_feed_run_export(true);
}