55 min readIntelligence & insights

Implementation Guide: Identify customers approaching key maintenance milestones for proactive outreach

Step-by-step implementation guide for deploying AI to identify customers approaching key maintenance milestones for proactive outreach for Automotive clients.

Hardware Procurement

Next-Generation Firewall / UTM Appliance

FortinetFortiGate 60F (FG-60F)Qty: 1

$500–$750 per unit (MSP cost) / $1,000–$1,500 suggested resale including first-year FortiGuard bundle license

Provides network perimeter security, intrusion detection/prevention, VPN, web filtering, and network segmentation via VLANs — all required under the FTC Safeguards Rule for dealerships. Ensures encrypted transit for customer data flowing between on-premise DMS and cloud SaaS analytics platforms. Essential for separating customer Wi-Fi from dealership operations network.

Managed Network Switch

CiscoCBS350-24T-4GQty: 1

$400–$600 per unit (MSP cost) / $650–$950 suggested resale

Provides VLAN-capable Layer 3 switching to segment dealership network into zones: DMS/finance, service advisor workstations, guest Wi-Fi, and IoT/phones. Required for FTC Safeguards network segmentation compliance. Supports QoS for VoIP if STELLA AI voice is deployed.

Entry-Level Server (if on-premise DMS)

DellPowerEdge T150 (Xeon E-2314, 16GB RAM, 2x 2TB HDD RAID 1)Qty: 1

$1,200–$1,800 per unit (MSP cost) / $1,800–$2,600 suggested resale

Hosts on-premise DMS application and database if dealership has not migrated to cloud DMS. Also serves as local file server for compliance documentation, backup staging, and DMS data export cache. Not required if dealership runs fully cloud-based DMS (e.g., Tekion or cloud-hosted CDK).

Service Advisor Workstations

DellOptiPlex 7020 SFF (i5-14500, 16GB RAM, 512GB SSD)Qty: 4

$700–$900 per unit (MSP cost) / $1,000–$1,300 suggested resale

Standard workstations for service advisors and BDC staff who will interact with the analytics dashboard, review milestone alerts, and manage outreach campaigns. Four units covers a typical single-rooftop service department (2–3 advisors + 1 BDC rep).

Uninterruptible Power Supply

Uninterruptible Power Supply

APCSMT1500RM2U (Smart-UPS 1500VA 2U Rackmount)Qty: 1

$450–$600 per unit (MSP cost) / $700–$950 suggested resale

Protects on-premise server and network equipment (firewall, switch) from power interruptions. Provides 15–20 minutes of runtime for graceful shutdown. Critical for protecting DMS database integrity during power events common in service bay environments.

Software Procurement

Affinitiv Essentials

Affinitiv (Polaris/Riverside portfolio)

$1,000–$3,000/month per rooftop (vendor direct pricing; MSP co-management fee of $500–$1,000/month additional)

Primary predictive analytics and lifecycle marketing engine. Provides AI/ML-powered identification of customers at 100+ ownership lifecycle milestones, automated multi-channel outreach (email, direct mail, SMS, voice), OEM maintenance schedule mapping, and campaign performance analytics. This is the core AI platform for the project.

Xtime Schedule + Engage

Cox AutomotiveSchedule + Engage

$500–$2,000/month per rooftop depending on module bundle

Online service scheduling platform integrated with DMS that enables customers receiving milestone outreach to instantly book appointments. Provides real-time service lane capacity management so outreach campaigns align with available appointment slots. Trusted by nearly 7,000 franchise dealers.

Custom quote; typically $500–$1,500/month per rooftop

AI voice assistant that handles inbound service calls generated by outreach campaigns, books appointments without human intervention, and can make outbound proactive reminder calls. Reduces BDC staffing burden and ensures 24/7 appointment booking capability. Has pre-built partnerships with Affinitiv and CDK Global.

Twilio SMS API + SendGrid Email API

Twilio Inc.Usage-based API

SMS: ~$0.0079/message sent + $0.0079/received; SendGrid Email: $19.95/month for 50,000 emails (Essentials plan). Typical dealership: $100–$400/month total

Serves as the communications infrastructure layer if the primary analytics platform (Affinitiv) requires supplemental outreach channels, or if building custom outreach workflows. Also used for transactional messages (appointment confirmations, service completion alerts) that supplement the marketing campaigns.

Managed Endpoint Protection

SentinelOne / Huntress (bundled)Qty: Per-endpoint monthly subscription

$3–$6/endpoint/month (MSP cost); resell at $8–$15/endpoint/month. Typical dealership: 15–30 endpoints = $120–$450/month resale

Required under FTC Safeguards Rule. Provides AI-powered endpoint detection and response (EDR) on all workstations and servers that access customer data. Huntress adds managed threat hunting layer for persistent threat detection. Critical for protecting customer PII and financial data.

Multi-Factor Authentication

Duo Security (Cisco)Qty: 15–25 users (typical dealership)

$3–$9/user/month (MSP cost); resell at $7–$15/user/month. Typical dealership: 15–25 users = $105–$375/month resale

FTC Safeguards Rule explicitly requires MFA for any individual accessing customer information. Deployed on DMS access, CRM login, analytics platform, email, and VPN. Duo provides push-based MFA with device trust policies and integrates with most automotive CRM/DMS platforms.

Cloud Backup Solution

Axcient x360Recover or Datto BCDR

$100–$300/month (MSP cost); resell at $250–$600/month

Provides automated backup of on-premise DMS database, CRM data exports, compliance documentation, and service history archives. Required for FTC Safeguards data retention and disaster recovery requirements. 30-day minimum retention with point-in-time recovery.

Email Security Gateway

Proofpoint Essentials

$2–$4/user/month (MSP cost); resell at $5–$10/user/month

Protects dealership email accounts from phishing, BEC attacks, and malware delivery. Critical because dealership staff process financial documents and customer PII via email. Also ensures outbound marketing emails maintain clean sender reputation for deliverability of milestone outreach campaigns.

$175–$400+/month per rooftop per integration

Provides programmatic access to DMS service repair order history, customer records, vehicle data, and appointment scheduling. Required data pipeline for feeding service history into the Affinitiv analytics engine. Note: Affinitiv has pre-built CDK integrations that may reduce or eliminate separate API fees.

Prerequisites

  • Active DMS subscription with API access enabled or export capability — CDK Drive with Fortellis API, Reynolds & Reynolds ERA/POWER with approved data partner access, or Dealertrack DMS with Cox integration layer
  • Existing CRM with customer contact records including name, email, phone, and mailing address — VinSolutions, DealerSocket, Elead, or comparable automotive CRM
  • Minimum 12–24 months of historical service repair order (RO) data in the DMS, including dates, mileage readings, service types performed, and associated VINs
  • Clean and deduplicated customer database — duplicates across sales and service records must be merged prior to analytics platform onboarding
  • Vehicle inventory and ownership data with VIN decoding capability (typically built into DMS) to map vehicles to OEM maintenance schedules
  • Business-grade internet connection: minimum 50 Mbps symmetrical (100+ Mbps recommended for multi-rooftop); business ISP with SLA and static IP for VPN/firewall
  • Valid business email domain with SPF, DKIM, and DMARC records properly configured — critical for email deliverability of outreach campaigns
  • Registered business entity information for 10DLC SMS campaign registration (EIN, business address, business type, website URL, use case description)
  • Documented customer communication consent records — opt-in consent for SMS and email marketing must exist in the CRM or be collected going forward
  • FTC Safeguards Rule Written Information Security Plan (WISP) — either existing or to be created as part of this implementation engagement
  • Designated Qualified Individual for FTC Safeguards compliance — can be dealership staff member or the MSP under a vCISO arrangement
  • Service advisor and BDC staff availability for 2–4 hours of training during Phase 5 of implementation
  • Dealership general manager or fixed-ops director sign-off on outreach campaign templates, timing rules, and customer segmentation criteria

Installation Steps

...

Step 1: Site Assessment and Compliance Audit

Conduct an on-site assessment of the dealership's current IT infrastructure, network topology, DMS/CRM environment, and security posture. Document all systems that touch customer data (DMS terminals, CRM workstations, F&I desktops, service advisor tablets). Perform a gap analysis against FTC Safeguards Rule requirements. Identify the DMS platform and version, CRM platform, existing integrations, and data export capabilities. Catalog the existing network equipment (router, switch, firewall, wireless APs) and assess whether upgrades are needed.

bash
nmap -sn 192.168.1.0/24  # Discover all devices on dealership network
nmap -sV -O <DMS_server_IP>  # Identify DMS server OS and services
openssl s_client -connect <DMS_hostname>:443 -tls1_2  # Verify TLS configuration on DMS web interface
dig TXT <dealership_domain> +short  # Check existing SPF records
dig TXT _dmarc.<dealership_domain> +short  # Check existing DMARC records
Note

This step should produce a formal Site Assessment Report documenting: (1) network diagram, (2) asset inventory, (3) FTC Safeguards gap analysis, (4) DMS/CRM platform details and API readiness, (5) data quality preliminary assessment. Budget 4–8 hours on-site. Bring a laptop with Nmap, Wireshark, and network diagramming tools.

Step 2: Network Infrastructure Upgrade and Hardening

