Spaces:
Runtime error
Runtime error
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:
- β Proper contact request storage (not just JSON)
- β Full chat context saved with each request
- β IP tracking for every session
- β Complete conversation history
- β Admin dashboard to manage requests
- β 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 β