New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

@cardog/adf

Package Overview
Dependencies
Maintainers
1
Versions
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@cardog/adf

The definitive ADF (Auto-lead Data Format) parser and builder for automotive leads — parse and create ADF XML for dealer CRMs

latest
Source
npmnpm
Version
1.0.0
Version published
Maintainers
1
Created
Source

@cardog/adf

The definitive TypeScript library for parsing and building ADF (Auto-lead Data Format) — the automotive industry's standard XML format for exchanging lead data between dealerships, CRMs, and lead providers.

npm version License: MIT

Features

  • Zero dependencies — No external packages required, works everywhere
  • TypeScript-first — Full type definitions with strict typing
  • Parse & Build — Bidirectional conversion between ADF XML and structured data
  • Spec-compliant — Implements ADF 1.0 specification with real-world compatibility
  • Normalized output — Flattened AdfLead structure for easy integration
  • Multi-vehicle support — Handles trade-ins and multiple vehicle interests
  • Battle-tested — Parses leads from AutoTrader, CarGurus, Kijiji Autos, and more

Installation

npm install @cardog/adf
# or
pnpm add @cardog/adf
# or
yarn add @cardog/adf

Quick Start

Parse ADF XML

import { parse, parseOne } from "@cardog/adf";

const xml = `<?xml version="1.0"?>
<?adf version="1.0"?>
<adf>
  <prospect status="new">
    <requestdate>2024-03-15T10:30:00Z</requestdate>
    <vehicle interest="buy" status="used">
      <year>2024</year>
      <make>Tesla</make>
      <model>Model 3</model>
      <vin>5YJ3E1EA5PF123456</vin>
    </vehicle>
    <customer>
      <contact>
        <name part="first">John</name>
        <name part="last">Doe</name>
        <email>john@example.com</email>
        <phone type="cellphone">416-555-1234</phone>
      </contact>
    </customer>
    <provider>
      <name>AutoTrader</name>
    </provider>
  </prospect>
</adf>`;

// Parse single lead
const lead = parseOne(xml);

console.log(lead.firstName); // "John"
console.log(lead.email); // "john@example.com"
console.log(lead.vehicleMake); // "Tesla"
console.log(lead.provider); // "AutoTrader"

// Parse multiple prospects
const result = parse(xml);
console.log(result.success); // true
console.log(result.leads); // AdfLead[]
console.log(result.errors); // string[]

Build ADF XML

import { build } from "@cardog/adf";

const xml = build(
  {
    firstName: "John",
    lastName: "Doe",
    email: "john@example.com",
    cellphone: "416-555-1234",
    vehicleMake: "Tesla",
    vehicleModel: "Model 3",
    vehicleYear: "2024",
    vehicleVin: "5YJ3E1EA5PF123456",
    vehiclePrice: 55000,
    vehiclePriceCurrency: "CAD",
  },
  {
    vendor: "Your Dealership",
    provider: "Your Website",
  },
);

Validate ADF

import { validate } from "@cardog/adf";

const result = validate(xml);
console.log(result.valid); // boolean
console.log(result.errors); // string[]

What is ADF?

ADF (Auto-lead Data Format) is an XML-based industry standard for transmitting automotive leads. Developed in the late 1990s by a consortium of 13 automotive internet companies, ADF has become the universal format supported by virtually every dealer CRM, lead provider, and automotive marketplace.

Key Facts

AttributeValue
Version1.0 (released May 2000)
FormatXML with optional DTD validation
EncodingUTF-8 (recommended)
TransmissionEmail attachment or HTTP POST
Specificationadfxml.info/adf_spec.pdf

Who Uses ADF?

Lead Providers:

  • AutoTrader.ca / AutoTrader.com
  • CarGurus
  • Kijiji Autos
  • Cars.com
  • CarsDirect
  • TrueCar
  • Edmunds
  • Facebook Marketplace (via adapters)

CRM Systems:

  • VinSolutions
  • DealerSocket
  • ELEAD
  • Activix
  • PBS Systems
  • CDK Global

ADF 2.0

An updated specification (ADF 2.0) has been proposed with additional elements for chat transcripts, sensitive data URLs, and service/parts leads, but ADF 1.0 remains the dominant standard.

ADF Document Structure

Minimal Valid ADF

<?xml version="1.0" encoding="UTF-8"?>
<?adf version="1.0"?>
<adf>
  <prospect status="new">
    <requestdate>2024-03-15T10:30:00Z</requestdate>
    <vehicle interest="buy">
      <year>2024</year>
      <make>Tesla</make>
      <model>Model 3</model>
    </vehicle>
    <customer>
      <contact>
        <name part="full">John Doe</name>
        <email>john@example.com</email>
      </contact>
    </customer>
  </prospect>
</adf>