Deploy the FortiGate 60F firewall, Cisco CBS350 managed switch, and UPS. Configure VLANs for network segmentation: VLAN 10 (DMS/Finance — restricted), VLAN 20 (Service/BDC workstations), VLAN 30 (Guest Wi-Fi — isolated), VLAN 40 (Management — MSP access only). Configure firewall policies to restrict inter-VLAN traffic per FTC Safeguards requirements. Enable IDS/IPS with FortiGuard signatures. Set up site-to-site VPN or ZTNA for MSP remote management.

FortiGate CLI and Cisco CBS350
shell
# VLAN creation, firewall policy, and IPS configuration

# FortiGate CLI — Create VLANs
config system interface
  edit vlan10-dms
    set vdom root
    set ip 10.10.10.1 255.255.255.0
    set allowaccess ping https ssh
    set interface internal
    set vlanid 10
  next
  edit vlan20-service
    set vdom root
    set ip 10.10.20.1 255.255.255.0
    set allowaccess ping https
    set interface internal
    set vlanid 20
  next
  edit vlan30-guest
    set vdom root
    set ip 10.10.30.1 255.255.255.0
    set allowaccess ping
    set interface internal
    set vlanid 30
  next
end

# FortiGate CLI — Firewall policy: Block guest from accessing DMS VLAN
config firewall policy
  edit 100
    set name block-guest-to-dms
    set srcintf vlan30-guest
    set dstintf vlan10-dms
    set srcaddr all
    set dstaddr all
    set action deny
    set schedule always
    set logtraffic all
  next
end

# FortiGate CLI — Enable IPS
config ips sensor
  edit default
    config entries
      edit 1
        set status enable
        set action block
      next
    end
  next
end

# Cisco CBS350 — VLAN configuration
configure terminal
vlan 10
  name DMS-Finance
vlan 20
  name Service-BDC
vlan 30
  name Guest-WiFi
vlan 40
  name Management
exit
interface GigabitEthernet1/0/1
  switchport mode access
  switchport access vlan 10
  description DMS-Server
exit
Note

Document all firewall rules and VLAN assignments in the compliance documentation package. Take screenshots of FortiGate dashboard showing IPS enabled, VPN configured, and firmware version. The FortiGate 60F supports up to 200 users concurrently — sufficient for single-rooftop dealerships. For multi-rooftop, consider FortiGate 80F or 100F.

Step 3: Endpoint Security and MFA Deployment

Deploy SentinelOne EDR agent and Duo MFA on all workstations and servers that access customer data. This includes DMS terminals, CRM workstations, service advisor desktops, F&I computers, and the on-premise server. Configure SentinelOne with Detect+Protect policy (automated threat remediation). Enroll all users in Duo MFA with push notification as primary factor. Configure Duo to protect DMS web login, CRM access, Windows RDP, VPN access, and Microsoft 365/Google Workspace.

SentinelOne EDR agent installation, verification, Duo Authentication Proxy installation and configuration, and FortiGate RADIUS setup for MFA on VPN
shell
# SentinelOne Agent Installation (Windows)
# Download agent from SentinelOne management console
SentinelOneInstaller_x64.exe /SITE_TOKEN=<your_site_token> /quiet /norestart

# Verify SentinelOne installation
sc query SentinelAgent
SentinelCtl.exe status

# Duo Authentication Proxy Installation (for RDP/RADIUS)
# Download from https://duo.com/docs/authproxy-reference
duoauthproxy-latest.exe /S

# Configure Duo Auth Proxy (authproxy.cfg)
# Location: C:\Program Files\Duo Security Authentication Proxy\conf\authproxy.cfg
[ad_client]
host=<AD_server_IP>
service_account_username=duo_service
service_account_password=<encrypted_password>
search_dn=DC=dealership,DC=local

[radius_server_auto]
ikey=<integration_key>
skey=<secret_key>
api_host=<api_hostname>.duosecurity.com
radius_ip_1=<fortigate_ip>
radius_secret_1=<shared_secret>
client=ad_client
failmode=safe

# Restart Duo Auth Proxy service
net stop DuoAuthProxy
net start DuoAuthProxy

# FortiGate — Configure RADIUS for Duo MFA on VPN
config user radius
  edit duo-radius
    set server <duo_proxy_ip>
    set secret <shared_secret>
  next
end
Note

FTC Safeguards Rule explicitly requires MFA for any individual accessing customer information. This is non-negotiable. Ensure every user who touches DMS, CRM, or analytics platform is enrolled in Duo before go-live. Configure Duo 'New User Policy' to 'Require enrollment' so new hires are automatically prompted. Document MFA enrollment in the compliance package.

Step 4: Email Domain Authentication Setup

Configure SPF, DKIM, and DMARC records for the dealership's email domain. This is critical for the outreach campaign emails to reach customer inboxes rather than being flagged as spam. Poor email authentication is the #1 cause of failed lifecycle marketing campaigns. Also configure the sending domain in the analytics platform (Affinitiv) and any supplemental email service (SendGrid).

DNS TXT Records to add at domain registrar/DNS host
dns
# DNS TXT Records to add at domain registrar/DNS host

# SPF Record (example — adjust include: values for actual mail services)
v=spf1 include:_spf.google.com include:sendgrid.net include:mail.affinitiv.com ~all

# DKIM — Generate via email provider (Google Workspace example)
# Add TXT record for selector:
# Host: google._domainkey.<dealership-domain>.com
# Value: v=DKIM1; k=rsa; p=<public_key_from_google_admin>

# SendGrid DKIM (if using Twilio SendGrid)
# Add CNAME records provided by SendGrid domain authentication wizard:
# s1._domainkey.<domain> -> s1.domainkey.uXXXXXX.wlXXX.sendgrid.net
# s2._domainkey.<domain> -> s2.domainkey.uXXXXXX.wlXXX.sendgrid.net

# DMARC Record
# Host: _dmarc.<dealership-domain>.com
# Value:
v=DMARC1; p=quarantine; rua=mailto:dmarc-reports@<dealership-domain>.com; ruf=mailto:dmarc-forensics@<dealership-domain>.com; pct=100

# Verify records
dig TXT <dealership-domain> +short
dig TXT _dmarc.<dealership-domain> +short
dig TXT google._domainkey.<dealership-domain> +short

# Test deliverability at mail-tester.com
# Send test email from dealership domain to the provided test address
Note

Start DMARC with p=none for the first 2 weeks to monitor without blocking, then move to p=quarantine after reviewing DMARC reports. Ensure the dealership's email provider (Google Workspace, Microsoft 365) is included in the SPF record along with Affinitiv and SendGrid. A mail-tester.com score of 9/10 or higher is the target before launching outreach campaigns.

Step 5: 10DLC SMS Campaign Registration

Register the dealership for 10DLC (10-Digit Long Code) messaging through The Campaign Registry (TCR) to enable compliant business SMS. Since 2023, all Application-to-Person (A2P) business SMS must be registered or carriers will filter/block messages. Register through Twilio's TCR integration or the analytics platform's built-in SMS provider. This step takes 1–4 weeks for approval, so initiate early.

Twilio CLI
shell
# Register 10DLC Brand (if using Twilio as SMS provider)

twilio api:messaging:v1:services:create --friendly-name 'DealershipServiceReminders'
  • Register Brand with TCR via Twilio Console: Navigate to Twilio Console > Messaging > Trust Hub > Brand Registrations
  • Enter business details: Legal Business Name: <Dealership Legal Name>
  • EIN: <Dealership EIN>
  • Business Type: Private Profit
  • Business Industry: Automotive
  • Business Registration Number: <State registration>
  • Website: <Dealership website URL>
  • Submit for vetting ($4 one-time fee)
  • Register Campaign after brand approval: Navigate to Twilio Console > Messaging > Trust Hub > Campaign Use Cases
  • Create campaign — Use Case: Mixed (covers service reminders + appointment confirmations)
  • Sample Message: 'Hi {FirstName}, your {Vehicle} is approaching its {Mileage}mi service. Schedule at {Link}. Reply STOP to opt out.'
  • Sample Message: '{FirstName}, your oil change is due. Book now: {Link}. Reply STOP to unsubscribe.'
  • Opt-in Description: Consent collected at service write-up via signed service agreement
  • Opt-out Keywords: STOP, UNSUBSCRIBE, CANCEL
  • Submit campaign ($10/month ongoing)
Assign phone number to Messaging Service
shell
twilio api:messaging:v1:services:phone-numbers:create \
  --service-sid <MESSAGING_SERVICE_SID> \
  --phone-number-sid <PHONE_NUMBER_SID>
Note

10DLC registration can take 1–4 weeks for brand vetting and campaign approval. Start this step in parallel with other work. Use 'Mixed' use case category to cover both service reminders (informational) and promotional offers. The dealership must have documented opt-in consent processes — verbal consent at service write-up is acceptable but written/digital consent is stronger for TCPA defense. Keep sample messages purely informational to maximize carrier approval rates.

Step 6: DMS Data Extraction and Quality Assessment

Connect to the dealership's DMS and extract historical service data for analysis and import into the analytics platform. Assess data quality: completeness of mileage readings, accuracy of customer contact information, VIN validity, and service type categorization. Clean and deduplicate records before importing into Affinitiv. This step is critical — poor data quality is the #1 cause of failed predictive analytics implementations.

