Skip to content

Commit

Permalink
Analytics: remove GA (#11532)
Browse files Browse the repository at this point in the history
* Analytics: remove GA

Closes readthedocs/addons#10

* Apply suggestions from code review

Co-authored-by: Eric Holscher <[email protected]>

---------

Co-authored-by: Eric Holscher <[email protected]>
  • Loading branch information
humitos and ericholscher authored Aug 10, 2024
1 parent 1bc451b commit 176fe58
Show file tree
Hide file tree
Showing 8 changed files with 13 additions and 121 deletions.
12 changes: 1 addition & 11 deletions docs/user/advertising/advertising-details.rst
Original file line number Diff line number Diff line change
Expand Up @@ -107,24 +107,14 @@ Analytics
---------

Analytics are a sensitive enough issue that they require their own section.
In the spirit of full transparency, Read the Docs uses Google Analytics (GA).
We go into a bit of detail on our use of GA in our :doc:`/privacy-policy`.

GA is a contentious issue inside Read the Docs and in our community.
Google Analytics is a contentious issue inside Read the Docs and in our community.
Some users are very sensitive and privacy conscious to usage of GA.
Some authors want their own analytics on their docs to see the usage their docs get.
The developers at Read the Docs understand that different users have different priorities
and we try to respect the different viewpoints as much as possible while also accomplishing
our own goals.

We have taken steps to address some of the privacy concerns surrounding GA.
These steps apply to analytics only collected by Read the Docs,
since project authors could follow a different policy if they add GA to their projects.

* Users can opt-out of analytics by using the Do Not Track feature of their browser.
* Read the Docs instructs Google to anonymize IP addresses sent to them.
* The cookie set by GA is a session (non-persistent) cookie rather than the default 2 years.

Why we use analytics
~~~~~~~~~~~~~~~~~~~~

Expand Down
1 change: 0 additions & 1 deletion docs/user/guides/content/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ How-to guides: content, themes and SEO

⏩️ :doc:`Using traffic analytics </analytics>`
In this guide, you can learn to use Read the Docs' built-in traffic analytics for your documentation project.
You will also learn how to optionally add your own Google Analytics account or completely disable Google Analytics on your project.

⏩️ :doc:`Managing translations for Sphinx projects </guides/manage-translations-sphinx>`
This guide walks through the process needed to manage translations of your documentation.
Expand Down
6 changes: 3 additions & 3 deletions docs/user/legal/dpa/subprocessors.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Sub-processor list
==================

:Effective: April 16, 2021
:Last updated: December 27, 2022
:Last updated: August 9, 2024

Read the Docs for Business uses services from the following sub-processors to
provide documentation hosting services. This document supplements :doc:`our Data
Expand Down Expand Up @@ -34,8 +34,8 @@ Sendgrid, Inc.
and other generated messages. The body of notification emails can include
user information, including email address.

Google Analytics
Website analtyics for dashboard and documentation sites.
Plausible
Website analytics for dashboard and Read the Docs owned documentation sites.

Stripe Inc.
Subscription payment provider. Data collected can include user data necessary
Expand Down
24 changes: 8 additions & 16 deletions docs/user/privacy-policy.rst
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ Analytics
+++++++++

We go into detail on analytics in a
:ref:`separate section specific to analytics <privacy-policy:Google Analytics>`.
:ref:`separate section specific to analytics <privacy-policy:Plausible>`.

Support desk
++++++++++++
Expand Down Expand Up @@ -236,8 +236,6 @@ and the `EFF's DNT Policy`_.
For Read the Docs, this means:

* We **do not** do behavioral ad targeting regardless of your DNT preference.
* When DNT is enabled, both logged-in and logged-out users
are considered opted-out of :ref:`analytics <privacy-policy:Google Analytics>`.
* Regardless of DNT preference, our logs that contain IP addresses
and user agent strings are deleted after 10 days unless a DNT exception applies.
* Our full DNT policy is `available here`_.
Expand Down Expand Up @@ -277,29 +275,23 @@ By using our website, you agree that we can place these types of cookies on your
If you disable your browser or device's ability to accept cookies,
you will not be able to log in to Read the Docs.

Google Analytics
~~~~~~~~~~~~~~~~
Plausible
~~~~~~~~~

We use Google Analytics as a third party tracking service,
We use Plausible as a third party analytics service,
but we don't use it to track you individually or collect your User Personal Information.
We use Google Analytics to collect information about how our website performs
We use Plausible to collect information about how our website performs
and how our users, in general, navigate through and use Read the Docs.
This helps us evaluate our users' use of Read the Docs;
compile statistical reports on activity; and improve our content and website performance.

Google Analytics gathers certain simple, non-personally identifying information over time,
such as your IP address, browser type, internet service provider, referring and exit pages,
Plausible gathers certain simple, non-personally identifying information over time,
such as browser type, internet service provider, referring and exit pages,
time stamp, and similar data about your use of Read the Docs.
We do not link this information to any of your personal information such as your user name.

Read the Docs will not, nor will we allow any third party to,
use the Google Analytics tool to track our users individually;
collect any User Personal Information other than IP address;
or correlate your IP address with your identity.
Google provides further information about its own privacy practices and offers a
`browser add-on to opt out of Google Analytics tracking <https://tools.google.com/dlpage/gaoptout>`_.
You may also opt-out of analytics on Read the Docs by enabling
:ref:`Do Not Track <privacy-policy:Do Not Track>`.
use the Plausible tool to track our users individually or collect any User Personal Information.


How Read the Docs secures your information
Expand Down
3 changes: 1 addition & 2 deletions docs/user/reference/analytics.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ Traffic Analytics lets you see *which* documents your users are reading.
This allows you to understand how your documentation is being used,
so you can focus on expanding and updating parts people are reading most.

If you require more detailed analytics, Read the Docs has native support for Google Analytics.
It's also possible to customize your documentation to include other analytics frameworks.
If you require more detailed analytics it's possible to customize your documentation to include other analytics tools.

Learn more in :doc:`/analytics`.

Expand Down
48 changes: 0 additions & 48 deletions readthedocs/analytics/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
import readthedocs
from readthedocs.worker import app

from .utils import send_to_analytics

DEFAULT_PARAMETERS = {
"v": "1", # analytics version (always 1)
"aip": "1", # anonymize IP
Expand All @@ -22,52 +20,6 @@
}


@app.task(queue="web")
def analytics_pageview(url, title=None, **kwargs):
"""
Send a pageview to Google Analytics.
:see: https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters
:param url: the URL of the pageview
:param title: the title of the page being viewed
:param kwargs: extra pageview parameters to send to GA
"""
data = {
"t": "pageview",
"dl": url, # URL of the pageview (required)
"dt": title, # Title of the page
}
data.update(DEFAULT_PARAMETERS)
data.update(kwargs)
send_to_analytics(data)


@app.task(queue="web")
def analytics_event(
event_category, event_action, event_label=None, event_value=None, **kwargs
):
"""
Send an analytics event to Google Analytics.
:see: https://developers.google.com/analytics/devguides/collection/protocol/v1/devguide#event
:param event_category: the category of the event
:param event_action: the action of the event (use action words like "click")
:param event_label: an optional string to differentiate the event
:param event_value: an optional numeric value for the event
:param kwargs: extra event parameters to send to GA
"""
data = {
"t": "event", # GA event - don't change
"ec": event_category, # Event category (required)
"ea": event_action, # Event action (required)
"el": event_label, # Event label
"ev": event_value, # Event value (numeric)
}
data.update(DEFAULT_PARAMETERS)
data.update(kwargs)
send_to_analytics(data)


@app.task(queue="web")
def delete_old_page_counts():
"""
Expand Down
29 changes: 0 additions & 29 deletions readthedocs/analytics/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import hashlib
import ipaddress

import requests
import structlog
from django.conf import settings
from django.utils.crypto import get_random_string
Expand Down Expand Up @@ -62,34 +61,6 @@ def anonymize_user_agent(user_agent):
return user_agent


def send_to_analytics(data):
"""Sends data to Google Analytics."""
if data.get("uip") and data.get("ua"):
data["cid"] = generate_client_id(data["uip"], data["ua"])

if data.get("uip"):
# Anonymize IP address if applicable
data["uip"] = anonymize_ip_address(data["uip"])

if data.get("ua"):
# Anonymize user agent if it is rare
data["ua"] = anonymize_user_agent(data["ua"])

resp = None
log.debug("Sending data to analytics.", data=data)
try:
resp = requests.post(
"https://www.google-analytics.com/collect",
data=data,
timeout=3, # seconds
)
except requests.Timeout:
log.warning("Timeout sending to Google Analytics")

if resp and not resp.ok:
log.warning("Unknown error sending to Google Analytics")


def generate_client_id(ip_address, user_agent):
"""
Create an advertising ID.
Expand Down
11 changes: 0 additions & 11 deletions readthedocs/proxito/views/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
from django.views.static import serve
from slugify import slugify as unicode_slugify

from readthedocs.analytics.tasks import analytics_event
from readthedocs.analytics.utils import get_client_ip
from readthedocs.audit.models import AuditLog
from readthedocs.builds.constants import INTERNAL
from readthedocs.core.resolver import Resolver
Expand Down Expand Up @@ -120,15 +118,6 @@ def _serve_dowload(self, request, project, version, type_):
download=True,
)

# Send media download to analytics - sensitive data is anonymized
analytics_event.delay(
event_category="Build Media",
event_action=f"Download {type_}",
event_label=str(version),
ua=request.headers.get("User-Agent"),
uip=get_client_ip(request),
)

response = self._serve_file(
request=request,
storage_path=storage_path,
Expand Down

0 comments on commit 176fe58

Please sign in to comment.