Skip to content
Mateusz Cieplak

Lead generation · Automotive

Grupa Krotoski

Test-drive booking funnel and campaign panel for a dealer group

A five-step booking funnel (city, brand, car, route, form) for a dealer group selling Audi, Volkswagen, Porsche and six other brands, and a panel where the agency and client teams build campaign links and QR codes and follow every lead to the dealership and the CRM.

Role
Lead developer: audit, rebuild, panel, emails and deployment (232 of 270 commits)
Period
Aug - Oct 2026
Stack
  • Next.js
  • React 19
  • TypeScript
  • SQLite
  • Docker
  • EasyPanel
  • REST API
  • CRM
What happens to a booking
  1. Campaign

    1. Link or QR code
    2. UTM kept for the session
  2. Funnel

    1. City
    2. Brand
    3. Car
    4. Route
    5. Form
  3. Delivery

    1. Lead saved
    2. Email to dealership
    3. Lead in CRM
    4. Confirmation to customer

The panel shows the status of each delivery and can resend it.

car list load
14.7 s → 8 ms
campaign paths verified in production
204 / 204
vehicles synced nightly
2,800+
blocking a11y issues, now on 31 screens
6 → 0

Context

The dealer group runs test-drive campaigns in 6 cities and 23 dealerships, across 44 test-drive routes. Every booking has to reach the right dealership, land in the CRM and confirm itself to the customer, with the campaign source kept intact.

I took over an AI-generated prototype and started with an audit. It found 8 critical issues, among them dealership emails that were never sent and 16 of 44 routes that could not be booked.

What I did

  • Audit of the prototype, then a rebuild and a move from Vercel to a self-hosted Docker server
  • Campaign paths as templates from a city × brand × dealership × model matrix, with 5 UTM parameters and a QR code for each link
  • Campaign links that open the funnel already narrowed down, with UTM attribution kept for the whole session
  • Lead form with rate limiting, a honeypot and validation
  • Delivery to the dealership by email and to the CRM, with delivery status and a separate resend button for each channel
  • Three email templates: dealership, customer confirmation and password reset
  • Two roles, admin and user, checked on the server
  • Nightly fleet sync from the client's API and user manuals for the client team

Hard parts and how I solved them

  1. Problem

    Every visit asked the client's fleet API for the car list: 14.7 seconds for 2,882 records, and an outage on the client's side left the funnel empty.

    Solution

    The fleet is fetched in the background, stored locally and passed to the first render on the server. The list now loads in 8 ms and the funnel no longer depends on the client's API being up.

  2. Problem

    A lead rejected by the CRM was simply lost.

    Solution

    Every lead is saved first, then delivered. The panel shows the status of the email and the CRM delivery separately and lets the team resend either one.

  3. Problem

    Campaign links could break silently when dealerships, models or routes changed.

    Solution

    A register of campaign paths and a check that opens every one of them. In production it passes 204 of 204.

Results

  • In production since 22.09.2026
  • Car list: 14.7 s → 8 ms
  • Blocking accessibility issues: from 6 to 0, kept at 0 as the panel grew to 31 screens
  • Smoke tests passing: email 13/13, security 8/8

Shown as a diagram. Screenshots and a walkthrough on request.

Contact

Let's talk.

Looking for a frontend developer who can take a project all the way to production? Use the form or write to me directly.

kontakt@mateuszcieplak.com

Your details are used only to reply to you. The form is delivered by Web3Forms.

Get in touch