CDK Fortellis API calls to retrieve service repair orders and customer records, plus a Python data quality assessment script
bash
# CDK Fortellis API — Example: Retrieve Service Repair Orders
curl -X GET 'https://api.fortellis.io/cdkdrive/service/v1/repair-orders?fromDate=2023-01-01&toDate=2024-12-31&status=closed' \
  -H 'Authorization: Bearer <access_token>' \
  -H 'Subscription-Id: <subscription_id>' \
  -H 'Accept: application/json'

# Example: Retrieve Customer Records
curl -X GET 'https://api.fortellis.io/cdkdrive/crm/v1/customers?pageSize=100&page=1' \
  -H 'Authorization: Bearer <access_token>' \
  -H 'Subscription-Id: <subscription_id>' \
  -H 'Accept: application/json'

# Python script for data quality assessment (run locally)
import pandas as pd
import json

# Load exported RO data (CSV or JSON from DMS)
df = pd.read_csv('repair_orders_export.csv')

# Data quality checks
print('=== DATA QUALITY REPORT ===')
print(f'Total Records: {len(df)}')
print(f'Missing Email: {df["email"].isna().sum()} ({df["email"].isna().mean()*100:.1f}%)')
print(f'Missing Phone: {df["phone"].isna().sum()} ({df["phone"].isna().mean()*100:.1f}%)')
print(f'Missing Mileage: {df["mileage"].isna().sum()} ({df["mileage"].isna().mean()*100:.1f}%)')
print(f'Invalid VINs: {(df["vin"].str.len() != 17).sum()}')
print(f'Duplicate Customers: {df["customer_id"].duplicated().sum()}')
print(f'Date Range: {df["ro_date"].min()} to {df["ro_date"].max()}')
print(f'\nService Types Distribution:')
print(df['service_type'].value_counts().head(20))
Note

For Reynolds & Reynolds DMS, data extraction requires a direct partnership arrangement or an approved data partner like Affinitiv (which already has R&R integration). CDK Fortellis API access costs $175–$400+/month per integration — confirm whether Affinitiv's existing CDK integration covers this or if separate API subscriptions are needed. Target data quality thresholds: >80% of records with valid email, >70% with valid phone, >90% with mileage at last service, 100% with valid VIN. Records below these thresholds need remediation before import.

Step 7: Affinitiv Platform Provisioning and DMS Integration

Work with Affinitiv's onboarding team to provision the dealership's Affinitiv Essentials account. Configure the DMS integration feed (Affinitiv has pre-built connectors for CDK, Reynolds, and Dealertrack). Map data fields between DMS and Affinitiv. Configure the dealership profile including OEM affiliation, hours of operation, service capacity, and branding assets. Import historical service data and customer records.

FortiGate firewall configuration for Affinitiv IP whitelisting and DMS integration verification
bash
# Affinitiv provisioning is vendor-managed via their onboarding portal
# MSP responsibilities during this step:

# 1. Ensure DMS API credentials are available
#    - CDK: Generate Fortellis API key in CDK admin portal
#    - Reynolds: Provide approved data partner credentials
#    - Dealertrack: Configure Cox integration layer

# 2. Whitelist Affinitiv IP ranges on firewall
# FortiGate CLI:
config firewall address
  edit affinitiv-cloud
    set type iprange
    set start-ip <affinitiv_ip_start>
    set end-ip <affinitiv_ip_end>
    set comment 'Affinitiv Analytics Platform'
  next
end

config firewall policy
  edit 200
    set name allow-dms-to-affinitiv
    set srcintf vlan10-dms
    set dstintf wan1
    set srcaddr all
    set dstaddr affinitiv-cloud
    set action accept
    set schedule always
    set service HTTPS
    set logtraffic all
    set utm-status enable
    set ssl-ssh-profile deep-inspection
  next
end

# 3. Verify data flow after integration
#    - Confirm Affinitiv dashboard shows customer count matching DMS
#    - Verify service history depth (should show 12-24 months)
#    - Check VIN decode accuracy (year/make/model populated)
#    - Validate mileage tracking and interval calculations
Note

Affinitiv's onboarding typically takes 2–3 weeks. The MSP role is primarily network/firewall configuration and DMS credential provisioning — the data integration itself is managed by Affinitiv's integration engineers. Schedule a joint call with Affinitiv onboarding, the dealership's DMS administrator, and the MSP to ensure all parties are aligned. Confirm that Affinitiv's data feed is encrypted in transit (TLS 1.2+) and document this for FTC Safeguards compliance.

Step 8: Configure Maintenance Milestone Rules and Triggers

Define the maintenance milestones that will trigger proactive outreach. Work with the dealership's service director to customize intervals based on their OEM requirements, regional factors (climate, road conditions), and customer driving patterns. Configure these rules in Affinitiv's campaign engine. Standard milestones include: oil change (every 5,000–7,500 miles or 6 months), tire rotation (every 5,000–7,500 miles), brake inspection (every 15,000–20,000 miles), transmission flush (every 30,000–60,000 miles), timing belt replacement (60,000–100,000 miles based on OEM), coolant flush (every 30,000 miles or 2 years), cabin air filter (every 15,000–20,000 miles), and manufacturer-recommended service intervals at 15K, 30K, 60K, 90K, and 100K+ miles.

Milestone trigger rules to configure in Affinitiv Campaign Manager
# Affinitiv milestone configuration is done through the vendor's admin portal
# The following represents the logical rules to configure:

# MILESTONE TRIGGER RULES (configure in Affinitiv Campaign Manager)
# ================================================================

# Rule 1: Oil Change Reminder
# Trigger: (Current_Date - Last_Oil_Change_Date >= 150 days) OR
#          (Estimated_Current_Mileage - Last_Oil_Change_Mileage >= 4,500 miles)
# Lead Time: 500 miles or 30 days BEFORE due date
# Channels: Email (Day 0), SMS (Day 3 if no open), Direct Mail (Day 7 if no engagement)

# Rule 2: Tire Rotation
# Trigger: Estimated_Current_Mileage - Last_Tire_Rotation_Mileage >= 6,500 miles
# Lead Time: 500 miles before due
# Channels: Email + SMS (same day)

# Rule 3: Brake Inspection
# Trigger: Estimated_Current_Mileage - Last_Brake_Service_Mileage >= 14,000 miles
# Lead Time: 1,000 miles before due
# Channels: Email (Day 0), Phone/Voice (Day 5 if no response), Direct Mail (Day 10)

# Rule 4: Major Service Milestones (30K/60K/90K)
# Trigger: Estimated_Current_Mileage approaching 28K/58K/88K (2,000 mile buffer)
# Lead Time: 2,000 miles before milestone
# Channels: Email + SMS + Direct Mail (high-value service, use all channels)

# Rule 5: Timing Belt (applicable VINs only)
# Trigger: VIN decode shows interference engine AND mileage approaching 55,000+
# Lead Time: 5,000 miles before OEM recommended interval
# Channels: Email + Phone (high urgency, safety-critical)

# Mileage Estimation Formula (used by Affinitiv):
# Estimated_Current_Mileage = Last_Recorded_Mileage + 
#   (Average_Daily_Miles * Days_Since_Last_Visit)
# where Average_Daily_Miles = Total_Miles_Driven / Total_Days_In_Service_History
Note

Affinitiv's AI engine automatically maps OEM maintenance schedules to VINs, so many of these rules are pre-configured. The MSP and dealership service director should review and customize the timing, lead times, and channel preferences. Key customization points: (1) lead time before milestone — too early and customers forget, too late and they've already gone elsewhere; (2) channel escalation sequence — start with low-cost email, escalate to SMS, then voice/mail; (3) customer segmentation — VIP/high-value customers may get phone calls instead of just email. Document all configured rules for the client handoff package.

Step 9: Outreach Campaign Template Configuration

Design and configure the email, SMS, and direct mail templates that will be sent to customers when milestone triggers fire. Templates must be CAN-SPAM compliant (email), TCPA compliant (SMS), and branded to the dealership. Work with the dealership's marketing manager and Affinitiv's creative team to customize templates. Configure personalization tokens (customer name, vehicle year/make/model, service type, estimated mileage, booking link).

  • SMS Template Examples (configure in Affinitiv or Twilio)
  • Note: Keep under 160 chars for single-segment delivery
  • Oil Change Reminder: Hi {FirstName}, your {Year} {Make} {Model} is due for an oil change at ~{EstMileage}mi. Book now: {BookingLink} Reply STOP to opt out
  • Brake Inspection: {FirstName}, it's time for a brake inspection on your {Vehicle}. Stay safe — schedule today: {BookingLink} Reply STOP to opt out
  • 30K/60K/90K Service: {FirstName}, your {Vehicle} is approaching {Milestone} miles! Schedule your {Milestone}-mile service: {BookingLink} Reply STOP to opt out
  • Email Template Structure (HTML — configure in Affinitiv Campaign Manager)
  • Subject Lines to A/B Test — A: '{FirstName}, your {Vehicle} is due for service' | B: 'Time for your {ServiceType} — schedule in seconds' | C: 'Don't wait — your {Year} {Make} {Model} needs attention'
  • Email must include: Dealership logo and branding
  • Email must include: Customer name and vehicle details
  • Email must include: Specific service recommendation with description
  • Email must include: One-click booking button (links to Xtime scheduler)
  • Email must include: Physical dealership address (CAN-SPAM requirement)
  • Email must include: Unsubscribe link (CAN-SPAM requirement)
  • Email must include: Service department phone number
  • Email must include: Service coupon/offer (optional — use sparingly per TCPA)
