Adding site tracking and consent to Tianji
Deploy Company Site / deploy (push) Successful in 4s

This commit is contained in:
2026-06-28 06:47:52 -05:00
parent 7e448cf61a
commit 6e7bd25e29
23 changed files with 617 additions and 40 deletions
+5
View File
@@ -69,6 +69,7 @@ TEMPLATES = [
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'public.context_processors.tianji_tracking',
],
},
},
@@ -153,3 +154,7 @@ EMAIL_USE_TLS = True
# Authentication Redirects
LOGIN_REDIRECT_URL = '/'
LOGOUT_REDIRECT_URL = '/'
# Tianji analytics (loaded only after user consent in production)
TIANJI_TRACKER_URL = 'https://tianji.aimloperations.com/tracker.js'
TIANJI_WEBSITE_ID = 'cm7w80pyy020oddswy2evl957'
@@ -9,23 +9,28 @@
<h1 class="section-title">Dashboard</h1>
<div class="card-grid" style="margin-bottom: 3rem;">
<a href="{% url 'contracts' %}" class="card">
<a href="{% url 'contracts' %}" class="card"
data-tianji-event="financial_nav" data-tianji-event-destination="contracts">
<span class="card-title">View Contracts</span>
<p class="card-text">Overview of all active and past contracts and their scopes.</p>
</a>
<a href="{% url 'new_contract' %}" class="card">
<a href="{% url 'new_contract' %}" class="card"
data-tianji-event="financial_nav" data-tianji-event-destination="new_contract">
<span class="card-title">New Contract</span>
<p class="card-text">Establish a new project contract to track budgets.</p>
</a>
<a href="{% url 'new_employee' %}" class="card">
<a href="{% url 'new_employee' %}" class="card"
data-tianji-event="financial_nav" data-tianji-event-destination="new_employee">
<span class="card-title">New Employee</span>
<p class="card-text">Add a new personnel member to your organization.</p>
</a>
<a href="{% url 'Timekeeping' %}" class="card">
<a href="{% url 'Timekeeping' %}" class="card"
data-tianji-event="financial_nav" data-tianji-event-destination="timekeeping">
<span class="card-title">Log Time</span>
<p class="card-text">Record work hours against specific contracts.</p>
</a>
<a href="{% url 'time_logs' %}" class="card">
<a href="{% url 'time_logs' %}" class="card"
data-tianji-event="financial_nav" data-tianji-event-destination="time_logs">
<span class="card-title">Manage Time Logs</span>
<p class="card-text">Review and edit submitted time entries.</p>
</a>
@@ -226,7 +226,8 @@
<textarea name="description" class="form-control" rows="4"></textarea>
</div>
<input type="hidden" name="next" value="{{ request.path }}">
<button type="submit" class="btn">Create</button>
<button type="submit" class="btn"
data-tianji-event="planning_create_item">Create</button>
</form>
</div>
</div>
@@ -328,9 +329,11 @@
.then(data => {
if (data.status !== 'success') {
alert('Failed to update status');
} else {
// Update counts if necessary, though reloading or dynamic updates are better.
// Simple approach: user just sees it moved.
} else if (window.aimlTrack) {
window.aimlTrack('planning_item_status_change', {
status: newStatus,
item_id: id
});
}
});
});
+18
View File
@@ -0,0 +1,18 @@
from django.conf import settings
def tianji_tracking(request):
return {
'tianji_enabled': not settings.DEBUG,
'tianji_tracker_url': getattr(
settings,
'TIANJI_TRACKER_URL',
'https://tianji.aimloperations.com/tracker.js',
),
'tianji_website_id': getattr(
settings,
'TIANJI_WEBSITE_ID',
'cm7w80pyy020oddswy2evl957',
),
'page_name': getattr(getattr(request, 'resolver_match', None), 'url_name', ''),
}
@@ -583,4 +583,118 @@ input:focus, select:focus, textarea:focus {
display: block;
margin-bottom: 1rem;
margin-top: -0.5rem;
}
/* Footer links */
.footer-links {
margin: 0.5rem 0;
font-size: 0.9rem;
}
.footer-links a {
color: var(--text-muted);
}
.footer-links a:hover {
color: var(--primary-color);
}
.footer-separator {
color: var(--text-muted);
margin: 0 0.5rem;
}
/* Legal pages */
.legal-page {
max-width: 820px;
}
.legal-updated {
text-align: center;
color: var(--text-muted);
margin-bottom: 2rem;
}
.legal-content h2 {
color: var(--primary-color);
font-size: 1.25rem;
margin: 2rem 0 0.75rem;
}
.legal-content h3 {
color: var(--text-color);
font-size: 1.05rem;
margin: 1.5rem 0 0.5rem;
}
.legal-content p,
.legal-content li {
color: var(--text-muted);
margin-bottom: 1rem;
}
.legal-content ul {
margin: 0 0 1rem 1.5rem;
}
/* Cookie consent banner */
.cookie-consent-banner {
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 1100;
padding: 1rem;
background: rgba(26, 26, 26, 0.98);
border-top: 1px solid rgba(0, 243, 255, 0.25);
backdrop-filter: blur(10px);
}
.cookie-consent-content {
max-width: 960px;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 1rem;
}
.cookie-consent-text {
flex: 1 1 420px;
color: var(--text-muted);
font-size: 0.95rem;
margin: 0;
}
.cookie-consent-actions {
display: flex;
gap: 0.75rem;
flex-shrink: 0;
}
.btn-outline {
background: transparent;
border: 1px solid rgba(255, 255, 255, 0.25);
color: var(--text-color);
}
.btn-outline:hover {
border-color: var(--primary-color);
color: var(--primary-color);
}
@media (max-width: 640px) {
.cookie-consent-content {
flex-direction: column;
align-items: stretch;
}
.cookie-consent-actions {
width: 100%;
}
.cookie-consent-actions .btn {
flex: 1;
}
}
@@ -0,0 +1,159 @@
(function () {
'use strict';
var CONSENT_KEY = 'aiml_analytics_consent';
var configEl = document.getElementById('tianji-config');
if (!configEl) {
return;
}
var trackerUrl = configEl.dataset.trackerUrl;
var websiteId = configEl.dataset.websiteId;
var userId = configEl.dataset.userId || '';
var pendingConsentEvent = false;
function getConsent() {
try {
return localStorage.getItem(CONSENT_KEY);
} catch (e) {
return null;
}
}
function setConsent(value) {
try {
localStorage.setItem(CONSENT_KEY, value);
} catch (e) {
/* ignore storage errors */
}
}
function hideBanner() {
var banner = document.getElementById('cookie-consent-banner');
if (banner) {
banner.hidden = true;
}
}
function showBanner() {
var banner = document.getElementById('cookie-consent-banner');
if (banner) {
banner.hidden = false;
}
}
function trackEvent(name, data) {
if (window.tianji && typeof window.tianji.track === 'function') {
window.tianji.track(name, data || {});
}
}
function identifyUser() {
if (!userId || !window.tianji || typeof window.tianji.identify !== 'function') {
return;
}
window.tianji.identify({ userId: userId });
}
function loadTracker() {
if (document.querySelector('script[data-tianji-loaded="true"]')) {
identifyUser();
return;
}
var script = document.createElement('script');
script.async = true;
script.defer = true;
script.src = trackerUrl;
script.setAttribute('data-website-id', websiteId);
script.setAttribute('data-do-not-track', 'true');
script.setAttribute('data-tianji-loaded', 'true');
script.onload = function () {
identifyUser();
if (pendingConsentEvent) {
trackEvent('consent_accepted');
pendingConsentEvent = false;
}
document.dispatchEvent(new CustomEvent('tianji:ready'));
};
document.head.appendChild(script);
}
function acceptTracking() {
setConsent('accepted');
hideBanner();
try {
localStorage.removeItem('tianji.disabled');
} catch (e) {
/* ignore storage errors */
}
pendingConsentEvent = true;
loadTracker();
}
function declineTracking() {
setConsent('declined');
hideBanner();
try {
localStorage.setItem('tianji.disabled', '1');
} catch (e) {
/* ignore storage errors */
}
if (window.aimlTrack) {
window.aimlTrack('consent_declined');
}
}
function bindBannerControls() {
var acceptBtn = document.getElementById('cookie-consent-accept');
var declineBtn = document.getElementById('cookie-consent-decline');
var manageLinks = document.querySelectorAll('[data-open-cookie-preferences]');
if (acceptBtn) {
acceptBtn.addEventListener('click', acceptTracking);
}
if (declineBtn) {
declineBtn.addEventListener('click', declineTracking);
}
manageLinks.forEach(function (link) {
link.addEventListener('click', function (event) {
event.preventDefault();
showBanner();
});
});
}
window.aimlTrack = function (name, data) {
trackEvent(name, data);
};
window.aimlTrackWhenReady = function (name, data) {
if (window.tianji && typeof window.tianji.track === 'function') {
trackEvent(name, data);
return;
}
document.addEventListener('tianji:ready', function handler() {
document.removeEventListener('tianji:ready', handler);
trackEvent(name, data);
});
};
document.addEventListener('DOMContentLoaded', function () {
bindBannerControls();
var consent = getConsent();
if (consent === 'accepted') {
hideBanner();
loadTracker();
return;
}
if (consent === 'declined') {
hideBanner();
return;
}
showBanner();
});
})();
+40 -7
View File
@@ -36,9 +36,13 @@
<link href="{% static 'public/css/style.css' %}" rel="stylesheet">
<link rel="icon" type="image/png" href="{% static 'public/img/favicon.png' %}">
{% if not debug %}
<script async defer src="https://tianji.aimloperations.com/tracker.js"
data-website-id="cm7w80pyy020oddswy2evl957"></script>
{% if tianji_enabled %}
<div id="tianji-config"
data-tracker-url="{{ tianji_tracker_url }}"
data-website-id="{{ tianji_website_id }}"
data-page-name="{{ page_name }}"
{% if user.is_authenticated %}data-user-id="{{ user.pk }}"{% endif %}
hidden></div>
{% endif %}
</head>
@@ -69,12 +73,15 @@
</ul>
</li>
<li><a href="{% url 'contact' %}"
class="{% if request.resolver_match.url_name == 'contact' %}active{% endif %}">Contact</a></li>
class="{% if request.resolver_match.url_name == 'contact' %}active{% endif %}"
data-tianji-event="nav_contact">Contact</a></li>
{% if user.is_authenticated %}
<li><a href="{% url 'planning:board_view' %}"
class="{% if 'planning' in request.path %}active{% endif %}">Planning</a></li>
class="{% if 'planning' in request.path %}active{% endif %}"
data-tianji-event="nav_planning">Planning</a></li>
<li><a href="{% url 'financial_index' %}"
class="{% if 'financial' in request.path %}active{% endif %}">Financials</a></li>
class="{% if 'financial' in request.path %}active{% endif %}"
data-tianji-event="nav_financials">Financials</a></li>
<li class="dropdown" id="user-profile-dropdown">
<a href="#" class="profile-icon-link" title="{{ user.get_full_name|default:user.username }}">
<svg class="profile-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
@@ -96,7 +103,8 @@
</li>
{% else %}
<li><a href="{% url 'login' %}" class="btn"
style="border: 1px solid var(--primary-color); padding: 0.4rem 1rem; border-radius: 4px; margin-left: 1rem; color: #000;">Sign
style="border: 1px solid var(--primary-color); padding: 0.4rem 1rem; border-radius: 4px; margin-left: 1rem; color: #000;"
data-tianji-event="nav_sign_in">Sign
In</a></li>
{% endif %}
</ul>
@@ -111,12 +119,36 @@
<footer class="footer">
<div class="container">
<p class="footer-text">AI ML Operations, LLC — Forward-deployed AI engineering.</p>
<p class="footer-links">
<a href="{% url 'terms_of_service' %}" data-tianji-event="footer_terms">Terms &amp; Privacy</a>
{% if tianji_enabled %}
<span class="footer-separator">|</span>
<a href="#" data-open-cookie-preferences data-tianji-event="footer_cookie_preferences">Cookie Preferences</a>
{% endif %}
</p>
<p class="footer-text footer-text--muted">&copy; 2023 -
<script>document.write(new Date().getFullYear());</script> All rights reserved.
</p>
</div>
</footer>
{% if tianji_enabled %}
<div id="cookie-consent-banner" class="cookie-consent-banner" hidden role="dialog" aria-live="polite"
aria-label="Cookie consent">
<div class="cookie-consent-content">
<p class="cookie-consent-text">
We use Tianji analytics to understand how visitors use our site. Tracking runs only if you accept.
See our <a href="{% url 'terms_of_service' %}">Terms of Service &amp; Privacy Policy</a> for details.
</p>
<div class="cookie-consent-actions">
<button type="button" id="cookie-consent-decline" class="btn btn-outline">Decline</button>
<button type="button" id="cookie-consent-accept" class="btn">Accept Analytics</button>
</div>
</div>
</div>
<script src="{% static 'public/js/tianji-consent.js' %}"></script>
{% endif %}
<script>
document.addEventListener('DOMContentLoaded', function () {
const mobileBtn = document.querySelector('.mobile-menu-btn');
@@ -129,6 +161,7 @@
}
});
</script>
{% block tracking_events %}{% endblock %}
</body>
</html>
@@ -83,7 +83,8 @@ workshops, and training for teams.{% endblock %}
<h2 class="section-title">Ready to Transform Your Business?</h2>
<p class="hero-subtitle" style="margin-bottom: 2rem;">Contact us today to schedule your AI Education sessions.</p>
<a href="{% url 'contact' %}"
style="display: inline-block; padding: 1rem 2rem; background: var(--primary-color); color: black; font-weight: bold; border-radius: 30px; text-transform: uppercase;">Get
style="display: inline-block; padding: 1rem 2rem; background: var(--primary-color); color: black; font-weight: bold; border-radius: 30px; text-transform: uppercase;"
data-tianji-event="service_cta" data-tianji-event-page="ai_education" data-tianji-event-action="get_started">Get
Started</a>
</div>
</div>
@@ -86,7 +86,8 @@ Machine Vision, Pattern Recognition, and NLP for sensors.{% endblock %}
<div class="container">
<h2 class="section-title">Ready to Enhance Your Sensors?</h2>
<p class="hero-subtitle" style="margin-bottom: 2rem;">Contact us today to discuss your AI sensor needs.</p>
<a href="{% url 'contact' %}" class="btn">Get Started</a>
<a href="{% url 'contact' %}" class="btn"
data-tianji-event="service_cta" data-tianji-event-page="ai_sensor" data-tianji-event-action="get_started">Get Started</a>
</div>
</div>
{% endblock %}
@@ -14,7 +14,8 @@
Proprietary agents built for your workflows and conversations—hosted, scalable, and observable.
</p>
<div class="hero-cta">
<a href="{% url 'contact' %}?subject=AI%20Agents" class="btn">Build Your Agent</a>
<a href="{% url 'contact' %}?subject=AI%20Agents" class="btn"
data-tianji-event="service_cta" data-tianji-event-page="bot" data-tianji-event-action="build_agent">Build Your Agent</a>
<a href="{% url 'forward_deployed' %}" class="btn btn-secondary">Forward-Deployed AI</a>
</div>
</div>
@@ -121,7 +122,8 @@
<div class="container">
<h2 class="section-title">Ready to Automate?</h2>
<p class="hero-subtitle" style="margin-bottom: 2rem;">Tell us the workflow you want an agent to own—we will design, deploy, and monitor it.</p>
<a href="{% url 'contact' %}?subject=AI%20Agents" class="btn">Get Started</a>
<a href="{% url 'contact' %}?subject=AI%20Agents" class="btn"
data-tianji-event="service_cta" data-tianji-event-page="bot" data-tianji-event-action="get_started">Get Started</a>
</div>
</div>
{% endblock %}
@@ -41,7 +41,8 @@
<div style="margin-top: 2rem;">
<button type="submit" class="btn"
style="width: 100%; padding: 0.75rem; background: var(--primary-color); color: white; border: none; border-radius: 4px; cursor: pointer; font-weight: 600; background: linear-gradient(90deg, #00d4ff 0%, #0099ff 100%);">Update
style="width: 100%; padding: 0.75rem; background: var(--primary-color); color: white; border: none; border-radius: 4px; cursor: pointer; font-weight: 600; background: linear-gradient(90deg, #00d4ff 0%, #0099ff 100%);"
data-tianji-event="password_change_submit">Update
Password</button>
</div>
</form>
@@ -15,7 +15,8 @@
designed to keep your data under your control.
</p>
<div style="display: flex; gap: 1rem; flex-wrap: wrap;">
<a href="https://chat.aimloperations.com" class="btn">Launch Chat</a>
<a href="https://chat.aimloperations.com" class="btn" target="_blank" rel="noopener noreferrer"
data-tianji-event="external_launch" data-tianji-event-product="chat">Launch Chat</a>
<a href="#features" class="btn"
style="background: transparent; border: 1px solid var(--text-muted); color: var(--text-color);">Learn More</a>
</div>
@@ -64,7 +65,8 @@
<p style="color: var(--text-muted); margin-bottom: 2.5rem; font-size: 1.1rem;">
Get full access to all features, including unlimited chats and file analysis.
</p>
<a class="btn" href="https://chat.aimloperations.com">Start Your Free Trial</a>
<a class="btn" href="https://chat.aimloperations.com" target="_blank" rel="noopener noreferrer"
data-tianji-event="external_launch" data-tianji-event-product="chat_trial">Start Your Free Trial</a>
</div>
</div>
</div>
@@ -87,7 +87,8 @@ PCs to AI servers and workstations.{% endblock %}
<div class="container">
<h2 class="section-title">Ready to Upgrade Your Systems?</h2>
<p class="hero-subtitle" style="margin-bottom: 2rem;">Contact us today to discuss your computer needs.</p>
<a href="{% url 'contact' %}" class="btn">Get Started</a>
<a href="{% url 'contact' %}" class="btn"
data-tianji-event="service_cta" data-tianji-event-page="computers" data-tianji-event-action="get_started">Get Started</a>
</div>
</div>
{% endblock %}
@@ -58,7 +58,8 @@
{% endif %}
</div>
<button class="btn" type="submit">
<button class="btn" type="submit"
data-tianji-event="contact_form_submit">
Send Message
</button>
</form>
@@ -85,4 +86,14 @@
</div>
</div>
</div>
{% endblock %}
{% block tracking_events %}
{% if success %}
<script>
if (window.aimlTrackWhenReady) {
window.aimlTrackWhenReady('contact_form_success');
}
</script>
{% endif %}
{% endblock %}
@@ -82,7 +82,8 @@ Protect your data with our advanced storage solutions.{% endblock %}
<h2 class="section-title">Ready to Secure Your Files?</h2>
<p class="hero-subtitle" style="margin-bottom: 2rem;">Contact us today to get started with our file hosting service.
</p>
<a href="{% url 'contact' %}" class="btn">Get Started</a>
<a href="{% url 'contact' %}" class="btn"
data-tianji-event="service_cta" data-tianji-event-page="file_hosting" data-tianji-event-action="get_started">Get Started</a>
</div>
</div>
@@ -145,7 +145,8 @@
<h2 class="section-title">Ready to Deploy?</h2>
<p class="hero-subtitle" style="margin-bottom: 2rem;">Tell us the workflow that is costing you the most time. We will help you automate it.</p>
<div class="hero-cta" style="margin-top: 0;">
<a href="{% url 'contact' %}?subject=Forward-Deployed%20AI" class="btn">Start a Conversation</a>
<a href="{% url 'contact' %}?subject=Forward-Deployed%20AI" class="btn"
data-tianji-event="service_cta" data-tianji-event-page="forward_deployed" data-tianji-event-action="start_conversation">Start a Conversation</a>
</div>
</div>
</div>
@@ -84,7 +84,8 @@ supervised, unsupervised, and reinforcement learning.{% endblock %}
<div class="container">
<h2 class="section-title">Ready to Solve Your Problem?</h2>
<p class="hero-subtitle" style="margin-bottom: 2rem;">Contact us today to create your custom ML model.</p>
<a href="{% url 'contact' %}" class="btn">Get Started</a>
<a href="{% url 'contact' %}" class="btn"
data-tianji-event="service_cta" data-tianji-event-page="ml_model" data-tianji-event-action="get_started">Get Started</a>
</div>
</div>
{% endblock %}
@@ -18,7 +18,8 @@
Forward-deployed AI engineering. We embed with your team to architect, build, and deploy custom AI workflows that solve complex operational bottlenecks.
</p>
<div class="hero-cta">
<a href="{% url 'forward_deployed' %}" class="btn btn-secondary">See How We Deploy</a>
<a href="{% url 'forward_deployed' %}" class="btn btn-secondary"
data-tianji-event="hero_cta" data-tianji-event-destination="forward_deployed">See How We Deploy</a>
</div>
</div>
</div>
@@ -167,50 +168,59 @@
</p>
<div class="card-grid">
<a href="{% url 'forward_deployed' %}" class="card card-featured">
<a href="{% url 'forward_deployed' %}" class="card card-featured"
data-tianji-event="service_click" data-tianji-event-service="Forward-Deployed AI">
<span class="card-badge">Primary</span>
<span class="card-title">Forward-Deployed AI</span>
<p class="card-text">Embed with your team to map bottlenecks, build integrations, and deploy custom AI workflows in your environment.</p>
</a>
<a href="{% url 'bot' %}" class="card card-featured">
<a href="{% url 'bot' %}" class="card card-featured"
data-tianji-event="service_click" data-tianji-event-service="AI Agents">
<span class="card-badge">Primary</span>
<span class="card-title">AI Agents &amp; Automation</span>
<p class="card-text">Proprietary web-hosted agents for your workflows and conversations—scalable hosting plus performance and real-time analytics.</p>
</a>
<a href="{% url 'web_design' %}" class="card">
<a href="{% url 'web_design' %}" class="card"
data-tianji-event="service_click" data-tianji-event-service="Web Design">
<span class="card-badge">Primary</span>
<span class="card-title">Web Design and Hosting</span>
<p class="card-text">Modern websites with reliable hosting for your online presence.</p>
</a>
<a href="{% url 'ml_model' %}" class="card">
<a href="{% url 'ml_model' %}" class="card"
data-tianji-event="service_click" data-tianji-event-service="ML Model Creation">
<span class="card-title">ML Model Creation</span>
<p class="card-text">Custom models designed for deployment inside your pipelines—not experiments that never ship.</p>
</a>
<a href="{% url 'chat' %}" class="card">
<a href="{% url 'chat' %}" class="card"
data-tianji-event="service_click" data-tianji-event-service="Secure AI Chat">
<span class="card-title">Secure AI Chat</span>
<p class="card-text">Hosted LLM workspace with privacy-first architecture—an example of how we deliver scalable, observable AI products.</p>
</a>
<a href="{% url 'ai_sensor' %}" class="card">
<a href="{% url 'ai_sensor' %}" class="card"
data-tianji-event="service_click" data-tianji-event-service="AI Sensor Algorithms">
<span class="card-title">AI Sensor Algorithms</span>
<p class="card-text">Intelligent algorithms for sensor data processing, real-time insights, and IoT applications.</p>
</a>
<a href="{% url 'ai_education' %}" class="card">
<a href="{% url 'ai_education' %}" class="card"
data-tianji-event="service_click" data-tianji-event-service="AI Education">
<span class="card-title">AI Education</span>
<p class="card-text">Tailored AI training for your team—in-person or virtual.</p>
</a>
<a href="{% url 'computers' %}" class="card">
<a href="{% url 'computers' %}" class="card"
data-tianji-event="service_click" data-tianji-event-service="Computer Builds">
<span class="card-title">Computer Builds</span>
<p class="card-text">Servers and workstations for compute, storage, and local inference workloads.</p>
</a>
<a href="{% url 'file_hosting' %}" class="card">
<a href="{% url 'file_hosting' %}" class="card"
data-tianji-event="service_click" data-tianji-event-service="File Hosting">
<span class="card-title">File Hosting</span>
<p class="card-text">Secure, scalable file hosting to store and share your data.</p>
</a>
@@ -0,0 +1,202 @@
{% extends "base.html" %}
{% block title %}Terms of Service &amp; Privacy Policy - AI ML Operations, LLC{% endblock %}
{% block meta_description %}Terms of Service and Privacy Policy for AI ML Operations, LLC, including how we collect, use, and protect your information and analytics practices.{% endblock %}
{% block content %}
<div class="section">
<div class="container legal-page">
<h1 class="section-title">Terms of Service &amp; Privacy Policy</h1>
<p class="legal-updated">Last updated: June 28, 2026</p>
<div class="legal-content">
<p>
These Terms of Service and Privacy Policy ("Terms") govern your access to and use of the website and online
services operated by AI ML Operations, LLC ("AI ML Operations," "we," "us," or "our"). By accessing or using
our website, you agree to these Terms. If you do not agree, do not use the site.
</p>
<h2>1. Use of the Website</h2>
<p>
You may use our website for lawful purposes only. You agree not to misuse the site, attempt unauthorized
access to our systems, interfere with site operation, or use the site in any way that violates applicable law.
</p>
<p>
Certain areas of the site, including internal planning and financial tools, are available only to
authenticated users authorized by AI ML Operations. You are responsible for maintaining the confidentiality
of your account credentials.
</p>
<h2>2. Services and Information</h2>
<p>
Content on this website describes our AI engineering, consulting, and related services. Information on the
site is provided for general informational purposes and does not constitute a binding offer unless expressly
agreed in a separate written contract.
</p>
<h2>3. Contact Submissions</h2>
<p>
When you submit a contact form, you represent that the information you provide is accurate and that you
have the right to share it with us. We may use that information to respond to your inquiry and for related
business communications.
</p>
<h2>4. Privacy Policy</h2>
<p>
This Privacy Policy explains what information we collect, how we use it, and the choices you have. It applies
to visitors and authenticated users of our public website and internal tools.
</p>
<h3>4.1 Information We Collect</h3>
<p>Depending on how you use the site, we may collect:</p>
<ul>
<li><strong>Information you provide:</strong> name, email address, message content, and other details submitted through contact forms or account-related requests.</li>
<li><strong>Account information:</strong> username and authentication data for authorized users of internal tools.</li>
<li><strong>Usage and analytics data:</strong> if you accept analytics in our cookie banner, we collect information about how you interact with the site, as described in Section 4.2.</li>
<li><strong>Technical information:</strong> browser type, device type, operating system, language, referring URLs, and similar data collected automatically when you use the site.</li>
</ul>
<p>
We do not intentionally collect sensitive personal information through the public website unless you choose to
include it in a message you send us.
</p>
<h3>4.2 Analytics and Usage Tracking</h3>
<p>
We use Tianji, a self-hosted analytics platform, to understand how visitors use our website and internal
tools. Tracking is enabled only after you provide consent through our cookie banner.
</p>
<p>When you accept analytics, we may collect information such as:</p>
<ul>
<li>Pages viewed and navigation paths</li>
<li>Approximate geographic location derived from truncated IP addresses</li>
<li>Browser type, device type, operating system, and language</li>
<li>Referring website or campaign parameters (UTM tags)</li>
<li>Custom interaction events, such as button clicks, form submissions, and feature usage</li>
<li>For signed-in users, an internal user identifier to associate activity with an account session</li>
</ul>
<p>
We do not use Tianji to sell your personal information. Analytics data helps us improve site performance,
content, and product usability. You may decline analytics at any time using the cookie preferences link
in the site footer. If you decline, the analytics script will not load.
</p>
<p>
We store your consent choice locally in your browser so we can remember your preference on future visits.
</p>
<h3>4.3 Cookies and Local Storage</h3>
<p>
In addition to analytics consent storage, our site uses essential cookies and session storage required for
authentication, security (including CSRF protection), and basic site functionality. These essential
technologies are necessary for the site to operate and are not used for marketing analytics.
</p>
<h3>4.4 How We Use Information</h3>
<p>We use collected information to:</p>
<ul>
<li>Operate, maintain, and secure the website and internal tools</li>
<li>Respond to contact requests and communicate with you about our services</li>
<li>Authenticate authorized users and provide access to restricted areas</li>
<li>Understand site usage and improve content, performance, and user experience</li>
<li>Comply with legal obligations and enforce these Terms</li>
</ul>
<h3>4.5 How We Share Information</h3>
<p>
We do not sell your personal information. We may share information only in these limited circumstances:
</p>
<ul>
<li>With service providers that help us operate the site (such as email delivery), subject to appropriate safeguards</li>
<li>When required by law, regulation, legal process, or governmental request</li>
<li>To protect the rights, property, or safety of AI ML Operations, our users, or others</li>
<li>In connection with a business transaction such as a merger or acquisition, with notice where required by law</li>
</ul>
<p>
Analytics data collected through Tianji is processed on our self-hosted analytics infrastructure and is not
shared with third-party advertising networks.
</p>
<h3>4.6 Data Retention</h3>
<p>
We retain contact form submissions and business communications for as long as needed to respond to inquiries,
maintain business records, and comply with legal obligations. Analytics data is retained according to our
internal retention settings on the Tianji platform. Account-related data is retained while your account is
active and as required thereafter for legitimate business or legal purposes.
</p>
<h3>4.7 Your Choices and Rights</h3>
<p>You can:</p>
<ul>
<li>Accept or decline analytics tracking through our cookie banner or the cookie preferences link in the footer</li>
<li>Contact us to request access to, correction of, or deletion of personal information you have provided, subject to applicable law</li>
<li>Disable non-essential browser storage or cookies through your browser settings, though essential site features may not function properly</li>
</ul>
<p>
Depending on your location, you may have additional privacy rights under applicable law. To exercise those
rights, contact us using the information in Section 12.
</p>
<h3>4.8 Security</h3>
<p>
We use reasonable administrative, technical, and organizational measures to protect information we collect.
No method of transmission or storage is completely secure, and we cannot guarantee absolute security.
</p>
<h3>4.9 Children's Privacy</h3>
<p>
Our website is not directed to children under 13, and we do not knowingly collect personal information from
children under 13. If you believe we have collected such information, contact us and we will take steps to
delete it.
</p>
<h2>5. Intellectual Property</h2>
<p>
The website, branding, text, graphics, logos, and other content are owned by AI ML Operations or its
licensors and are protected by applicable intellectual property laws. You may not copy, modify, distribute,
or create derivative works without our prior written permission, except as permitted by law.
</p>
<h2>6. Third-Party Links</h2>
<p>
Our site may contain links to third-party websites or services. We are not responsible for the content,
privacy practices, or terms of those third parties. Your use of third-party sites is at your own risk.
</p>
<h2>7. Disclaimer of Warranties</h2>
<p>
The website and its content are provided "as is" and "as available" without warranties of any kind, whether
express or implied, including implied warranties of merchantability, fitness for a particular purpose, and
non-infringement. We do not warrant that the site will be uninterrupted, error-free, or secure.
</p>
<h2>8. Limitation of Liability</h2>
<p>
To the fullest extent permitted by law, AI ML Operations will not be liable for any indirect, incidental,
special, consequential, or punitive damages, or any loss of profits, data, or goodwill, arising from your use
of the website. Our total liability for any claim relating to the website will not exceed one hundred U.S.
dollars (USD $100), unless applicable law requires otherwise.
</p>
<h2>9. Changes to These Terms</h2>
<p>
We may update these Terms from time to time. The "Last updated" date at the top of this page indicates when
the Terms were most recently revised. Continued use of the site after changes become effective constitutes
acceptance of the revised Terms.
</p>
<h2>10. Governing Law</h2>
<p>
These Terms are governed by the laws of the State of Ohio, United States, without regard to conflict-of-law
principles. Any dispute arising under these Terms will be resolved in the courts located in Ohio, unless
applicable law requires a different venue.
</p>
<h2>11. Contact Us</h2>
<p>
If you have questions about these Terms, our privacy practices, or your data, contact us at
<a href="mailto:ryan@aimloperations.com">ryan@aimloperations.com</a> or through our
<a href="{% url 'contact' %}">contact page</a>.
</p>
</div>
</div>
</div>
{% endblock %}
@@ -186,7 +186,8 @@ visually stunning, functional websites tailored to your business.{% endblock %}
<div class="container">
<h2 class="section-title">Ready to Build Your Online Presence?</h2>
<p class="hero-subtitle" style="margin-bottom: 2rem;">Contact us today to get started on your website project.</p>
<a href="{% url 'contact' %}" class="btn">Get Started</a>
<a href="{% url 'contact' %}" class="btn"
data-tianji-event="service_cta" data-tianji-event-page="web_design" data-tianji-event-action="get_started">Get Started</a>
</div>
</div>
{% endblock %}
@@ -27,7 +27,8 @@
<input type="password" name="password" autocomplete="current-password" required id="id_password" class="form-control" style="width: 100%; padding: 0.8rem; background: rgba(0,0,0,0.2); border: 1px solid rgba(255,255,255,0.1); border-radius: 6px; color: white;">
</div>
<button type="submit" class="btn" style="width: 100%; padding: 0.8rem; font-size: 1.1rem; border-radius: 6px; background: var(--primary-color); color: #000; font-weight: bold; border: none; cursor: pointer; transition: 0.2s;" onmouseover="this.style.boxShadow='0 0 15px var(--primary-color)'" onmouseout="this.style.boxShadow='none'">Sign In</button>
<button type="submit" class="btn" style="width: 100%; padding: 0.8rem; font-size: 1.1rem; border-radius: 6px; background: var(--primary-color); color: #000; font-weight: bold; border: none; cursor: pointer; transition: 0.2s;" onmouseover="this.style.boxShadow='0 0 15px var(--primary-color)'" onmouseout="this.style.boxShadow='none'"
data-tianji-event="login_submit">Sign In</button>
<input type="hidden" name="next" value="{{ next|default:'/' }}">
</form>
</div>
+1
View File
@@ -14,6 +14,7 @@ urlpatterns = [
path("forward-deployed-ai", views.forward_deployed, name="forward_deployed"),
path("ml_model", views.ml_model, name="ml_model"),
path("contact", views.contact, name="contact"),
path("terms", views.terms_of_service, name="terms_of_service"),
path("change_password", views.change_password, name="change_password"),
path("preview_email/<int:pk>/", views.preview_email, name="preview_email")
]
+3
View File
@@ -55,6 +55,9 @@ def forward_deployed(request):
def ml_model(request):
return render(request, "public/ml_model.html", {})
def terms_of_service(request):
return render(request, "public/terms_of_service.html", {})
@login_required
def preview_email(request, pk):
email_instance = get_object_or_404(EmailMessage, pk=pk)