DEV Community

Vin Lookup
Vin Lookup

Posted on

Showing TrailerType from vPIC Without Inventing Tow Ratings

NHTSA vPIC sometimes returns a TrailerType field on DecodeVinValues-style payloads -- catalog tokens for trailer-oriented patterns (boat, utility, fifth-wheel style labels, and similar). That string can help when the VIN actually decodes as a trailer. The trap is turning it into a tow-rating pitch for a truck or SUV decode -- "tows 10,000 lb," "fifth-wheel ready," "rated for this trailer type" -- that TrailerType never asserted for the tow vehicle.

This post is about honest display: show TrailerType when vPIC provides it, refuse tow inventing, and allow a clean "not provided" state when the field is empty. Keep trailer catalog labels separate from vehicle GVWR, drive type, and marketing tow charts.

What TrailerType is (and is not)

TrailerType is a catalog attribute associated with the VIN decode. It answers a narrow question: which trailer-type label did the decode associate with this pattern?

It does not answer:

  • Maximum tow capacity of a pickup, SUV, or chassis cab
  • Tongue weight, hitch class, or trailer brake controller requirements
  • Whether a truck VIN "matches" a trailer VIN for safe pairing
  • Payload remaining after passengers and bed load
  • Lifestyle copy ("weekend warrior," "ranch ready") derived from a trailer token

Empty TrailerType does not mean "not a trailer" in a way that authorizes you to invent hitch ratings on a truck card. It means vPIC did not give you that field. Do not fill the gap from BodyClass folklore or from a static tow table keyed only by Make/Model/Year.

Normalize empties, do not invent tow numbers

Treat blank, "Not Applicable", "N/A", and similar tokens as missing. Do not rewrite a trailer type string into "7,500 lb tow" or append hitch class because a brochure listed that combination for a different trim.

const EMPTY = new Set([
  "",
  "not applicable",
  "n/a",
  "na",
  "null",
  "none",
  "unknown",
]);

export type TrailerTypeView = {
  label: string | null;
  source: "vpic" | "missing";
};

export function viewTrailerType(fields: {
  TrailerType?: string | null;
}): TrailerTypeView {
  const raw = (fields.TrailerType ?? "").trim();
  if (!raw || EMPTY.has(raw.toLowerCase())) {
    return { label: null, source: "missing" };
  }
  // Keep the catalog token; do not coerce into tow / hitch claims.
  return { label: raw, source: "vpic" };
}

export function trailerTypeLines(view: TrailerTypeView): string[] {
  if (view.source === "missing" || !view.label) {
    return ["Trailer type: not provided by vPIC for this VIN"];
  }
  return [
    `Trailer type (vPIC): ${view.label}`,
    "Catalog label only -- not a tow rating or hitch class",
  ];
}
Enter fullscreen mode Exit fullscreen mode

The footnote matters. Buyers scanning a truck decode will over-read any trailer-shaped word. If the VIN is a trailer, the label is useful. If blank on a truck, say "not provided" -- no greyed tow-package placeholder.

Forbidden upgrades

Product pressure often asks for:

  1. Mapping TrailerType tokens into "tows X lb" badges on truck result cards
  2. Inferring hitch class from TrailerType when vPIC never returned hitch data
  3. Pairing a truck VIN with a trailer VIN and declaring them "compatible" from type strings alone
  4. Merging TrailerType with GVWRClass into "Heavy Tow Package"
  5. Defaulting blank TrailerType to "Utility" so trailer inventory UIs never look empty

Refuse those. If you show GVWR, DriveType, or BodyClass from other sourced fields, show each on its own row. Never invent tow arithmetic in the mapper.

export function assertNoTowMarketing(moduleSource: string): void {
  const banned = [
    /tows?\s+\d/i,
    /hitch\s*class\s*\d/i,
    /tongue\s*weight/i,
    /heavy\s+tow\s+package/i,
    /fifth[-\s]?wheel\s+ready/i,
  ];
  for (const re of banned) {
    if (re.test(moduleSource)) {
      throw new Error(
        `TrailerType display must not invent tow claims: ${re}`,
      );
    }
  }
}

export function cardRows(fields: {
  TrailerType?: string | null;
  BodyClass?: string | null;
  GVWRClass?: string | null;
}): { label: string; value: string }[] {
  const trailer = viewTrailerType(fields);
  const body = (fields.BodyClass ?? "").trim();
  const gvwr = (fields.GVWRClass ?? "").trim();
  const rows: { label: string; value: string }[] = [];

  if (trailer.source === "vpic" && trailer.label) {
    rows.push({ label: "Trailer type (vPIC)", value: trailer.label });
  } else {
    rows.push({ label: "Trailer type (vPIC)", value: "not provided" });
  }

  if (body && !EMPTY.has(body.toLowerCase())) {
    rows.push({ label: "Body class (vPIC)", value: body });
  }
  if (gvwr && !EMPTY.has(gvwr.toLowerCase())) {
    rows.push({ label: "GVWR (vPIC)", value: gvwr });
  }

  return rows;
}
Enter fullscreen mode Exit fullscreen mode

Separate rows keep attribution clear. A single "Towing" chip that secretly combines TrailerType and GVWR is how marketing sneaks past review.

When to hide the row entirely

You may always show "not provided" or omit the row on clearly non-trailer BodyClass values. Either is fine if you do not invent. Never fill a blank with a tow upsell.

Small tests that lock honesty

import assert from "node:assert/strict";

assert.equal(
  viewTrailerType({ TrailerType: "Boat Trailer" }).source,
  "vpic",
);
assert.equal(viewTrailerType({ TrailerType: "N/A" }).source, "missing");
assert.equal(viewTrailerType({ TrailerType: "" }).source, "missing");

assert.ok(
  trailerTypeLines(
    viewTrailerType({ TrailerType: "Utility" }),
  ).some((l) => /not a tow rating/i.test(l)),
);
assert.ok(
  !trailerTypeLines(
    viewTrailerType({ TrailerType: "Utility" }),
  ).some((l) => /tows|hitch class|tongue/i.test(l)),
);

const rows = cardRows({
  TrailerType: "",
  BodyClass: "Pickup",
  GVWRClass: "Class 2E: 6,001 - 7,000 lb",
});
assert.ok(rows.some((r) => r.label.includes("Trailer type") && r.value === "not provided"));
assert.ok(rows.some((r) => r.label.includes("GVWR")));
assert.ok(!rows.some((r) => /Heavy Tow|tows \d/i.test(r.value)));
Enter fullscreen mode Exit fullscreen mode

Add a review rule: the TrailerType module must not contain tow or hitch marketing phrases except in tests that forbid them. For chips, show the catalog type with a "Trailer type" label -- never upgrade a blank into "Standard Utility" or a truck tow package.

Takeaway

TrailerType is a catalog label. Display it with clear sourcing, allow "not provided," and never use it as a key into invented tow ratings or hitch classes. Your free VIN UI stays trustworthy when trailer type is either a real vPIC value with a modest footnote -- or absent -- and towing marketing lives somewhere else, clearly labeled, or not at all.

I maintain VIN Lookup, a free VIN decode based on NHTSA data.

Top comments (0)