SendGrid API — Send test email (if supplementing Affinitiv)
bash
curl -X POST 'https://api.sendgrid.com/v3/mail/send' \
  -H 'Authorization: Bearer <SENDGRID_API_KEY>' \
  -H 'Content-Type: application/json' \
  -d '{
    "personalizations": [{
      "to": [{"email": "test@dealership.com"}],
      "dynamic_template_data": {
        "first_name": "John",
        "vehicle": "2022 Toyota Camry",
        "service_type": "Oil Change",
        "booking_link": "https://schedule.xtime.com/dealership"
      }
    }],
    "from": {"email": "service@dealership.com", "name": "ABC Toyota Service"},
    "template_id": "<TEMPLATE_ID>"
  }'
Critical

CRITICAL TCPA COMPLIANCE: SMS messages should be informational (service reminders) not promotional. Avoid words like 'sale', 'discount', 'special offer' in SMS — these cross the line into marketing and require higher-tier consent. If including promotional content, ensure the customer has given express written consent (not just verbal). Every SMS must include opt-out instructions. Every email must include physical address and unsubscribe link. A/B test subject lines for the first 30 days to optimize open rates before scaling.

Step 10: Xtime Service Scheduler Integration

Configure Xtime Schedule to serve as the appointment booking destination for all outreach campaign links. Integrate Xtime with the DMS to ensure real-time service lane capacity is reflected in available appointment slots. Configure the online booking widget with dealership branding, service menu, and advisor selection. Generate unique booking URLs for campaign tracking.

Xtime configuration tasks via Cox Automotive admin portal
bash
# Xtime configuration is performed through the Cox Automotive admin portal
# MSP tasks:

# 1. Ensure Xtime is integrated with the DMS
#    - CDK Drive: Xtime has native integration — verify in Xtime admin > DMS Settings
#    - Dealertrack: Native Cox ecosystem integration
#    - Reynolds: Requires Xtime API bridge — contact Xtime support

# 2. Configure UTM tracking parameters for campaign links
#    Base URL: https://schedule.xtime.com/<dealership_slug>
#    Campaign URL format:
#    https://schedule.xtime.com/<slug>?utm_source=affinitiv&utm_medium=email&utm_campaign=oil_change_reminder&utm_content={customer_id}

# 3. Set up Google Analytics tracking (if dealership has GA4)
#    Add Xtime booking page as a conversion event:
#    - Event name: service_appointment_booked
#    - Configure in GA4 > Admin > Events > Create Event

# 4. Verify real-time capacity sync
#    - Book a test appointment through Xtime widget
#    - Confirm it appears in DMS service schedule within 60 seconds
#    - Confirm advisor assignment and time slot accuracy

# 5. Configure automated appointment confirmation
#    - Email confirmation: enabled by default in Xtime
#    - SMS confirmation: enable in Xtime Settings > Communications
#    - Reminder: 24-hour and 2-hour pre-appointment reminders
Note

The Xtime booking link is the critical conversion point for the entire outreach system. Test the booking flow end-to-end from the customer's perspective: click link in email/SMS → see available appointments → select service → choose advisor → confirm booking → receive confirmation. Ensure the booking page loads in under 3 seconds on mobile (most customers will click from their phone). If the dealership doesn't have Xtime, alternatives include DealerSocket's scheduling module, Tekion's built-in scheduler, or a standalone tool like Calendly (not recommended for automotive due to lack of DMS integration).

Step 11: Cloud Backup and Disaster Recovery Configuration

Deploy the cloud backup solution (Axcient x360Recover or Datto BCDR) to protect on-premise DMS data, compliance documentation, and configuration files. Configure automated daily backups with 30-day retention. Set up backup verification and alerting. This fulfills the FTC Safeguards requirement for data availability and disaster recovery.

Axcient x360Recover Agent Installation (Windows Server) — Download agent from Axcient partner portal
shell
x360Recover-Agent-Setup.exe /silent /REGISTRATION_KEY=<key>
1
Select protected machine (DMS server)
2
Configure volumes: All data volumes (exclude temp/swap)
3
Schedule: Daily incremental at 11:00 PM, Weekly full on Sunday 2:00 AM
4
Retention: 30 daily, 12 weekly, 6 monthly
5
Enable AutoVerify (boots backup image to verify integrity)
6
Configure alerts: Email MSP NOC on backup failure
  • Run manual backup and confirm completion in Axcient console
  • Test restore of single file from latest backup
  • Document backup RPO (Recovery Point Objective): 24 hours
  • Document backup RTO (Recovery Time Objective): 4 hours (cloud spinup)
  • Create monitor in RMM (e.g., ConnectWise Automate): Check Axcient backup status daily at 7:00 AM
  • Alert conditions: Backup older than 26 hours, verification failed, agent offline
Note

FTC Safeguards Rule requires documented disaster recovery procedures. Create a one-page DR runbook specific to this dealership and include it in the compliance documentation package. If the dealership runs a cloud-only DMS (Tekion, cloud CDK), backup responsibility shifts to the DMS vendor — document their backup SLAs and include in the compliance file. The MSP should still back up local workstation configurations, firewall configs, and compliance documentation.

Step 12: FTC Safeguards Rule Compliance Documentation Package

Compile the complete Written Information Security Plan (WISP) and supporting compliance documentation required by the FTC Safeguards Rule. This package is both a regulatory requirement and a key MSP deliverable that justifies ongoing compliance-as-a-service fees. Include: risk assessment, information security policy, access control documentation, encryption inventory, incident response plan, vendor management inventory, and employee training records.

  • No CLI commands — this is a documentation step
  • Use MSP's compliance documentation template or tools like: Galactic Advisors compliance platform, Compliancy Group, ConnectWise Identify (compliance module)
  • REQUIRED DOCUMENTS (per FTC Safeguards Rule):
  • 1. Written Information Security Plan (WISP) — Scope: All systems handling customer NPI; Designated Qualified Individual: [Name and Title]; Risk assessment methodology; Safeguard descriptions for each identified risk
  • 2. Risk Assessment — Asset inventory (documented in Step 1); Threat identification; Vulnerability assessment; Risk ratings (High/Medium/Low); Mitigation plans with timelines
  • 3. Access Control Policy — User access list with role-based permissions; MFA implementation evidence (Duo enrollment report); Password policy (complexity, rotation, history); Termination procedures (access revocation within 24 hours)
  • 4. Encryption Inventory — Data at rest: DMS database encryption, full-disk encryption on workstations; Data in transit: TLS 1.2+ for all SaaS connections, VPN for remote access; Certificate inventory and expiration tracking
  • 5. Incident Response Plan — Detection procedures; Containment steps; FTC notification requirement (within 30 days for events affecting 500+ customers); Customer notification procedures per state law; Forensics and recovery procedures
  • 6. Vendor Management — List all vendors with customer data access; Affinitiv, Xtime, Twilio/SendGrid, CDK/Reynolds, etc.; Document each vendor's security certifications (SOC 2, ISO 27001); Review vendor contracts for data protection clauses
  • 7. Training Records — Annual security awareness training for all staff; Role-specific training for service advisors (handling customer data); Phishing simulation results
Note

The FTC Safeguards compliance package is one of the highest-value MSP deliverables in this engagement. Many dealerships are not yet compliant despite the requirements being in effect since June 2023. As of May 2024, dealerships must also notify the FTC of security events affecting 500+ customers within 30 days. Position the MSP as the Qualified Individual or support the dealership's designated QI with quarterly compliance reviews. This documentation justifies $500–$1,500/month in ongoing compliance-as-a-service fees.

Step 13: User Acceptance Testing and Staff Training

Conduct comprehensive testing of the entire system: DMS data flow → Affinitiv analytics → milestone trigger → outreach delivery → customer booking → DMS appointment creation. Train service advisors, BDC representatives, and the service director on the analytics dashboard, campaign monitoring, and customer response workflows. Verify end-to-end functionality with a controlled test group of 50–100 customers.

1
Test 1: Data Flow Verification — Confirm latest DMS repair orders appear in Affinitiv within 24 hours. Verify customer count in Affinitiv matches DMS active customer count (±5%). Check mileage estimation accuracy: compare predicted vs. actual for 10 recent ROs.
2
Test 2: Milestone Trigger Accuracy — Identify 10 customers manually who should be approaching oil change (from DMS data). Verify Affinitiv has flagged these same customers for outreach. Check for false positives: customers flagged who recently had service.
3
Test 3: Email Deliverability — Send test campaign to 50 internal/test email addresses. Check inbox placement (not spam folder) across Gmail, Outlook, Yahoo. Verify personalization tokens render correctly. Confirm unsubscribe link works. Check email rendering on mobile devices.
4
Test 4: SMS Delivery — Send test SMS to 10 internal phone numbers. Verify delivery within 60 seconds. Confirm STOP opt-out works (reply STOP, verify removal from future sends). Check message displays correctly on iOS and Android.
5
Test 5: Booking Flow — Click booking link from test email. Select service, choose time slot, confirm appointment. Verify appointment appears in DMS service schedule. Verify confirmation email/SMS received.
6
Test 6: Controlled Pilot Launch — Select 100 customers with upcoming oil change milestones. Launch campaign to pilot group only. Monitor for 7 days: open rates, click rates, bookings, opt-outs. Target: >25% open rate (email), >5% click rate, >2% booking rate. If opt-out rate >2%, review messaging and consent records.
Note

