This commit is contained in:
Flatlogic Bot 2025-11-18 19:49:45 +00:00
parent e444f992d1
commit bb9ecddfa5
16 changed files with 528 additions and 43 deletions

View File

@ -222,3 +222,64 @@ body {
background-color: #0056b3; background-color: #0056b3;
border-color: #0056b3; border-color: #0056b3;
} }
.ga-status-connected {
color: #28A745;
font-weight: bold;
margin-bottom: 16px;
}
.btn-secondary {
background-color: #6C757D;
color: #FFFFFF;
border: 1px solid #6C757D;
}
.ga-property-id-section {
background-color: #FFFFFF;
padding: 24px;
border-radius: 8px;
border: 1px solid #DEE2E6;
margin-bottom: 32px;
}
.ga-data-section {
background-color: #FFFFFF;
padding: 24px;
border-radius: 8px;
border: 1px solid #DEE2E6;
margin-bottom: 32px;
}
.ga-data-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 24px;
}
.ga-data-card {
background-color: #F8F9FA;
padding: 24px;
border-radius: 8px;
text-align: center;
}
.ga-data-card h3 {
font-size: 1rem;
color: #6C757D;
margin-bottom: 8px;
}
.ga-data-value {
font-size: 2rem;
font-weight: bold;
}
.demo-notice {
background-color: #FFF3CD;
color: #856404;
padding: 16px;
border: 1px solid #FFEEBA;
border-radius: 4px;
margin-bottom: 24px;
}

View File