Complete Element Reference

adf
└── prospect                    # One or more lead records
    ├── @status                 # "new" | "resend"
    ├── id                      # Unique identifier
    │   └── @sequence, @source
    ├── requestdate             # ISO 8601 timestamp
    ├── vehicle[]               # One or more vehicles
    │   ├── @interest           # "buy" | "lease" | "sell" | "trade-in" | "test-drive"
    │   ├── @status             # "new" | "used" | "certified"
    │   ├── id
    │   ├── year
    │   ├── make
    │   ├── model
    │   ├── trim
    │   ├── vin
    │   ├── stock
    │   ├── bodystyle
    │   ├── doors
    │   ├── transmission        # "automatic" | "manual" | "CVT"
    │   ├── condition
    │   ├── colorcombination
    │   │   ├── interiorcolor
    │   │   └── exteriorcolor
    │   ├── price
    │   │   ├── @type           # "asking" | "offer" | "msrp" | "invoice" | "appraisal"
    │   │   ├── @currency       # ISO 4217 code (CAD, USD)
    │   │   └── @delta, @relativeto, @source
    │   ├── odometer
    │   │   ├── @status         # "actual" | "estimated" | "not-actual"
    │   │   └── @units          # "km" | "mi"
    │   ├── option[]
    │   ├── finance
    │   │   ├── method          # "finance" | "lease" | "cash"
    │   │   └── balance
    │   ├── pricecomments
    │   ├── comments
    │   └── imageurl / imagetag
    ├── customer
    │   ├── contact
    │   │   ├── @primarycontact # "1" for primary
    │   │   ├── name[]
    │   │   │   ├── @part       # "first" | "middle" | "last" | "suffix" | "full"
    │   │   │   └── @type       # "individual" | "business"
    │   │   ├── email[]
    │   │   │   └── @preferredcontact  # "1" if preferred
    │   │   ├── phone[]
    │   │   │   ├── @type       # "phone" | "cellphone" | "fax" | "pager" | "voice"
    │   │   │   └── @time       # "morning" | "afternoon" | "evening" | "day" | "nopreference"
    │   │   └── address[]
    │   │       ├── @type       # "home" | "work" | "delivery"
    │   │       ├── street[]
    │   │       │   └── @line   # Line number for multi-line
    │   │       ├── apartment
    │   │       ├── city
    │   │       ├── regioncode  # Province/State code (ON, CA, NY)
    │   │       ├── postalcode
    │   │       └── country
    │   ├── comments
    │   └── timeframe
    │       ├── description     # "immediate" | "day" | "week" | "month" | "year"
    │       ├── earliestdate
    │       └── latestdate
    ├── vendor                  # The dealership
    │   ├── @id
    │   ├── id
    │   ├── vendorname
    │   ├── url
    │   └── contact             # Same structure as customer/contact
    └── provider                # The lead source
        ├── @id
        ├── id
        ├── name
        ├── service
        ├── url
        ├── email
        ├── phone
        └── contact

AdfLead Type

The normalized, flattened lead structure returned by parse() and parseOne():

interface AdfLead {
  // === Source Information ===
  id?: string; // Unique lead identifier
  requestDate?: Date; // When the lead was submitted
  status: ProspectStatus; // "new" | "resend"
  provider?: string; // Lead source name (AutoTrader, CarGurus)
  providerService?: string; // Service type
  vendor?: string; // Dealership name

  // === Contact Information ===
  firstName?: string;
  middleName?: string;
  lastName?: string;
  fullName?: string; // Computed or from part="full"
  email?: string; // Primary email
  phone?: string; // Primary phone
  cellphone?: string; // Mobile phone
  address?: {
    street?: string;
    city?: string;
    state?: string; // Mapped from regioncode
    postalCode?: string;
    country?: string;
  };

  // === Vehicle of Interest ===
  vehicleInterest?: VehicleInterest; // "buy" | "lease" | "sell" | "trade-in" | "test-drive"
  vehicleStatus?: VehicleStatus; // "new" | "used" | "certified"
  vehicleYear?: string;
  vehicleMake?: string;
  vehicleModel?: string;
  vehicleTrim?: string;
  vehicleVin?: string;
  vehicleStock?: string;
  vehiclePrice?: number; // Parsed numeric value
  vehiclePriceCurrency?: string; // "CAD" | "USD"
  vehicleOdometer?: number; // Parsed numeric value
  vehicleOdometerUnits?: string; // "km" | "mi"
  vehicleExteriorColor?: string;
  vehicleInteriorColor?: string;

  // === Trade-In (if present) ===
  tradeIn?: {
    year?: string;
    make?: string;
    model?: string;
    vin?: string;
    odometer?: number;
    condition?: string;
  };

