npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@cardog/adf

v1.0.0

Published

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

Readme

@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>[email protected]</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); // "[email protected]"
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: "[email protected]",
    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

| Attribute | Value | | ----------------- | ------------------------------------------------------------ | | Version | 1.0 (released May 2000) | | Format | XML with optional DTD validation | | Encoding | UTF-8 (recommended) | | Transmission | Email attachment or HTTP POST | | Specification | adfxml.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>[email protected]</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>[email protected]</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>[email protected]</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