@ -1,23 +1,158 @@
<?php <?php
// Dummy data for the dashboard // dashboard.php
$client_name = "Example Client";
$data = [
"sessions" => ["value" => "12,345", "change" => "+5.2%"],
"conversions" => ["value" => "678", "change" => "+12.8%"],
"ad_spend" => ["value" => "$2,456", "change" => "-3.1%"],
"clicks" => ["value" => "34,567", "change" => "+8.4%"],
"keyword_ranks" => ["value" => "5", "change" => "+2"],
"backlinks" => ["value" => "1,234", "change" => "+50"],
"site_audit_score" => ["value" => "88/100", "change" => "+3"],
"calls" => ["value" => "98", "change" => "+15%"],
];
// Dummy data for the main chart (e.g., sessions over time) // Start session to store GA data and manage state
session_start();
// Configuration and token management
$google_analytics_connected = file_exists('db/google_tokens.json');
$ga_property_id = null;
$ga_data = null;
$ga_error = null;
// Handle GA Property ID submission
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ga_property_id'])) {
$property_id = trim($_POST['ga_property_id']);
if (!empty($property_id)) {
file_put_contents('db/ga_property_id.txt', $property_id);
// Clear previous GA data on new ID
if (isset($_SESSION['ga_data'])) unset($_SESSION['ga_data']);
if (isset($_SESSION['ga_error'])) unset($_SESSION['ga_error']);
// Set a flag to indicate we need to fetch data
$_SESSION['ga_fetch_required'] = true;
header('Location: dashboard.php');
exit();
}
}
// Load GA Property ID if it exists
if (file_exists('db/ga_property_id.txt')) {
$ga_property_id = file_get_contents('db/ga_property_id.txt');
}
// --- GOOGLE ANALYTICS DATA FETCHING ---
// Fetch data only if connected, property ID is set, and a fetch is required
if ($google_analytics_connected && $ga_property_id && isset($_SESSION['ga_fetch_required'])) {
unset($_SESSION['ga_fetch_required']); // Unset the flag to prevent re-fetching on every page load
require_once 'google-config.php';
$tokens_json = file_get_contents('db/google_tokens.json');
$tokens = json_decode($tokens_json, true);
if (!is_array($tokens) || !isset($tokens['access_token']) || !isset($tokens['refresh_token'])) {
$_SESSION['ga_error'] = "Google token file is corrupt or invalid. Please disconnect and reconnect.";
error_log("Invalid google_tokens.json content: " . $tokens_json);
header('Location: dashboard.php');
exit();
}
$access_token = $tokens['access_token'];
$refresh_token = $tokens['refresh_token'];
// --- 1. Refresh Access Token ---
$token_url = 'https://oauth2.googleapis.com/token';
$token_params = [
'client_id' => GOOGLE_CLIENT_ID,
'client_secret' => GOOGLE_CLIENT_SECRET,
'refresh_token' => $refresh_token,
'grant_type' => 'refresh_token'
];
$ch = curl_init($token_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($token_params));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($http_code == 200) {
$new_token_data = json_decode($response, true);
if (isset($new_token_data['access_token'])) {
$tokens['access_token'] = $new_token_data['access_token'];
file_put_contents('db/google_tokens.json', json_encode($tokens));
$access_token = $new_token_data['access_token'];
// --- 2. Fetch Data from Google Analytics Data API ---
$analytics_api_url = "https://analyticsdata.googleapis.com/v1beta/properties/{$ga_property_id}:runReport";
$api_request_body = [
'dateRanges' => [['startDate' => '28daysAgo', 'endDate' => 'today']],
'metrics' => [
['name' => 'sessions'],
['name' => 'totalUsers'],
['name' => 'screenPageViews'],
['name' => 'bounceRate']
]
];
$ch_analytics = curl_init($analytics_api_url);
curl_setopt($ch_analytics, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $access_token,
'Content-Type: application/json'
]);
curl_setopt($ch_analytics, CURLOPT_POST, true);
curl_setopt($ch_analytics, CURLOPT_POSTFIELDS, json_encode($api_request_body));
curl_setopt($ch_analytics, CURLOPT_RETURNTRANSFER, true);
$analytics_response = curl_exec($ch_analytics);
$analytics_http_code = curl_getinfo($ch_analytics, CURLINFO_HTTP_CODE);
curl_close($ch_analytics);
if ($analytics_http_code == 200) {
$report = json_decode($analytics_response, true);
if (isset($report['rows'][0]['metricValues'])) {
$metricValues = $report['rows'][0]['metricValues'];
$_SESSION['ga_data'] = [
'sessions' => $metricValues[0]['value'] ?? '0',
'users' => $metricValues[1]['value'] ?? '0',
'page_views' => $metricValues[2]['value'] ?? '0',
'bounce_rate' => isset($metricValues[3]['value']) ? round($metricValues[3]['value'] * 100, 2) . '%' : '0%',
];
} else {
$_SESSION['ga_error'] = "No data returned from Analytics. Check if the property ID is correct and has recent data.";
}
} else {
$error_response = json_decode($analytics_response, true);
$error_message = "HTTP {$analytics_http_code}";
if (is_array($error_response) && isset($error_response['error']['message'])) {
$error_message = $error_response['error']['message'];
} else {
error_log("Unknown Google API Error. Code: {$analytics_http_code}. Response: " . $analytics_response);
}
$_SESSION['ga_error'] = "Error fetching Analytics data: " . $error_message;
}
} else {
$_SESSION['ga_error'] = "Failed to refresh token, new access token not found.";
}
} else {
$_SESSION['ga_error'] = "Error refreshing Google token. Please try disconnecting and reconnecting.";
}
// Redirect to clean the URL and prevent re-submission
header('Location: dashboard.php');
exit();
}
// Load data from session if available
if (isset($_SESSION['ga_data'])) {
$ga_data = $_SESSION['ga_data'];
unset($_SESSION['ga_data']); // Clear after loading
}
if (isset($_SESSION['ga_error'])) {
$ga_error = $_SESSION['ga_error'];
unset($_SESSION['ga_error']); // Clear after loading
}
// Dummy data for other sections (can be replaced later)
$client_name = "Example Client";
$chart_data = [ $chart_data = [
"labels" => ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], "labels" => ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
"values" => [5000, 5500, 6200, 7100, 8000, 8500, 9200, 9800, 10500, 11200, 12000, 12345], "values" => [5000, 5500, 6200, 7100, 8000, 8500, 9200, 9800, 10500, 11200, 12000, 12345],
]; ];
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
@ -44,32 +179,72 @@ $chart_data = [
<main class="dashboard-main"> <main class="dashboard-main">
<div class="integration-connect"> <div class="integration-connect">
<?php if ($google_analytics_connected): ?>
<div class="ga-status-connected">Connected to Google Analytics</div>
<a href="google_disconnect.php" class="btn btn-secondary">Disconnect</a>
<?php else: ?>
<a href="google_auth.php" class="btn btn-primary">Connect to Google Analytics</a> <a href="google_auth.php" class="btn btn-primary">Connect to Google Analytics</a>
<?php endif; ?>
</div> </div>
<div class="dashboard-title"> <div class="dashboard-title">
<h1><?php echo htmlspecialchars($client_name); ?>'s Dashboard</h1> <h1><?php echo htmlspecialchars($client_name); ?>'s Dashboard</h1>
<div class="date-range-picker"> <div class="date-range-picker">
<input type="text" value="Last 30 Days"> <input type="text" value="Last 28 Days">
<svg width="14" height="8" viewBox="0 0 14 8" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1 1L7 7L13 1" stroke="#6C757D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg> <svg width="14" height="8" viewBox="0 0 14 8" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1 1L7 7L13 1" stroke="#6C757D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
</div> </div>
</div> </div>
<section class="metrics-grid"> <?php if ($google_analytics_connected): ?>
<?php foreach ($data as $key => $metric): ?> <?php if (!$ga_property_id): ?>
<div class="metric-card"> <section class="ga-property-id-section">
<h3 class="metric-title"><?php echo ucwords(str_replace("_", " ", $key)); ?></h3> <h2>Enter your Google Analytics Property ID</h2>
<p class="metric-value"><?php echo htmlspecialchars($metric['value']); ?></p> <p>This is required to fetch data from your Analytics account.</p>
<p class="metric-change <?php echo strpos($metric['change'], '+') !== false ? 'positive' : 'negative'; ?>"> <form method="POST" action="dashboard.php">
<?php echo htmlspecialchars($metric['change']); ?> <input type="text" name="ga_property_id" placeholder="Enter your Property ID (e.g., 123456789)" required>
</p> <button type="submit" class="btn btn-primary">Save and Fetch Data</button>
</div> </form>
<?php endforeach; ?>
</section> </section>
<?php else: ?>
<section class="ga-data-section">
<h2>Google Analytics Overview <span class="ga-property-id">(Property ID: <?php echo htmlspecialchars($ga_property_id); ?>)</span></h2>
<?php if ($ga_error): ?>
<div class="ga-error-notice">
<strong>Error:</strong> <?php echo htmlspecialchars($ga_error); ?>
</div>
<?php endif; ?>
<?php if ($ga_data): ?>
<div class="ga-data-grid">
<div class="ga-data-card">
<h3>Sessions</h3>
<p class="ga-data-value"><?php echo htmlspecialchars($ga_data['sessions']); ?></p>
</div>
<div class="ga-data-card">
<h3>Users</h3>
<p class="ga-data-value"><?php echo htmlspecialchars($ga_data['users']); ?></p>
</div>
<div class="ga-data-card">
<h3>Page Views</h3>
<p class="ga-data-value"><?php echo htmlspecialchars($ga_data['page_views']); ?></p>
</div>
<div class="ga-data-card">
<h3>Bounce Rate</h3>
<p class="ga-data-value"><?php echo htmlspecialchars($ga_data['bounce_rate']); ?></p>
</div>
</div>
<?php else: ?>
<div class="ga-loading-notice">
Attempting to fetch live data from Google Analytics... If this message persists, please check your Property ID or try reconnecting.
</div>
<?php endif; ?>
</section>
<?php endif; ?>
<?php endif; ?>
<section class="chart-section"> <section class="chart-section">
<div class="chart-container"> <div class="chart-container">
<h2 class="chart-title">Sessions Over Time</h2> <h2 class="chart-title">Sessions Over Time (Sample)</h2>
<!-- Simple bar chart using inline styles for dummy representation -->
<div class="chart"> <div class="chart">
<?php <?php
$max_value = max($chart_data['values']); $max_value = max($chart_data['values']);

1
db/ga_property_id.txt Normal file
View File

@ -0,0 +1 @@
G-XE06RVWK6S

1
db/google_tokens.json Normal file
View File

@ -0,0 +1 @@
{"access_token":"ya29.a0ATi6K2uk0Gb_RDk8IRqUCYlK4xhbAoOR6sM6T9fudqgQtVDahmlHDshpy5sKcqUtpmhCT5HBPWrDfaSb1GALm5iSkbRagO0Sq_drZfhFYA4G22OwS1J418mYgBsI0BS4_SdYO8Biwy-U2nhATQMqkBqxUAnETW9Vp_7qgmgbPYIp01MCqXJ9b_5CJm-673rL4GT2YlcaCgYKAXQSARYSFQHGX2MivzBSL3ClF2zW9KP5SQnJ8g0206","expires_in":3599,"refresh_token":"1\/\/04GWLH1ZGkD_lCgYIARAAGAQSNwF-L9Ir2NCtmqTH8Cxr8O5uXkkX4TvTzC2dXXFTrS7amm1DVPKtlfupCJyvopZHDy2wY5blJoI","scope":"https:\/\/www.googleapis.com\/auth\/analytics.readonly","token_type":"Bearer"}

1
db/perm_test.txt Normal file
View File

@ -0,0 +1 @@
test

5
google-config.php Normal file
View File

@ -0,0 +1,5 @@
<?php
// config/google.php
define('GOOGLE_CLIENT_ID', '711888153406-074gd97v22f8nqq9dr3cjlo761pts4s9.apps.googleusercontent.com');
define('GOOGLE_CLIENT_SECRET', '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');
define('GOOGLE_REDIRECT_URI', 'https://'. $_SERVER['HTTP_HOST'] . '/google_callback.php');

View File

@ -1,7 +1,8 @@
<?php <?php
session_start(); session_start();
unset($_SESSION['google_access_token']);
require_once 'config/google.php'; require_once 'google-config.php';
$auth_url = 'https://accounts.google.com/o/oauth2/v2/auth?' . http_build_query([ $auth_url = 'https://accounts.google.com/o/oauth2/v2/auth?' . http_build_query([
'client_id' => GOOGLE_CLIENT_ID, 'client_id' => GOOGLE_CLIENT_ID,

View File

@ -1,7 +1,22 @@
<?php <?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
file_put_contents('logs/debug.log', "Callback script started\n", FILE_APPEND);
session_start(); session_start();
require_once 'config/google.php';
require_once 'google-config.php';
function log_error($message) {
$log_file = 'logs/google_auth.log';
$timestamp = date('Y-m-d H:i:s');
// Ensure the log directory exists
if (!is_dir(dirname($log_file))) {
mkdir(dirname($log_file), 0775, true);
}
file_put_contents($log_file, "[$timestamp] $message\n", FILE_APPEND);
}
if (isset($_GET['code'])) { if (isset($_GET['code'])) {
$code = $_GET['code']; $code = $_GET['code'];
@ -22,27 +37,45 @@ if (isset($_GET['code'])) {
$response = curl_exec($ch); $response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curl_error = curl_error($ch);
curl_close($ch); curl_close($ch);
if ($curl_error) {
log_error("cURL Error: " . $curl_error);
echo "An error occurred. Please try again later. (Code: 1)";
exit();
}
if ($http_code == 200) { if ($http_code == 200) {
$token_data = json_decode($response, true); $token_data = json_decode($response, true);
// For now, just print the token data if (json_last_error() !== JSON_ERROR_NONE) {
// In a real application, you would store this securely in a database log_error("Failed to decode JSON response: " . $response);
echo '<pre>'; echo "An error occurred. Please try again later. (Code: 2)";
print_r($token_data); exit();
echo '</pre>'; }
// Ensure the db directory exists
if (!is_dir(dirname('db/google_tokens.json'))) {
mkdir(dirname('db/google_tokens.json'), 0775, true);
}
if (file_put_contents('db/google_tokens.json', json_encode($token_data)) === false) {
log_error("Failed to write tokens to db/google_tokens.json");
echo "An error occurred. Please try again later. (Code: 3)";
exit();
}
// Store the access token in the session for immediate use
$_SESSION['google_access_token'] = $token_data['access_token']; $_SESSION['google_access_token'] = $token_data['access_token'];
// Redirect back to the dashboard header('Location: dashboard.php');
// header('Location: dashboard.php'); exit();
// exit();
} else { } else {
echo "Error fetching access token: " . $response; log_error("Error fetching access token. HTTP Code: " . $http_code . ", Response: " . $response);
echo "An error occurred while trying to connect to Google. Please check your credentials in setup.php and try again.";
} }
} else { } else {
log_error("Authorization code not found in callback.");
echo "Authorization code not found."; echo "Authorization code not found.";
} }

7
google_disconnect.php Normal file
View File

@ -0,0 +1,7 @@
<?php
if (file_exists('db/google_tokens.json')) {
unlink('db/google_tokens.json');
}
header('Location: dashboard.php');
exit();

View File

@ -80,6 +80,9 @@
<footer class="text-center py-4"> <footer class="text-center py-4">
<div class="container"> <div class="container">
<p class="text-muted">&copy; <?php echo date("Y"); ?> AgencyAnalytics. All rights reserved.</p> <p class="text-muted">&copy; <?php echo date("Y"); ?> AgencyAnalytics. All rights reserved.</p>
<p class="text-muted small">
<a href="privacy.php">Privacy Policy</a> &middot; <a href="terms.php">Terms of Service</a>
</p>
</div> </div>
</footer> </footer>

2
logs/debug.log Normal file
View File

@ -0,0 +1,2 @@
Callback script started
Callback script started

4
logs/google_auth.log Normal file
View File

@ -0,0 +1,4 @@
[2025-11-18 19:43:05] Error fetching access token. HTTP Code: 400, Response: {
"error": "invalid_grant",
"error_description": "Bad Request"
}

1
logs/perm_test.txt Normal file
View File

@ -0,0 +1 @@
test

43
privacy.php Normal file
View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Privacy Policy</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
<div class="container mt-5">
<h1>Privacy Policy</h1>
<p><em>Last updated: <?php echo date("F j, Y"); ?></em></p>
<div class="alert alert-warning">
<strong>Disclaimer:</strong> This is a template and not legal advice. You should replace this content with your own privacy policy.
</div>
<h2>Introduction</h2>
<p>Welcome to our application. We are committed to protecting your privacy. This Privacy Policy explains how we collect, use, disclose, and safeguard your information when you use our application.</p>
<h2>Information We Collect</h2>
<p>We may collect information about you in a variety of ways. The information we may collect via the Application includes:</p>
<ul>
<li><strong>Personal Data:</strong> Personally identifiable information, such as your name, shipping address, email address, and telephone number, and demographic information, such as your age, gender, hometown, and interests, that you voluntarily give to us when you register with the Application.</li>
<li><strong>Data from Google Analytics:</strong> We connect to your Google Analytics account to retrieve and display your website traffic data. We only request read-only access and do not store your data permanently on our servers.</li>
</ul>
<h2>Use of Your Information</h2>
<p>Having accurate information about you permits us to provide you with a smooth, efficient, and customized experience. Specifically, we may use information collected about you via the Application to:</p>
<ul>
<li>Create and manage your account.</li>
<li>Display your Google Analytics data on a personal dashboard.</li>
<li>Email you regarding your account or order.</li>
</ul>
<h2>Contact Us</h2>
<p>If you have questions or comments about this Privacy Policy, please contact us.</p>
<hr>
<a href="index.php">Back to Home</a>
</div>
</body>
</html>

101
setup.php Normal file
View File

@ -0,0 +1,101 @@
<?php
$config_file = 'google-config.php';
$error_message = '';
$success_message = '';
// Check if the form has been submitted
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Get the submitted values
$client_id = $_POST['client_id'] ?? '';
$client_secret = $_POST['client_secret'] ?? '';
if (!empty($client_id) && !empty($client_secret)) {
// Read the existing config file
$config_content = file_get_contents($config_file);
if ($config_content !== false) {
// Replace the placeholder values
$config_content = preg_replace("/define\('GOOGLE_CLIENT_ID', '.*'\);/", "define('GOOGLE_CLIENT_ID', '$client_id');", $config_content);
$config_content = preg_replace("/define\('GOOGLE_CLIENT_SECRET', '.*'\);/", "define('GOOGLE_CLIENT_SECRET', '$client_secret');", $config_content);
// Write the updated content back to the file
if (file_put_contents($config_file, $config_content) !== false) {
$success_message = 'Your Google API credentials have been saved successfully!';
} else {
$error_message = 'Error: Unable to write to the configuration file. Please check file permissions.';
}
} else {
$error_message = 'Error: Unable to read the configuration file.';
}
} else {
$error_message = 'Please provide both Client ID and Client Secret.';
}
}
// Read the current values to display them (or placeholders)
$current_client_id = '';
$current_client_secret = '';
if (file_exists($config_file)) {
$config_content = file_get_contents($config_file);
if (preg_match("/define\('GOOGLE_CLIENT_ID', '(.*)'\);/", $config_content, $matches)) {
$current_client_id = $matches[1];
}
if (preg_match("/define\('GOOGLE_CLIENT_SECRET', '(.*)'\);/", $config_content, $matches)) {
$current_client_secret = $matches[1];
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Google API Setup</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body {
background-color: #f8f9fa;
}
.setup-container {
max-width: 600px;
margin: 50px auto;
padding: 30px;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
</style>
</head>
<body>
<div class="container">
<div class="setup-container">
<h2 class="text-center mb-4">Google API Setup</h2>
<?php if ($error_message): ?>
<div class="alert alert-danger"><?php echo $error_message; ?></div>
<?php endif; ?>
<?php if ($success_message): ?>
<div class="alert alert-success"><?php echo $success_message; ?></div>
<?php endif; ?>
<form method="POST" action="setup.php">
<div class="mb-3">
<label for="client_id" class="form-label">Google Client ID</label>
<input type="text" class="form-control" id="client_id" name="client_id" value="<?php echo htmlspecialchars($current_client_id); ?>" required>
</div>
<div class="mb-3">
<label for="client_secret" class="form-label">Google Client Secret</label>
<input type="password" class="form-control" id="client_secret" name="client_secret" value="<?php echo htmlspecialchars($current_client_secret); ?>" required>
</div>
<div class="d-grid">
<button type="submit" class="btn btn-primary">Save Credentials</button>
</div>
</form>
<div class="text-center mt-3">
<a href="index.php">Back to Home</a>
</div>
</div>
</div>
</body>
</html>

46
terms.php Normal file
View File

@ -0,0 +1,46 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Terms of Service</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
<div class="container mt-5">
<h1>Terms of Service</h1>
<p><em>Last updated: <?php echo date("F j, Y"); ?></em></p>
<div class="alert alert-warning">
<strong>Disclaimer:</strong> This is a template and not legal advice. You should replace this content with your own terms of service.
</div>
<h2>1. Agreement to Terms</h2>
<p>By using our application, you agree to be bound by these Terms of Service. If you do not agree to these Terms, do not use the application.</p>
<h2>2. License to Use</h2>
<p>We grant you a limited, non-exclusive, non-transferable, revocable license to use the application for your personal, non-commercial purposes, subject to these Terms.</p>
<h2>3. User Accounts</h2>
<p>When you create an account with us, you must provide us with information that is accurate, complete, and current at all times. Failure to do so constitutes a breach of the Terms, which may result in immediate termination of your account on our Service.</p>
<h2>4. Intellectual Property</h2>
<p>The Service and its original content, features, and functionality are and will remain the exclusive property of the application owner and its licensors.</p>
<h2>5. Termination</h2>
<p>We may terminate or suspend your account immediately, without prior notice or liability, for any reason whatsoever, including without limitation if you breach the Terms.</p>
<h2>6. Governing Law</h2>
<p>These Terms shall be governed and construed in accordance with the laws of the jurisdiction in which the application owner is based, without regard to its conflict of law provisions.</p>
<h2>7. Changes to Terms</h2>
<p>We reserve the right, at our sole discretion, to modify or replace these Terms at any time. We will provide at least 30 days' notice prior to any new terms taking effect.</p>
<h2>Contact Us</h2>
<p>If you have any questions about these Terms, please contact us.</p>
<hr>
<a href="index.php">Back to Home</a>
</div>
</body>
</html>