  // === Additional ===
  comments?: string; // Vehicle comments
  customerComments?: string; // Customer message
  financeMethod?: string; // "finance" | "lease" | "cash"
  timeframe?: string; // Purchase timeframe

  // === Raw Data ===
  raw: {
    prospect: AdfProspect; // Full parsed prospect
    xml?: string; // Original XML
  };
}

Real-World Examples

AutoTrader.ca Lead

<?xml version="1.0" encoding="UTF-8"?>
<?ADF VERSION="1.0"?>
<adf>
  <prospect status="new">
    <requestdate>2024-03-18T16:45:00Z</requestdate>
    <vehicle interest="buy" status="used">
      <id sequence="1" source="AutoTrader.ca">AT-98765</id>
      <year>2024</year>
      <make>Hyundai</make>
      <model>IONIQ 5</model>
      <vin>KM8KRDAF3NU123456</vin>
      <price type="asking" currency="CAD">54995</price>
    </vehicle>
    <customer>
      <contact primarycontact="1">
        <name part="first">David</name>
        <name part="last">Williams</name>
        <email>david@example.com</email>
        <phone type="cellphone">416-555-1234</phone>
      </contact>
      <comments>Is this vehicle still available?</comments>
    </customer>
    <vendor>
      <vendorname>Your Dealership</vendorname>
    </vendor>
    <provider>
      <name part="full">AutoTrader.ca</name>
      <service>New Lead Notification</service>
    </provider>
  </prospect>
</adf>

Trade-In / Sell Request

<?xml version="1.0"?>
<?adf version="1.0"?>
<adf>
  <prospect status="new">
    <vehicle interest="buy" status="new">
      <year>2025</year>
      <make>Tesla</make>
      <model>Model Y</model>
    </vehicle>
    <vehicle interest="trade-in" status="used">
      <year>2020</year>
      <make>Honda</make>
      <model>Civic</model>
      <vin>2HGFC2F59LH123456</vin>
      <odometer units="km">85000</odometer>
      <condition>Good</condition>
    </vehicle>
    <customer>
      <contact>
        <name part="full">Jane Smith</name>
        <email>jane@example.com</email>
      </contact>
    </customer>
  </prospect>
</adf>

Provider-Specific Notes

AutoTrader.ca / AutoTrader.com

  • Uses uppercase <?ADF VERSION="1.0"?> processing instruction
  • Includes imagetag element for vehicle photos
  • Price element has extended attributes: delta, relativeto, source
  • Phone type="voice" instead of type="phone"

CarGurus

  • May omit <?adf version="1.0"?> processing instruction
  • Uses street line="1" attribute for multi-line addresses
  • Includes deal rating and price analysis data in comments

Kijiji Autos

  • Similar format to AutoTrader (same parent company)
  • May include listing URL in provider section

Facebook Marketplace

  • Requires adapter/middleware to convert to ADF
  • Contact info may be limited based on user privacy settings

API Reference

parse(xml: string): ParseResult

Parse ADF XML into normalized leads.

interface ParseResult {
  success: boolean; // True if no errors
  leads: AdfLead[]; // Normalized leads
  errors: string[]; // Error messages
  document?: AdfDocument; // Raw parsed document
}

parseOne(xml: string): AdfLead | null

Parse ADF XML and return the first lead, or null if parsing fails.

validate(xml: string): { valid: boolean; errors: string[] }

Validate ADF XML structure without normalizing.

build(lead: Partial<AdfLead>, options?: BuildOptions): string

Build ADF XML from a lead object.

interface BuildOptions {
  xmlDeclaration?: boolean; // Include <?xml ...?> (default: true)
  adfPi?: boolean; // Include <?adf version="1.0"?> (default: true)
  pretty?: boolean; // Pretty print (default: true)
  vendor?: string; // Default vendor name
  provider?: string; // Default provider name
  providerService?: string; // Default service name
}

buildFromProspect(prospect: Partial<AdfProspect>, options?: BuildOptions): string

Build ADF XML from a raw prospect structure (advanced use).

Low-Level XML Utilities

For advanced use cases, the XML parser is exposed:

import {
  parseXml,
  findChild,
  findChildren,
  getChildText,
  getAttr,
} from "@cardog/adf";
import type { XmlNode } from "@cardog/adf";

const root = parseXml(xml);
const prospect = findChild(root, "prospect");
const vehicles = findChildren(prospect, "vehicle");
const year = getChildText(vehicles[0], "year");
const status = getAttr(vehicles[0], "status");

Specification References

Contributing

Contributions are welcome! If you encounter an ADF format from a provider that doesn't parse correctly, please open an issue with a sample (with personal info redacted).

License

MIT - see LICENSE

Built by Cardog

Keywords

adf

FAQs

Package last updated on 20 Mar 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts