diff --git a/database.py b/database.py index d37a1b8..6da51f8 100644 --- a/database.py +++ b/database.py @@ -4180,6 +4180,9 @@ class UserSession(Base): # Bot detection is_bot = Column(Boolean, default=False) + # PWA detection + is_pwa = Column(Boolean, default=False) + # UTM Parameters (kampanie marketingowe) utm_source = Column(String(255), nullable=True) # google, facebook, newsletter utm_medium = Column(String(255), nullable=True) # cpc, email, social, organic diff --git a/database/migrations/063_add_is_pwa_to_user_sessions.sql b/database/migrations/063_add_is_pwa_to_user_sessions.sql new file mode 100644 index 0000000..2f242ad --- /dev/null +++ b/database/migrations/063_add_is_pwa_to_user_sessions.sql @@ -0,0 +1,4 @@ +-- Migration 063: Add is_pwa column to user_sessions +-- Tracks whether the session originated from the PWA (installed app) + +ALTER TABLE user_sessions ADD COLUMN IF NOT EXISTS is_pwa BOOLEAN DEFAULT FALSE; diff --git a/templates/base.html b/templates/base.html index 0add7a0..e654e89 100755 --- a/templates/base.html +++ b/templates/base.html @@ -2371,6 +2371,11 @@ } } + // PWA detection — set cookie for backend analytics + if (window.matchMedia('(display-mode: standalone)').matches || window.navigator.standalone) { + document.cookie = 'pwa_mode=1; path=/; max-age=86400; SameSite=Lax'; + } + // PWA Smart Banner logic (function() { var banner = document.getElementById('pwaSmartBanner'); diff --git a/utils/analytics.py b/utils/analytics.py index 44f9aed..8433239 100644 --- a/utils/analytics.py +++ b/utils/analytics.py @@ -54,9 +54,17 @@ def get_or_create_analytics_session(): browser_version = ua.browser.version_string os_name = ua.os.family os_version = ua.os.version_string - is_bot = ua.is_bot or any(p in ua_string.lower() for p in + ua_lower = ua_string.lower() + is_bot = ua.is_bot or any(p in ua_lower for p in ['curl/', 'python-requests', 'axios/', 'wget/', 'scrapy', - 'werkzeug', 'leakix', 'nuclei', 'masscan', 'zgrab', 'httpx']) + 'werkzeug', 'leakix', 'nuclei', 'masscan', 'zgrab', 'httpx', + 'googleassociationservice', 'censysinspect', 'paloaltonetworks', + 'cortex', 'netcraft', 'fasthttp', 'cms-checker', + 'wp-safe-scanner', 'notebooklm', 'ruby/', 'skypeuri', + 'com.apple.webkit', 'networkingextension']) + # Flag empty or bare Mozilla/5.0 user agents as bots + if not ua_string.strip() or ua_string.strip() == 'Mozilla/5.0': + is_bot = True except Exception: device_type = 'desktop' browser = 'Unknown' @@ -77,6 +85,10 @@ def get_or_create_analytics_session(): os_version=os_version[:20] if os_version else None, is_bot=is_bot ) + # PWA detection from cookie + is_pwa = request.cookies.get('pwa_mode') == '1' + user_session.is_pwa = is_pwa + db.add(user_session) db.commit() db.refresh(user_session)