Do NOT launch to the full customer database without completing the pilot test. A botched mass outreach (wrong names, broken links, spam folder delivery) damages dealership reputation and creates TCPA liability. Schedule a 2-hour training session with the service team covering: (1) how to read the Affinitiv dashboard, (2) how to identify high-priority customers, (3) how to handle customer callbacks from outreach, (4) how to update customer preferences/opt-outs, and (5) escalation procedure for complaints. Record the training session for future new-hire onboarding.

Step 14: Full Production Launch and Performance Monitoring

After successful pilot testing, launch outreach campaigns to the full customer database. Configure ongoing performance monitoring dashboards and establish KPI review cadence with the dealership. Set up automated alerting for anomalies (sudden drop in delivery rates, spike in opt-outs, booking system errors). Begin the first 30-day optimization cycle.

  • Daily automated alerts (set up in Affinitiv + RMM): Email delivery rate > 95%, SMS delivery rate > 98%, Opt-out rate < 1% per campaign, Booking link uptime 100%, DMS data feed last sync < 24 hours ago
  • Weekly KPI review: Emails sent / delivered / opened / clicked, SMS sent / delivered / responded, Appointments booked from outreach, Appointment show rate from outreach, Revenue attributed to outreach-driven appointments, Cost per appointment booked
  • Monthly optimization: A/B test results review (subject lines, send times, channel mix), Customer segment performance comparison, Milestone trigger timing adjustment based on actual customer behavior, Campaign expansion — add new milestones or customer segments
  • Quarterly business review with dealership: ROI analysis (outreach cost vs. service revenue generated), Customer retention rate trend, Competitive comparison (service capture rate vs. local market), Compliance review and WISP update
Note

The first 30 days after launch are critical for optimization. Expect email open rates to start at 20–30% and improve to 30–45% with subject line and timing optimization. SMS response rates are typically 3–5x higher than email. The most impactful optimization lever is send timing — most dealership customers engage with service reminders on Tuesday–Thursday mornings (8–10 AM local time). Avoid Mondays (inbox overload) and weekends (perceived as spam). Track attribution carefully: use unique booking URLs per campaign to measure which milestones drive the most appointments.

Custom AI Components

Mileage Estimation Engine

Type: workflow A predictive workflow that estimates each customer's current vehicle mileage based on historical service visit data, enabling accurate milestone trigger timing even when real-time telematics data is unavailable. This is the core intelligence component that determines WHEN to reach out to each customer.

Implementation:

Mileage Estimation Engine — Logic Specification

Overview

This component calculates estimated current mileage for each vehicle in the customer database by analyzing historical service visit patterns. It runs daily as a batch process and updates the customer record with predicted mileage and next-milestone proximity scores.

Data Inputs

  • Service repair order history (from DMS via API): date, mileage, VIN, customer_id
  • VIN decode data: year, make, model, engine type
  • OEM maintenance schedule: mapped from VIN to interval table

Algorithm

python
import pandas as pd
from datetime import datetime, timedelta
import numpy as np

def estimate_current_mileage(customer_vehicles: pd.DataFrame) -> pd.DataFrame:
    """
    Estimate current mileage for each customer vehicle based on service history.
    
    Input DataFrame columns:
    - customer_id, vin, ro_date (datetime), ro_mileage (int), service_type
    
    Output DataFrame columns:
    - customer_id, vin, estimated_current_mileage, avg_daily_miles,
      confidence_score, last_visit_date, last_visit_mileage
    """
    results = []
    
    for (cust_id, vin), group in customer_vehicles.groupby(['customer_id', 'vin']):
        visits = group.sort_values('ro_date')
        
        if len(visits) < 2:
            # Single visit — use national average (37 miles/day = 13,500/yr)
            last_visit = visits.iloc[0]
            days_since = (datetime.now() - last_visit['ro_date']).days
            est_mileage = last_visit['ro_mileage'] + (37 * days_since)
            confidence = 0.3  # Low confidence with single data point
        else:
            # Multiple visits — calculate personalized driving rate
            first_visit = visits.iloc[0]
            last_visit = visits.iloc[-1]
            
            total_miles = last_visit['ro_mileage'] - first_visit['ro_mileage']
            total_days = (last_visit['ro_date'] - first_visit['ro_date']).days
            
            if total_days == 0:
                avg_daily_miles = 37  # Fallback to national average
                confidence = 0.3
            else:
                avg_daily_miles = total_miles / total_days
                
                # Confidence based on data points and recency
                recency_days = (datetime.now() - last_visit['ro_date']).days
                data_point_score = min(len(visits) / 5, 1.0)  # Max confidence at 5+ visits
                recency_score = max(1 - (recency_days / 730), 0.1)  # Decays over 2 years
                confidence = round(data_point_score * recency_score, 2)
            
            days_since = (datetime.now() - last_visit['ro_date']).days
            est_mileage = last_visit['ro_mileage'] + (avg_daily_miles * days_since)
        
        # Sanity bounds: 0-300 miles/day, mileage can't decrease
        avg_daily_miles = np.clip(avg_daily_miles if 'avg_daily_miles' in dir() else 37, 5, 300)
        est_mileage = max(est_mileage, last_visit['ro_mileage'])
        
        results.append({
            'customer_id': cust_id,
            'vin': vin,
            'estimated_current_mileage': int(est_mileage),
            'avg_daily_miles': round(avg_daily_miles, 1),
            'confidence_score': confidence,
            'last_visit_date': last_visit['ro_date'],
            'last_visit_mileage': int(last_visit['ro_mileage'])
        })
    
    return pd.DataFrame(results)


def calculate_milestone_proximity(vehicle_estimates: pd.DataFrame, 
                                   milestone_schedule: dict) -> pd.DataFrame:
    """
    Determine which maintenance milestones each vehicle is approaching.
    
    milestone_schedule example:
    {
        'oil_change': {'interval_miles': 5000, 'interval_days': 180, 'lead_miles': 500},
        'tire_rotation': {'interval_miles': 7500, 'interval_days': None, 'lead_miles': 500},
        'brake_inspection': {'interval_miles': 20000, 'interval_days': None, 'lead_miles': 1000},
        'transmission_flush': {'interval_miles': 30000, 'interval_days': None, 'lead_miles': 2000},
        'timing_belt': {'interval_miles': 60000, 'interval_days': None, 'lead_miles': 5000},
        '30k_service': {'interval_miles': 30000, 'interval_days': None, 'lead_miles': 2000},
        '60k_service': {'interval_miles': 60000, 'interval_days': None, 'lead_miles': 2000},
        '90k_service': {'interval_miles': 90000, 'interval_days': None, 'lead_miles': 2000},
    }
    """
    alerts = []
    
    for _, vehicle in vehicle_estimates.iterrows():
        est_miles = vehicle['estimated_current_mileage']
        
        for milestone_name, params in milestone_schedule.items():
            interval = params['interval_miles']
            lead = params['lead_miles']
            
            # Calculate next occurrence of this milestone
            miles_into_current_interval = est_miles % interval
            miles_to_next = interval - miles_into_current_interval
            
            # Check if within lead distance
            if miles_to_next <= lead:
                days_to_milestone = miles_to_next / max(vehicle['avg_daily_miles'], 1)
                
                alerts.append({
                    'customer_id': vehicle['customer_id'],
                    'vin': vehicle['vin'],
                    'milestone': milestone_name,
                    'estimated_miles_to_milestone': int(miles_to_next),
                    'estimated_days_to_milestone': int(days_to_milestone),
                    'estimated_current_mileage': est_miles,
                    'confidence_score': vehicle['confidence_score'],
                    'priority': 'high' if days_to_milestone <= 7 else 'medium' if days_to_milestone <= 21 else 'low'
                })
    
    return pd.DataFrame(alerts)

Deployment Notes

  • If using Affinitiv Essentials, this logic is built into the platform and does NOT need to be custom-built. The code above documents the logic for MSPs who need to understand the system or build a lightweight version for independent dealers not using Affinitiv.
  • For custom implementations, deploy as a Python script running on AWS Lambda (scheduled via EventBridge) or Azure Functions (timer trigger) on a daily cron schedule.
  • Output should feed into the outreach trigger system (next component).

Outreach Trigger and Channel Orchestration Workflow

Type: workflow

An automated workflow that takes milestone proximity alerts from the Mileage Estimation Engine and orchestrates multi-channel outreach in the correct sequence with appropriate delays, de-duplication, and compliance checks. Ensures customers receive the right message on the right channel at the right time.

Implementation:

Outreach Trigger & Channel Orchestration — n8n/Make.com Workflow Specification

This workflow runs daily, processes milestone alerts, applies business rules (suppression, de-duplication, compliance), and dispatches outreach via email, SMS, and optional voice channels in a waterfall sequence.

Workflow Definition (n8n JSON)

n8n workflow JSON
json
# Maintenance Milestone Outreach Orchestrator

