customeragent-api / CONTACT_TRACKING_GUIDE.md
anasraza526's picture
Clean deploy to Hugging Face
ac90985

Contact Request & IP Tracking Implementation

βœ… Features Implemented

1. Contact Request Storage

File: app/models/contact_request.py

What It Stores:

  • βœ… User information (name, email, phone, message)
  • βœ… Full chat context (entire conversation)
  • βœ… IP address tracking
  • βœ… User agent (browser info)
  • βœ… Status tracking (pending β†’ contacted β†’ resolved)
  • βœ… Timestamps (created, updated, contacted, resolved)

Fields:

class ContactRequest:
    name: str
    email: str
    phone: str
    message: str
    chat_context: JSON  # Full conversation array
    ip_address: str
    user_agent: str
    status: str  # pending, contacted, resolved

2. Chat Session Tracking

File: app/models/chat_session.py

What It Tracks:

  • βœ… Every chat session with unique ID
  • βœ… IP address for each user
  • βœ… All messages in conversation
  • βœ… Session duration and activity
  • βœ… Language detected
  • βœ… Satisfaction ratings
  • βœ… Response times

Example:

{
  "session_id": "abc123",
  "ip_address": "192.168.1.1",
  "messages": [
    {
      "text": "Hey there! 😊",
      "isUser": false,
      "timestamp": "2025-12-07T03:22:00Z"
    },
    {
      "text": "how are you",
      "isUser": true,
      "timestamp": "2025-12-07T03:22:15Z"
    }
  ],
  "message_count": 10,
  "is_active": true
}

3. Contact Form API

File: app/api/contact.py

Endpoints:

Submit Contact Request

POST /api/contact/submit

// Request
{
  "name": "John Doe",
  "email": "john@example.com",
  "phone": "+1234567890",
  "message": "I need help with...",
  "session_id": "abc123",
  "chat_context": [
    {"text": "Hey there! 😊", "isUser": false},
    {"text": "how are you", "isUser": true},
    {"text": "I am fine", "isUser": false}
  ]
}

// Response
{
  "id": 42,
  "status": "success",
  "message": "Thank you! We'll get back to you soon."
}

Get Contact Requests

GET /api/contact/requests?website_id=123&status=pending

// Response
[
  {
    "id": 42,
    "name": "John Doe",
    "email": "john@example.com",
    "chat_context": [...],
    "ip_address": "192.168.1.1",
    "status": "pending",
    "created_at": "2025-12-07T03:22:00Z"
  }
]

Update Status

PATCH /api/contact/request/42/status

{
  "status": "contacted",
  "notes": "Called customer, issue resolved"
}

4. Session Tracking Service

File: app/services/session_tracker.py

Features:

  • Automatic session creation on first message
  • IP address capture from request headers
  • Message logging with timestamps
  • Session end tracking
  • Analytics and reporting

Usage Example:

from app.services.session_tracker import get_session_tracker

tracker = get_session_tracker(db)

# Create/get session
session = tracker.get_or_create_session(
    session_id="abc123",
    website_id=1,
    ip_address="192.168.1.1",
    user_agent="Mozilla/5.0..."
)

# Add messages
tracker.add_message(
    session_id="abc123",
    text="Hello!",
    is_user=True,
    response_time=1500  # ms
)

# Get stats
stats = tracker.get_session_stats("abc123")
# {
#   "message_count": 10,
#   "duration_seconds": 180,
#   "ip_address": "192.168.1.1"
# }

# Find sessions by IP
sessions = tracker.get_sessions_by_ip("192.168.1.1")

πŸ”§ Integration Guide

Step 1: Update Chat API to Track Sessions

# In your chat endpoint
from app.services.session_tracker import get_session_tracker

@router.post("/api/chat")
async def chat(
    request: Request,
    message: str,
    session_id: str,
    website_id: int,
    db: Session = Depends(get_db)
):
    # Get IP address
    ip_address = request.headers.get("X-Forwarded-For", "").split(",")[0]
    if not ip_address:
        ip_address = request.client.host
    
    # Track session
    tracker = get_session_tracker(db)
    session = tracker.get_or_create_session(
        session_id=session_id,
        website_id=website_id,
        ip_address=ip_address,
        user_agent=request.headers.get("User-Agent")
    )
    
    # Log user message
    tracker.add_message(
        session_id=session_id,
        text=message,
        is_user=True
    )
    
    # Generate bot response
    response = await generate_response(message)
    
    # Log bot message
    tracker.add_message(
        session_id=session_id,
        text=response,
        is_user=False,
        response_time=1500
    )
    
    return {"response": response}

Step 2: Update Frontend Contact Form

// ContactForm.jsx
const handleSubmit = async (formData) => {
  try {
    // Get full chat context
    const chatContext = messages.map(msg => ({
      text: msg.text,
      isUser: msg.isUser,
      timestamp: msg.timestamp
    }));
    
    // Submit to API
    const response = await fetch('/api/contact/submit', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        name: formData.name,
        email: formData.email,
        phone: formData.phone,
        message: formData.message,
        session_id: sessionId,
        chat_context: chatContext
      })
    });
    
    const result = await response.json();
    
    if (result.status === 'success') {
      // Show success message
      setShowThankYou(true);
    }
  } catch (error) {
    console.error('Failed to submit:', error);
  }
};

Step 3: Database Migration

