AITOOL / ads /google_ads.py
NandanData's picture
Upload 54 files
ab3b796 verified
"""
Google Ads Integration
Handles displaying Google AdSense ads and tracking ad impressions/clicks
"""
import os
import uuid
import logging
import json
import time
from typing import Dict, Any, Optional, List
from datetime import datetime
# Setup logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("google_ads")
class GoogleAdsManager:
"""Manages Google AdSense integration and tracking"""
def __init__(self, publisher_id: Optional[str] = None, config_file: str = None):
"""Initialize Google Ads Manager"""
self.publisher_id = publisher_id or os.getenv("GOOGLE_ADSENSE_PUBLISHER_ID", "")
self.config_file = config_file or os.path.join(os.path.dirname(__file__), "ads_config.json")
# Load ad units configuration
self.ad_units = self._load_ad_units()
# Track impressions and clicks
self.impressions_file = os.path.join(os.path.dirname(__file__), "impressions.json")
self.clicks_file = os.path.join(os.path.dirname(__file__), "clicks.json")
# Create tracking files if they don't exist
self._initialize_tracking_files()
def _load_ad_units(self) -> Dict[str, Any]:
"""Load ad units configuration"""
default_ad_units = {
"sidebar": {
"ad_unit_id": "1234567890",
"ad_format": "display",
"width": 300,
"height": 250,
"slot": "sidebar-ad",
"enabled": True
},
"footer": {
"ad_unit_id": "0987654321",
"ad_format": "display",
"width": 728,
"height": 90,
"slot": "footer-ad",
"enabled": True
},
"reward_video": {
"ad_unit_id": "5678901234",
"ad_format": "video",
"slot": "reward-video-ad",
"enabled": True,
"reward_credits": 10
}
}
# Create config file with default values if it doesn't exist
if not os.path.exists(self.config_file):
os.makedirs(os.path.dirname(self.config_file), exist_ok=True)
with open(self.config_file, "w") as f:
json.dump({"publisher_id": self.publisher_id, "ad_units": default_ad_units}, f, indent=2)
return default_ad_units
# Load config from file
try:
with open(self.config_file, "r") as f:
config = json.load(f)
# Update publisher ID if it was set in the config file
if config.get("publisher_id"):
self.publisher_id = config["publisher_id"]
return config.get("ad_units", default_ad_units)
except Exception as e:
logger.error(f"Error loading ad units config: {e}")
return default_ad_units
def _initialize_tracking_files(self):
"""Initialize tracking files if they don't exist"""
os.makedirs(os.path.dirname(self.impressions_file), exist_ok=True)
if not os.path.exists(self.impressions_file):
with open(self.impressions_file, "w") as f:
json.dump([], f)
if not os.path.exists(self.clicks_file):
with open(self.clicks_file, "w") as f:
json.dump([], f)
def get_ad_code(self, ad_position: str) -> Dict[str, Any]:
"""
Get HTML/JS code for displaying an ad at the specified position
Returns both the ad code and metadata about the ad
"""
if not self.publisher_id:
logger.warning("No Google AdSense publisher ID configured")
return {"success": False, "error": "No publisher ID configured"}
# Get ad unit configuration
ad_unit = self.ad_units.get(ad_position)
if not ad_unit:
logger.error(f"Ad position '{ad_position}' not configured")
return {"success": False, "error": f"Ad position '{ad_position}' not found"}
if not ad_unit.get("enabled", True):
logger.info(f"Ad unit '{ad_position}' is disabled")
return {"success": False, "error": "Ad unit is disabled"}
# Generate HTML/JS code for the ad
ad_format = ad_unit.get("ad_format", "display")
ad_unit_id = ad_unit.get("ad_unit_id", "")
ad_slot = ad_unit.get("slot", f"{ad_position}-ad")
if ad_format == "display":
width = ad_unit.get("width", 300)
height = ad_unit.get("height", 250)
ad_code = f"""
<ins class="adsbygoogle"
style="display:inline-block;width:{width}px;height:{height}px"
data-ad-client="ca-pub-{self.publisher_id}"
data-ad-slot="{ad_unit_id}"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({{}});
</script>
"""
elif ad_format == "video":
ad_code = f"""
<div id="{ad_slot}" class="reward-ad-container">
<div class="reward-ad-placeholder">
<p>Watch a video to earn {ad_unit.get('reward_credits', 5)} credits</p>
<button class="watch-ad-btn" onclick="loadRewardAd('{ad_slot}', '{ad_unit_id}', {ad_unit.get('reward_credits', 5)})">Watch Now</button>
</div>
</div>
"""
else:
logger.error(f"Unsupported ad format: {ad_format}")
return {"success": False, "error": f"Unsupported ad format: {ad_format}"}
# Generate a unique ID for tracking this ad impression
impression_id = str(uuid.uuid4())
# Record the impression for tracking
self._record_impression(impression_id, ad_position, ad_unit_id)
return {
"success": True,
"ad_code": ad_code,
"impression_id": impression_id,
"ad_position": ad_position,
"ad_format": ad_format,
"reward_credits": ad_unit.get("reward_credits", 0) if ad_format == "video" else 0
}
def _record_impression(self, impression_id: str, ad_position: str, ad_unit_id: str):
"""Record an ad impression for tracking"""
try:
# Load existing impressions
with open(self.impressions_file, "r") as f:
impressions = json.load(f)
# Add new impression
impressions.append({
"id": impression_id,
"timestamp": datetime.now().isoformat(),
"ad_position": ad_position,
"ad_unit_id": ad_unit_id
})
# Save updated impressions
with open(self.impressions_file, "w") as f:
json.dump(impressions, f, indent=2)
except Exception as e:
logger.error(f"Error recording ad impression: {e}")
def record_ad_click(self, impression_id: str, user_id: Optional[str] = None) -> bool:
"""Record an ad click for tracking"""
try:
# Load existing clicks
with open(self.clicks_file, "r") as f:
clicks = json.load(f)
# Add new click
clicks.append({
"impression_id": impression_id,
"user_id": user_id,
"timestamp": datetime.now().isoformat()
})
# Save updated clicks
with open(self.clicks_file, "w") as f:
json.dump(clicks, f, indent=2)
return True
except Exception as e:
logger.error(f"Error recording ad click: {e}")
return False
def record_reward_ad_completion(self, impression_id: str, user_id: str) -> Dict[str, Any]:
"""
Record completion of a reward ad and return reward information
Args:
impression_id: The unique ID of the ad impression
user_id: The user ID to reward
Returns:
Dictionary with reward information and success status
"""
try:
# Find the impression to determine the ad unit
with open(self.impressions_file, "r") as f:
impressions = json.load(f)
# Find the impression with matching ID
impression = next((imp for imp in impressions if imp.get("id") == impression_id), None)
if not impression:
logger.error(f"Impression ID {impression_id} not found")
return {
"success": False,
"error": "Invalid impression ID"
}
# Get the ad position from the impression
ad_position = impression.get("ad_position")
ad_unit = self.ad_units.get(ad_position)
if not ad_unit:
logger.error(f"Ad unit for position {ad_position} not found")
return {
"success": False,
"error": "Ad unit not found"
}
# Get the reward amount
reward_credits = ad_unit.get("reward_credits", 0)
# Record the ad completion (we could store this in a separate file)
self.record_ad_click(impression_id, user_id)
return {
"success": True,
"reward_credits": reward_credits,
"user_id": user_id,
"impression_id": impression_id,
"timestamp": datetime.now().isoformat()
}
except Exception as e:
logger.error(f"Error processing reward ad completion: {e}")
return {
"success": False,
"error": str(e)
}
def get_html_header_code(self) -> str:
"""Get the HTML code to include in the page header for AdSense"""
if not self.publisher_id:
return ""
return f"""
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-{self.publisher_id}"
crossorigin="anonymous"></script>
"""
def get_reward_ad_js(self) -> str:
"""Get the JavaScript code for handling reward ads"""
return """
<script>
let rewardAdLoaded = false;
let adEventListenersAdded = false;
let currentAdSlot = null;
let rewardAmount = 0;
function loadRewardAd(adSlot, adUnitId, credits) {
currentAdSlot = adSlot;
rewardAmount = credits;
// Show loading indicator
document.getElementById(adSlot).innerHTML = '<div class="loading-ad">Loading ad, please wait...</div>';
// Create a new ad container
const adContainer = document.createElement('div');
adContainer.id = adSlot + '-container';
document.getElementById(adSlot).appendChild(adContainer);
// Load the Google ad
const adManager = new google.ads.AdManager(adContainer);
// Set up the ad
adManager.setAdUnitPath(`/ca-pub-${publisherId}/${adUnitId}`);
adManager.setAdSize([300, 250]);
// Add event listeners
if (!adEventListenersAdded) {
adManager.addEventListener('loaded', onAdLoaded);
adManager.addEventListener('error', onAdError);
adManager.addEventListener('completed', onAdCompleted);
adEventListenersAdded = true;
}
// Load the ad
adManager.load();
}
function onAdLoaded() {
rewardAdLoaded = true;
document.getElementById(currentAdSlot).querySelector('.loading-ad').style.display = 'none';
}
function onAdError(error) {
document.getElementById(currentAdSlot).innerHTML =
`<div class="ad-error">Error loading ad: ${error.message}. Please try again later.</div>`;
}
function onAdCompleted() {
// Send a request to the server to record the completion and reward the user
fetch('/api/ads/reward', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
impression_id: currentImpressionId,
completed: true
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
// Show success message
document.getElementById(currentAdSlot).innerHTML =
`<div class="reward-success">Congratulations! You earned ${rewardAmount} credits.</div>`;
// Update user credits display if available
const creditsDisplay = document.getElementById('user-credits');
if (creditsDisplay) {
const currentCredits = parseInt(creditsDisplay.innerText, 10);
creditsDisplay.innerText = currentCredits + rewardAmount;
}
} else {
document.getElementById(currentAdSlot).innerHTML =
`<div class="reward-error">Error: ${data.error}</div>`;
}
})
.catch(error => {
document.getElementById(currentAdSlot).innerHTML =
`<div class="reward-error">Error: Unable to process reward. Please try again.</div>`;
});
}
</script>
"""
# Example usage
if __name__ == "__main__":
# Initialize the ads manager
ads_manager = GoogleAdsManager()
# Get ad code for the sidebar
sidebar_ad = ads_manager.get_ad_code("sidebar")
print(f"Sidebar ad success: {sidebar_ad['success']}")
if sidebar_ad['success']:
print(f"Impression ID: {sidebar_ad['impression_id']}")
# Get the header code for AdSense
header_code = ads_manager.get_html_header_code()
print(f"Header code length: {len(header_code)}")