{
  "name": "Maintenance Milestone Outreach Orchestrator",
  "nodes": [
    {
      "name": "Daily Trigger",
      "type": "n8n-nodes-base.cron",
      "parameters": {
        "triggerTimes": {
          "item": [{"hour": 7, "minute": 0}]
        }
      },
      "notes": "Runs daily at 7 AM local time"
    },
    {
      "name": "Fetch Milestone Alerts",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "{{$env.ANALYTICS_API_URL}}/api/v1/milestone-alerts?status=pending",
        "method": "GET",
        "authentication": "predefinedCredentialType",
        "headers": {"Authorization": "Bearer {{$env.ANALYTICS_API_KEY}}"}
      },
      "notes": "Pulls pending milestone alerts from Affinitiv API or custom analytics DB"
    },
    {
      "name": "Apply Suppression Rules",
      "type": "n8n-nodes-base.function",
      "parameters": {
        "functionCode": "const alerts = items.map(item => item.json);\nconst filtered = alerts.filter(alert => {\n  // Suppress if customer contacted in last 14 days\n  const lastContact = new Date(alert.last_outreach_date);\n  const daysSinceContact = (Date.now() - lastContact) / (1000*60*60*24);\n  if (daysSinceContact < 14) return false;\n  \n  // Suppress if customer opted out\n  if (alert.opt_out_status === true) return false;\n  \n  // Suppress if customer has active appointment\n  if (alert.has_pending_appointment === true) return false;\n  \n  // Suppress if customer visited in last 7 days\n  const lastVisit = new Date(alert.last_visit_date);\n  const daysSinceVisit = (Date.now() - lastVisit) / (1000*60*60*24);\n  if (daysSinceVisit < 7) return false;\n  \n  // Suppress if confidence score too low\n  if (alert.confidence_score < 0.2) return false;\n  \n  return true;\n});\nreturn filtered.map(a => ({json: a}));"
      },
      "notes": "Removes customers who should NOT receive outreach"
    },
    {
      "name": "Determine Channel",
      "type": "n8n-nodes-base.function",
      "parameters": {
        "functionCode": "return items.map(item => {\n  const alert = item.json;\n  let channel = 'email'; // Default\n  \n  // High priority (< 7 days to milestone): email + SMS\n  if (alert.priority === 'high') {\n    channel = 'email_and_sms';\n  }\n  \n  // Safety-critical services: add phone call\n  if (['timing_belt', 'brake_inspection'].includes(alert.milestone)) {\n    channel = 'email_sms_and_voice';\n  }\n  \n  // No email on file: SMS only\n  if (!alert.customer_email) {\n    channel = 'sms_only';\n  }\n  \n  // No phone on file: email only\n  if (!alert.customer_phone) {\n    channel = 'email_only';\n  }\n  \n  alert.outreach_channel = channel;\n  return {json: alert};\n});"
      }
    },
    {
      "name": "Route by Channel",
      "type": "n8n-nodes-base.switch",
      "parameters": {
        "dataPropertyName": "outreach_channel",
        "rules": [
          {"value": "email_only", "output": 0},
          {"value": "sms_only", "output": 1},
          {"value": "email_and_sms", "output": 2},
          {"value": "email_sms_and_voice", "output": 3}
        ]
      }
    },
    {
      "name": "Send Email (SendGrid)",
      "type": "n8n-nodes-base.sendGrid",
      "parameters": {
        "resource": "mail",
        "operation": "send",
        "fromEmail": "service@{{$env.DEALERSHIP_DOMAIN}}",
        "toEmail": "={{$json.customer_email}}",
        "subject": "={{$json.customer_first_name}}, your {{$json.vehicle_display}} is due for service",
        "templateId": "={{$json.milestone}}_email_template"
      }
    },
    {
      "name": "Send SMS (Twilio)",
      "type": "n8n-nodes-base.twilio",
      "parameters": {
        "operation": "send",
        "from": "{{$env.TWILIO_PHONE_NUMBER}}",
        "to": "={{$json.customer_phone}}",
        "message": "Hi {{$json.customer_first_name}}, your {{$json.vehicle_display}} is approaching its {{$json.milestone_display}} at ~{{$json.estimated_current_mileage}}mi. Schedule now: {{$json.booking_url}} Reply STOP to opt out"
      }
    },
    {
      "name": "Log Outreach",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "{{$env.ANALYTICS_API_URL}}/api/v1/outreach-log",
        "method": "POST",
        "body": {
          "customer_id": "={{$json.customer_id}}",
          "vin": "={{$json.vin}}",
          "milestone": "={{$json.milestone}}",
          "channel": "={{$json.outreach_channel}}",
          "timestamp": "={{$now.toISO()}}"
        }
      },
      "notes": "Log every outreach for compliance audit trail and suppression rule enforcement"
    }
  ]
}

Deployment Notes

  • If using Affinitiv Essentials, this orchestration is handled natively within the platform. The workflow above is for MSPs building custom solutions or supplementing Affinitiv's built-in outreach.
  • For custom deployments, host n8n on a Docker container (AWS ECS, Azure Container Instance, or self-hosted) or use Make.com (formerly Integromat) as a no-code alternative.
n8n self-hosted Docker run command
shell
docker run -d --name n8n -p 5678:5678 -v n8n_data:/home/node/.n8n n8nio/n8n
Warning

Ensure all outreach logs are retained for minimum 5 years for TCPA compliance (proof of consent and delivery records).

Type: integration An integration component that synchronizes customer communication preferences (opt-in/opt-out status) across the DMS, CRM, analytics platform, and outreach channels. Ensures TCPA and CAN-SPAM compliance by providing a single source of truth for consent status.

Purpose

Maintain a unified consent registry that all outreach systems check before sending any communication. This is the compliance backbone of the entire solution.

Data Model

Customer consent and audit log table definitions
sql
CREATE TABLE customer_consent (
    id SERIAL PRIMARY KEY,
    customer_id VARCHAR(50) NOT NULL,
    vin VARCHAR(17),
    channel VARCHAR(20) NOT NULL CHECK (channel IN ('email', 'sms', 'voice', 'direct_mail')),
    consent_status VARCHAR(20) NOT NULL CHECK (consent_status IN ('opted_in', 'opted_out', 'not_collected')),
    consent_method VARCHAR(50), -- 'service_agreement', 'web_form', 'verbal', 'text_keyword'
    consent_date TIMESTAMP,
    opt_out_date TIMESTAMP,
    opt_out_method VARCHAR(50), -- 'sms_stop', 'email_unsubscribe', 'phone_request', 'in_person'
    last_verified TIMESTAMP,
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW(),
    UNIQUE(customer_id, channel)
);

CREATE INDEX idx_consent_customer ON customer_consent(customer_id);
CREATE INDEX idx_consent_status ON customer_consent(consent_status);

-- Audit trail for compliance
CREATE TABLE consent_audit_log (
    id SERIAL PRIMARY KEY,
    customer_id VARCHAR(50) NOT NULL,
    channel VARCHAR(20) NOT NULL,
    previous_status VARCHAR(20),
    new_status VARCHAR(20),
    change_source VARCHAR(100), -- 'twilio_webhook', 'sendgrid_webhook', 'crm_sync', 'manual'
    changed_by VARCHAR(100),
    changed_at TIMESTAMP DEFAULT NOW(),
    raw_payload JSONB
);

Webhook Handlers

Flask webhook handlers and consent management functions
python
from flask import Flask, request, jsonify
from datetime import datetime
import psycopg2

app = Flask(__name__)

# Twilio SMS opt-out webhook (receives STOP messages)
@app.route('/webhooks/twilio/opt-out', methods=['POST'])
def twilio_opt_out():
    from_number = request.form.get('From')
    body = request.form.get('Body', '').strip().upper()
    
    if body in ['STOP', 'UNSUBSCRIBE', 'CANCEL', 'QUIT', 'END']:
        update_consent(
            phone=from_number,
            channel='sms',
            new_status='opted_out',
            method='sms_stop',
            source='twilio_webhook',
            raw_payload=dict(request.form)
        )
    elif body in ['START', 'SUBSCRIBE', 'YES']:
        update_consent(
            phone=from_number,
            channel='sms',
            new_status='opted_in',
            method='sms_start',
            source='twilio_webhook',
            raw_payload=dict(request.form)
        )
    
    return '', 200

# SendGrid email unsubscribe webhook
@app.route('/webhooks/sendgrid/events', methods=['POST'])
def sendgrid_events():
    events = request.json
    for event in events:
        if event.get('event') in ['unsubscribe', 'group_unsubscribe', 'spamreport']:
            update_consent(
                email=event.get('email'),
                channel='email',
                new_status='opted_out',
                method=f'email_{event["event"]}',
                source='sendgrid_webhook',
                raw_payload=event
            )
    return '', 200

# CRM sync endpoint (called by CRM when preference updated)
@app.route('/api/v1/consent/sync', methods=['POST'])
def crm_consent_sync():
    data = request.json
    update_consent(
        customer_id=data['customer_id'],
        channel=data['channel'],
        new_status=data['consent_status'],
        method=data.get('method', 'crm_update'),
        source='crm_sync',
        raw_payload=data
    )
    return jsonify({'status': 'synced'}), 200