# Create migration
cd server
alembic revision -m "add_contact_and_session_tracking"

# Apply migration
alembic upgrade head

Migration Example:

# migrations/versions/xxx_add_contact_and_session_tracking.py

def upgrade():
    # Create contact_requests table
    op.create_table('contact_requests',
        sa.Column('id', sa.Integer(), primary_key=True),
        sa.Column('website_id', sa.Integer(), nullable=False),
        sa.Column('session_id', sa.String(255), nullable=False),
        sa.Column('name', sa.String(255)),
        sa.Column('email', sa.String(255)),
        sa.Column('phone', sa.String(50)),
        sa.Column('message', sa.Text()),
        sa.Column('ip_address', sa.String(50)),
        sa.Column('user_agent', sa.Text()),
        sa.Column('chat_context', sa.JSON()),
        sa.Column('status', sa.String(50), default='pending'),
        sa.Column('created_at', sa.DateTime(), default=datetime.utcnow)
    )
    
    # Create chat_sessions table
    op.create_table('chat_sessions',
        sa.Column('id', sa.Integer(), primary_key=True),
        sa.Column('session_id', sa.String(255), unique=True),
        sa.Column('website_id', sa.Integer(), nullable=False),
        sa.Column('ip_address', sa.String(50)),
        sa.Column('messages', sa.JSON()),
        sa.Column('is_active', sa.Boolean(), default=True),
        sa.Column('started_at', sa.DateTime(), default=datetime.utcnow)
    )

πŸ“Š Admin Dashboard Views

Contact Requests View

// ContactRequestsPage.jsx
const ContactRequests = () => {
  const [requests, setRequests] = useState([]);
  
  useEffect(() => {
    fetch(`/api/contact/requests?website_id=${websiteId}`)
      .then(res => res.json())
      .then(data => setRequests(data));
  }, []);
  
  return (
    <div className="contact-requests">
      <h2>Contact Requests</h2>
      <table>
        <thead>
          <tr>
            <th>Date</th>
            <th>Name</th>
            <th>Email</th>
            <th>IP Address</th>
            <th>Messages</th>
            <th>Status</th>
            <th>Actions</th>
          </tr>
        </thead>
        <tbody>
          {requests.map(req => (
            <tr key={req.id}>
              <td>{new Date(req.created_at).toLocaleString()}</td>
              <td>{req.name}</td>
              <td>{req.email}</td>
              <td>{req.ip_address}</td>
              <td>{req.chat_context?.length} msgs</td>
              <td>
                <span className={`badge badge-${req.status}`}>
                  {req.status}
                </span>
              </td>
              <td>
                <button onClick={() => viewDetails(req.id)}>
                  View
                </button>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
};

Session Analytics View

// SessionAnalytics.jsx
const SessionAnalytics = () => {
  return (
    <div className="analytics">
      <h2>Chat Session Analytics</h2>
      
      <div className="stats-grid">
        <div className="stat-card">
          <h3>Active Sessions</h3>
          <p className="stat-value">42</p>
        </div>
        
        <div className="stat-card">
          <h3>Unique IPs (Today)</h3>
          <p className="stat-value">127</p>
        </div>
        
        <div className="stat-card">
          <h3>Avg. Messages/Session</h3>
          <p className="stat-value">8.5</p>
        </div>
        
        <div className="stat-card">
          <h3>Contact Conversion</h3>
          <p className="stat-value">12%</p>
        </div>
      </div>
      
      <div className="sessions-map">
        <h3>Sessions by Location (IP-based)</h3>
        {/* Map showing user locations */}
      </div>
    </div>
  );
};

πŸ” Privacy & GDPR Compliance

IP Address Handling

Storage:

  • βœ… IP addresses stored for analytics
  • βœ… Can be anonymized (last octet)
  • βœ… Auto-deletion after 90 days

Anonymization (optional):

def anonymize_ip(ip_address: str) -> str:
    """Anonymize IP by removing last octet"""
    parts = ip_address.split('.')
    if len(parts) == 4:
        parts[-1] = '0'
    return '.'.join(parts)
    # 192.168.1.123 β†’ 192.168.1.0

GDPR Compliance:

  • βœ… User can request data deletion
  • βœ… Privacy policy disclosure
  • βœ… Data retention policies
  • βœ… Opt-out mechanism

πŸ“ˆ Benefits

For Business

  • βœ… Track all contact requests in one place
  • βœ… See full conversation context
  • βœ… Identify returning visitors by IP
  • βœ… Analyze chat effectiveness
  • βœ… Spot patterns and trends

For Support

  • βœ… Full chat history before contact
  • βœ… Know what user already tried
  • βœ… Better context for responses
  • βœ… Track resolution status

For Analytics

  • βœ… Session duration tracking
  • βœ… Message count analysis
  • βœ… Geographic distribution (IP-based)
  • βœ… Conversion rate tracking
  • βœ… Response time metrics

βœ… Summary

What You Get:

  1. βœ… Proper contact request storage (not just JSON)
  2. βœ… Full chat context saved with each request
  3. βœ… IP tracking for every session
  4. βœ… Complete conversation history
  5. βœ… Admin dashboard to manage requests
  6. βœ… Analytics and reporting

Before: Contact request just shows JSON ❌
After: Properly stored in database with full context βœ…

Before: No user tracking ❌
After: Every session tracked by IP βœ