Vehicle stock module

Module id: vehicle_stock. Dependencies: none.

A car dealer's stock, kept in the CMS and published from there to the car platforms the website picks. The dealer enters a car once; every platform it is selected for gets a listing that follows it: created when the car goes on sale, updated whenever it changes, withdrawn when it is sold.

The CMS is the source. Nothing is read back from the platforms: a change made directly on a platform is overwritten by the next change in the CMS.

No dependency on the shop modules: a dealer site needs no webshop.

Status

Built so far: the stock itself, the channel framework, the admin API, the admin screens and the pages on the website. Still to come, each on its own card:

  • the first channel, AutoScout24 (which also publishes to AutoTrack);
  • Marktplaats, once GSID is a Marktplaats Car Dealer API partner.

On the website

With the module on, the website has two pages of its own, in every language it runs:

  • /occasions: the stock, with filters (make, model, fuel, body, transmission, maximum price, year, mileage) and an order. A filtered list is not indexed by search engines; the car pages are what should rank.
  • /occasions/{slug}: one car, with its photos, specifications, description and equipment, and schema.org Car data for search engines.

Drafts never show. A sold car stays, marked sold, until an editor deletes it, so a shared link keeps working; lists show sold cars after the ones for sale. Both pages are in the sitemap (/sitemap-vehicles.xml).

A page with the slug occasions takes the overview over, for dealers who want their own copy around the stock. The theme can restyle both pages, add an enquiry form to the car page, and show cars anywhere else (a "latest stock" block on the homepage); see the vehicle stock section of twig-helpers.md.

Until a channel ships, turning a channel on is not possible: the settings list every registered channel, and there are none yet.

Platforms

Platform How Needs
AutoScout24 Listing Creation API GSID approved as an AutoScout24 data provider; the dealer's AutoScout24 customer id
AutoTrack through AutoScout24 (a publication channel) as AutoScout24
AutoTrader.nl, Gaspedaal owned by AutoScout24, no API of their own nothing to configure
Marktplaats Marktplaats API v2 GSID approved as a Car Dealer API partner; the dealer's Marktplaats account

In the admin

  • Commerce → Vehicle stock: the stock list (status filter, search on make, model, kenteken or stock number) and New car. Editors can use it, like Products.
  • The car editor has six tabs: General (kenteken, make, model, version, VIN, stock number, status), Specifications, Price, Description & equipment (description per language, equipment one item per line), Photos and Platforms.
  • Websites → Module settings → Vehicle stock: which platforms the site publishes to and their credentials, with Test connection.

A car

Make and model are required; everything else can be filled in as the car is prepared. With the Vehicle lookup module also on, the admin can fill a car from its kenteken (Fill from RDW): make, model, year, first registration, fuel, colour, body, doors, seats, engine size and APK date. Only empty fields are filled, so nothing the dealer typed is overwritten, and a value RDW names in a way we have no mapping for is left empty rather than guessed.

Status On the platforms
draft never listed
available listed on every channel it is selected for
reserved stays listed
sold withdrawn everywhere; back to available lists it again

The price is in cents including VAT where there is any; an empty price means "on request". VAT regime says whether that price is a margin price or includes deductible VAT, which the platforms show separately.

Photos are media from the website's media library, in order; the first is the cover. Renaming or deleting a photo in the media library is tracked like a product photo.

Channels per car

Each car carries the list of channels the dealer wants it on. A listing belongs on a platform when all of these hold:

  • the dealer selected that channel for the car;
  • the car is available or reserved;
  • the channel is switched on for the website, with its credentials filled in.

When one of them stops holding, the listing is withdrawn. Deselecting a channel keeps the listing until the withdrawal has gone through, so a live ad is never forgotten.

The platform calls run in the worker, never in the admin's request. Each listing shows its state (pending, published, failed, withdrawn), the platform's id and link, and the platform's error when a push failed. A failure on one platform never holds up the others; Send again now on the car's Platforms tab tries again, and Refresh shows the outcome.

Deleting a car first withdraws it everywhere, in the request. If a platform refuses, the car is not deleted and the admin sees which listing is still live.

Switching the module off stops all syncing and withdraws nothing: the listings stay on the platforms as they were. To take the stock off the platforms, switch the channels off first, let them withdraw, then switch the module off.

Restoring a website backup rewinds the cars and their listings together. A listing created on a platform after the backup was taken is no longer known to the CMS and stays live there until it is removed by hand on the platform.

What operators set

Module settings → Vehicle stock:

Setting Default What it does
Channels none Which platforms this website publishes to.
Credentials empty Per channel, the fields that platform needs. Secrets are write-only: the admin only sees whether one is stored.

Test connection tries the stored credentials against the platform without changing anything there, and shows the platform's own error.

The settings stay editable with the module off, so a site can be prepared before it goes live.

Admin API

Method Path (under /api/admin/websites/{id}/vehicle-stock) What it does
GET /vehicles The stock, newest first (?status=available)
POST /vehicles Add a car
GET /vehicles/{vid} One car with its listings
PATCH /vehicles/{vid} Change what is sent, incl. channels
DELETE /vehicles/{vid} Withdraw everywhere, then delete
POST /vehicles/{vid}/sync Push again now
POST /prefill {"kenteken": "AB-123-C"}: fields from RDW (needs vehicle_lookup)
GET /settings Channels and their credential fields
PATCH /settings channels, credentials
POST /settings/channels/{channel}/test Test a channel's credentials

Everything but /settings 404s when the module is off.