# Consent check endpoint (called by outreach workflow before sending)
@app.route('/api/v1/consent/check', methods=['GET'])
def check_consent():
    customer_id = request.args.get('customer_id')
    channel = request.args.get('channel')
    
    conn = get_db_connection()
    cur = conn.cursor()
    cur.execute(
        'SELECT consent_status FROM customer_consent WHERE customer_id = %s AND channel = %s',
        (customer_id, channel)
    )
    result = cur.fetchone()
    conn.close()
    
    if result is None:
        return jsonify({'customer_id': customer_id, 'channel': channel, 'consent': 'not_collected', 'can_send': False})
    
    can_send = result[0] == 'opted_in'
    return jsonify({'customer_id': customer_id, 'channel': channel, 'consent': result[0], 'can_send': can_send})

def update_consent(customer_id=None, phone=None, email=None, channel=None, 
                   new_status=None, method=None, source=None, raw_payload=None):
    conn = get_db_connection()
    cur = conn.cursor()
    
    # Resolve customer_id from phone or email if not provided
    if not customer_id and phone:
        cur.execute('SELECT customer_id FROM customers WHERE phone = %s', (phone,))
        result = cur.fetchone()
        customer_id = result[0] if result else None
    elif not customer_id and email:
        cur.execute('SELECT customer_id FROM customers WHERE email = %s', (email,))
        result = cur.fetchone()
        customer_id = result[0] if result else None
    
    if not customer_id:
        conn.close()
        return
    
    # Get current status for audit log
    cur.execute('SELECT consent_status FROM customer_consent WHERE customer_id = %s AND channel = %s',
                (customer_id, channel))
    current = cur.fetchone()
    previous_status = current[0] if current else None
    
    # Upsert consent record
    opt_out_date = datetime.now() if new_status == 'opted_out' else None
    cur.execute('''
        INSERT INTO customer_consent (customer_id, channel, consent_status, consent_method, consent_date, opt_out_date, opt_out_method, updated_at)
        VALUES (%s, %s, %s, %s, %s, %s, %s, NOW())
        ON CONFLICT (customer_id, channel) DO UPDATE SET
            consent_status = EXCLUDED.consent_status,
            opt_out_date = EXCLUDED.opt_out_date,
            opt_out_method = EXCLUDED.opt_out_method,
            updated_at = NOW()
    ''', (customer_id, channel, new_status, method, datetime.now(), opt_out_date, method if new_status == 'opted_out' else None))
    
    # Audit log
    import json
    cur.execute('''
        INSERT INTO consent_audit_log (customer_id, channel, previous_status, new_status, change_source, changed_by, raw_payload)
        VALUES (%s, %s, %s, %s, %s, %s, %s)
    ''', (customer_id, channel, previous_status, new_status, source, 'system', json.dumps(raw_payload) if raw_payload else None))
    
    conn.commit()
    conn.close()

def get_db_connection():
    return psycopg2.connect(
        host=os.environ['DB_HOST'],
        database=os.environ['DB_NAME'],
        user=os.environ['DB_USER'],
        password=os.environ['DB_PASSWORD']
    )

Deployment

  • Deploy as a Flask microservice on AWS ECS Fargate or Azure App Service
  • Database: PostgreSQL on AWS RDS or Azure Database for PostgreSQL (smallest tier: ~$15/month)
  • If using Affinitiv Essentials, consent management is built-in — this component is only needed for custom implementations or as a supplemental compliance layer
  • Retain all audit logs for minimum 5 years (TCPA statute of limitations is 4 years)

Service Revenue Attribution Dashboard

Type: integration A reporting dashboard that tracks the ROI of the predictive outreach system by attributing service appointments and revenue back to specific outreach campaigns. Provides the dealership with clear evidence that the AI investment is generating measurable returns. Implementation:

Service Revenue Attribution Dashboard — Power BI / Google Looker Studio Specification

Overview

Connects outreach campaign data (emails sent, SMS delivered, appointments booked) with DMS service revenue data to calculate cost-per-appointment, revenue-per-campaign, and overall ROI.

Data Sources

1
Outreach Log (from Affinitiv or custom workflow): campaign_id, customer_id, channel, sent_date, opened, clicked, booked_appointment
2
DMS Service Revenue (from CDK/Reynolds API): repair_order_id, customer_id, ro_date, total_revenue, labor_revenue, parts_revenue, service_type
3
Appointment Data (from Xtime): appointment_id, customer_id, source, scheduled_date, show_status

Attribution Logic

Attribution query linking outreach campaigns to DMS service revenue using last-touch attribution within a 30-day window
sql
-- Attribution query: link outreach to revenue
WITH outreach_touches AS (
    SELECT 
        ol.customer_id,
        ol.campaign_id,
        ol.milestone,
        ol.channel,
        ol.sent_date,
        ol.opened,
        ol.clicked
    FROM outreach_log ol
    WHERE ol.sent_date >= CURRENT_DATE - INTERVAL '90 days'
),
service_visits AS (
    SELECT
        ro.customer_id,
        ro.repair_order_id,
        ro.ro_date,
        ro.total_revenue,
        ro.labor_revenue,
        ro.parts_revenue,
        ro.service_type
    FROM dms_repair_orders ro
    WHERE ro.ro_date >= CURRENT_DATE - INTERVAL '90 days'
),
attributed_revenue AS (
    SELECT
        ot.campaign_id,
        ot.milestone,
        ot.channel,
        sv.repair_order_id,
        sv.ro_date,
        sv.total_revenue,
        sv.labor_revenue,
        sv.parts_revenue,
        -- Attribution window: service visit within 30 days of outreach
        CASE 
            WHEN sv.ro_date BETWEEN ot.sent_date AND ot.sent_date + INTERVAL '30 days' 
            THEN 'attributed'
            ELSE 'organic'
        END as attribution_status,
        ROW_NUMBER() OVER (
            PARTITION BY sv.repair_order_id 
            ORDER BY ot.sent_date DESC
        ) as touch_rank  -- Last-touch attribution
    FROM service_visits sv
    LEFT JOIN outreach_touches ot ON sv.customer_id = ot.customer_id
)
SELECT
    campaign_id,
    milestone,
    channel,
    COUNT(DISTINCT repair_order_id) as attributed_ros,
    SUM(total_revenue) as total_attributed_revenue,
    SUM(labor_revenue) as labor_revenue,
    SUM(parts_revenue) as parts_revenue,
    AVG(total_revenue) as avg_ro_value
FROM attributed_revenue
WHERE attribution_status = 'attributed' AND touch_rank = 1
GROUP BY campaign_id, milestone, channel
ORDER BY total_attributed_revenue DESC;

Dashboard KPIs

Power BI Implementation

  • Connect to Affinitiv reporting API or export CSV
  • Connect to DMS data warehouse or API
  • Create data model with relationships on customer_id
  • Build dashboard pages: Executive Summary, Campaign Performance, Milestone Breakdown, Channel Comparison, Monthly Trends
  • Schedule daily data refresh
  • Share via Power BI Service with dealership GM and Fixed Ops Director

Alternative: Google Looker Studio (Free)

  • Use Google Sheets as intermediate data store
  • Automate data pull via Google Apps Script + API connectors
  • Build equivalent dashboard with free Looker Studio
  • Best for budget-conscious single-rooftop dealers

Testing & Validation

  • Data Flow Test: Verify that the last 24 hours of DMS repair orders appear in the Affinitiv dashboard within the expected sync interval. Compare a random sample of 20 repair orders in DMS against Affinitiv records — customer name, VIN, mileage, service date, and service type should all match.
  • Mileage Estimation Accuracy Test: Select 10 customers who visited the dealership in the past week. Compare Affinitiv's predicted mileage (before their visit) against the actual mileage recorded on their repair order. Acceptable accuracy: predicted mileage within ±1,500 miles of actual for customers with 3+ prior visits.
  • Milestone Trigger Test: Manually identify 5 customers from DMS data who are clearly due for an oil change (last oil change >5,000 miles and >5 months ago). Verify that Affinitiv has flagged all 5 for outreach. Also verify that 5 customers who recently had oil changes are NOT flagged (false positive check).
  • Email Deliverability Test: Send a test outreach email campaign to 50 internal test addresses across Gmail, Outlook.com, Yahoo Mail, and the dealership's own domain. Verify: (1) >95% delivery rate, (2) 0% land in spam folder, (3) personalization tokens render correctly (first name, vehicle, mileage), (4) booking link resolves to Xtime scheduler, (5) unsubscribe link functions.
  • SMS Delivery Test: Send test SMS to 10 internal phone numbers across AT&T, Verizon, and T-Mobile carriers. Verify: (1) delivery within 60 seconds, (2) message displays correctly on iOS and Android, (3) reply STOP triggers opt-out and confirmation reply, (4) booking link is clickable and resolves correctly.
  • Booking Link End-to-End Test: Click the booking URL from a test outreach email on a mobile device. Complete the full booking flow: select service type → choose date/time → select service advisor → confirm appointment. Verify the appointment appears in the DMS service schedule within 2 minutes and that a confirmation email/SMS is received by the customer.
  • Opt-Out Compliance Test: Send test SMS, reply STOP, verify opt-out confirmation is received, then trigger another outreach campaign — verify the opted-out number does NOT receive any further messages. Repeat for email: click unsubscribe link, verify removal confirmation, trigger new campaign, verify no email sent.
  • Suppression Rules Test: Verify that a customer who has a pending service appointment does NOT receive a new outreach message for the same service type. Verify that a customer who was contacted in the last 14 days does NOT receive another message regardless of milestone status. Verify that customers flagged as 'do not contact' in the CRM are excluded from all campaigns.
  • Network Security Validation: Run a vulnerability scan (Nessus or Qualys) against the dealership network from outside the firewall. Verify: (1) no open ports except authorized services, (2) TLS 1.2+ on all web interfaces, (3) VPN access requires MFA (test Duo challenge), (4) guest WiFi VLAN cannot access DMS VLAN (attempt ping from guest to DMS server IP — should fail).
  • FTC Safeguards Compliance Audit: Walk through the complete WISP documentation and verify each control is implemented: (1) MFA enrolled for all users (pull Duo enrollment report), (2) encryption at rest enabled (BitLocker on workstations, database encryption on server), (3) backup running and verified (pull Axcient backup report), (4) incident response plan reviewed and contact list current, (5) vendor security certifications documented.
  • Performance Baseline Test: Before launch, document the dealership's current monthly service appointment count, service revenue, and customer return rate (past 90 days). These baselines will be used to measure the impact of the predictive outreach system at the 30, 60, and 90-day post-launch reviews.
  • Load and Capacity Test: Simulate a full campaign launch by scheduling outreach to 1,000 customers simultaneously. Verify: (1) emails queue and send within 2 hours without triggering rate limits, (2) SMS messages send within 4 hours without carrier throttling, (3) Xtime booking page remains responsive under increased traffic (check page load time <3 seconds), (4) no errors in outreach log.

Client Handoff

Client Handoff Checklist

Training Sessions (schedule 2 sessions, 2 hours each)

Session 1: Service Advisors and BDC Team (2 hours)

  • How to read the Affinitiv dashboard: understanding milestone alerts, customer priority scores, and outreach status
  • How to handle inbound calls from customers who received outreach messages: scripts for confirming service needs, booking appointments, and upselling additional recommended services
  • How to update customer contact preferences and opt-out requests in the CRM
  • How to recognize and handle TCPA-related customer complaints (when to escalate to management vs. MSP)
  • How to use the Xtime scheduler to manage increased appointment volume from outreach campaigns
  • Demonstration of the SMS opt-out flow and email unsubscribe process

Session 2: Service Director / Fixed Ops Manager / General Manager (2 hours)

  • Dashboard walkthrough: how to read campaign performance KPIs (open rates, booking rates, attributed revenue)
  • How to request campaign adjustments: timing changes, new milestone additions, template modifications
  • Monthly and quarterly ROI review process: what numbers to look at and how to interpret them
  • Compliance responsibilities: annual WISP review, employee training requirements, incident reporting obligations
  • Escalation paths: when to call the MSP vs. Affinitiv support vs. DMS vendor

Documentation Package (leave behind)

1
System Architecture Diagram: Visual showing DMS → Affinitiv → Outreach channels → Xtime booking flow
2
Login Credentials Sheet: All platform credentials (Affinitiv admin, Xtime admin, Twilio console, SendGrid) stored in a password manager — provide access, not plaintext
3
Campaign Rules Reference: Document listing all configured milestone triggers, timing rules, channel sequences, and suppression rules
4
Template Gallery: Copies of all email and SMS templates with personalization token reference
5
Compliance Binder: Complete FTC Safeguards WISP, incident response plan, vendor security inventory, training records, consent management procedures
6
Escalation Contact Sheet: MSP support number and hours, Affinitiv support contact, CDK/DMS support contact, Xtime support contact
7
Quick Reference Card: Laminated card for service advisors with the top 5 tasks they need to know (how to check dashboard, update opt-out, book from alert, run report, escalate issue)

Success Criteria Review (at 30-day mark)

Maintenance

Ongoing Maintenance Responsibilities

Daily (Automated Monitoring)

  • DMS data feed health check: Verify Affinitiv is receiving DMS data within expected intervals. Alert if no new data received in 24+ hours. Root cause: API key expiration, DMS server offline, network connectivity issue.
  • Email/SMS delivery monitoring: Check delivery rates in Affinitiv/SendGrid/Twilio dashboards. Alert if email delivery drops below 90% or SMS delivery drops below 95%. Root cause: domain reputation issue, 10DLC suspension, sender blacklisting.
  • Backup verification: Confirm daily backup completed successfully via Axcient/Datto dashboard. Alert on any failed backup. RPO: 24 hours.
  • Endpoint security status: Verify SentinelOne agents are online and reporting on all endpoints via management console. Alert on any offline agent >4 hours.

Weekly (MSP Technician — 30 minutes)

  • Review Affinitiv campaign performance dashboard: open rates, click rates, booking rates, opt-out rates.
  • Check for any customer complaints or escalations logged by dealership staff.
  • Verify MFA enrollment is current (check for new hires who need Duo enrollment).
  • Review firewall logs for any blocked intrusion attempts or anomalous traffic.
  • Confirm 10DLC campaign status is active and healthy in Twilio console.

Monthly (MSP Account Manager — 1 hour + reporting)

  • Generate monthly performance report: outreach volume, engagement rates, appointments booked, attributed service revenue, campaign ROI.
  • Present report to dealership Fixed Ops Director or General Manager.
  • Review and tune milestone trigger timing based on actual customer behavior data.
  • A/B test new email subject lines or SMS copy variants.
  • Update SPF/DKIM/DMARC records if any email infrastructure changes occurred.
  • Verify all software subscriptions are current (Affinitiv, SentinelOne, Duo, Axcient, Proofpoint).
  • Patch/update FortiGate firmware if new version available (schedule during off-hours).

Quarterly (MSP Security Specialist — 2-4 hours)

  • FTC Safeguards compliance review: update WISP, review risk assessment, verify all controls are functioning.
  • Run vulnerability scan on dealership network (Nessus/Qualys).
  • Review and update vendor security inventory (check for any new vendor SOC 2 reports).
  • Conduct phishing simulation for dealership staff and document results.
  • Review access control lists: remove terminated employees, verify role-based permissions.
  • Test incident response plan with tabletop exercise (annual requirement, quarterly recommended).
  • Review data retention policies and purge expired records per policy.

Annually

  • Full FTC Safeguards audit with updated Written Information Security Plan.
  • Renew all security certifications and subscriptions.
  • Hardware lifecycle review: assess server, firewall, switch, and workstation age and plan replacements.
  • Comprehensive penetration test (external firm recommended).
  • Annual security awareness training for all dealership staff (document for compliance).
  • Review Affinitiv contract and negotiate renewal terms.
  • Evaluate new platform capabilities or competitive alternatives.

SLA Considerations

  • Critical (DMS data feed down, outreach system offline): 4-hour response, 8-hour resolution during business hours.
  • High (email/SMS delivery degraded, security alert): 8-hour response, 24-hour resolution.
  • Medium (dashboard reporting issue, template change request): 24-hour response, 72-hour resolution.
  • Low (new feature request, optimization suggestion): Next scheduled maintenance window.

Escalation Paths

  • Tier 1 (Dealership Staff): Basic issues — restart Affinitiv dashboard, clear browser cache, verify internet connectivity. Escalate to MSP if unresolved in 15 minutes.
  • Tier 2 (MSP Help Desk): Integration issues, API errors, email deliverability problems, user access issues. Escalate to Tier 3 if requires vendor engagement.
  • Tier 3 (MSP Senior Engineer + Vendor): DMS API changes, Affinitiv platform issues, CDK/Reynolds escalation, security incidents. Joint troubleshooting with vendor support.
  • Security Incident: Immediate MSP notification → follow incident response plan → contain threat → assess scope → notify FTC if required (500+ customer records) → notify affected customers per state law.

Alternatives

...

AutoAlert AlertMiner + Equity Mining Approach

Replace Affinitiv Essentials with AutoAlert's AlertMiner platform, which combines service milestone detection with equity mining capabilities. AutoAlert identifies not only customers due for service but also those in favorable equity positions for vehicle trade-in/upgrade, enabling the dealership to monetize both service retention and vehicle sales opportunities from the same data platform.

automotiveMastermind Market EyeQ (Enterprise Tier)

Deploy automotiveMastermind's Market EyeQ platform, which leverages S&P Global Mobility's IHS Markit vehicle registration and ownership data for superior predictive accuracy. This approach adds external data sources (vehicle registration transfers, competitive market activity, demographic data) on top of the dealership's internal DMS data for more precise customer lifecycle predictions.

DIY Custom Build with CRM + Twilio + Power Automate

Build a lightweight custom solution using the dealership's existing CRM (VinSolutions, DealerSocket, or Elead), Microsoft Power Automate for workflow orchestration, Twilio for SMS, and SendGrid for email. Extract service history data via DMS API or scheduled CSV exports, apply simple mileage-based rules in Power Automate, and trigger outreach without a dedicated analytics platform.

Cox Automotive Full-Stack Approach (Dealertrack + VinSolutions + Xtime)

Tekion Automotive Retail Cloud (Cloud-Native Approach)

Migrate the dealership to Tekion's cloud-native Automotive Retail Cloud, which includes built-in AI/ML for service predictions, customer lifecycle management, and automated outreach — all within a single modern platform that replaces the traditional DMS + CRM + analytics stack. Tekion leverages AI-driven machine learning for upselling, cross-selling, and operational efficiency.

Want early access to the full toolkit?