2
0
mirror of https://github.com/offen/website.git synced 2024-11-23 01:20:29 +01:00

Merge pull request #133 from offen/development

Add articel, minor page wide updates
This commit is contained in:
Hendrik Niefeld 2021-01-06 09:53:32 +01:00 committed by GitHub
commit da2aca62c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 294 additions and 150 deletions

1
.gitignore vendored
View File

@ -115,3 +115,4 @@ venv.bak/
test.py
*.json
homepage/cache

View File

@ -1,9 +1,13 @@
version: '3'
services:
homepage:
proxy:
image: nginx:1.17-alpine
volumes:
- output:/usr/share/nginx/html
ports:
- 8000:8000
- 8000:80
homepage:
build:
context: '.'
dockerfile: ./Dockerfile.python
@ -11,9 +15,11 @@ services:
volumes:
- .:/website
- homepagedeps:/root/.local
command: make devserver
- output:/website/homepage/output
command: make regenerate
environment:
DEBUG: 1
volumes:
homepagedeps:
output:

View File

@ -23,10 +23,10 @@ Although we have dug very deep, things may still contain issues. Therefore, we r
## Offen v0.1.0-alpha.3
#### Single binary file for Linux, Windows or MacOS
##### Single binary file for Linux, Windows or MacOS
[Download](https://get.offen.dev/){: data-button="full"}
#### Your own Offen instance
##### Your own Offen instance
[Deploy to Heroku](https://heroku.com/deploy?template=https://github.com/offen/heroku/tree/master){: target="_blank" data-button-mb5="full"}
Download or deploy Offen today and give it a spin. *[Check our Docs](https://docs.offen.dev/){: target="_blank"} for detailed instructions.*

View File

@ -65,7 +65,7 @@ Offen generates client side keys for encrypting data for each user. At the end o
### 1-Click Deploy
Self hosted software is a great fit for privacy focused software like Offen. Yet, it can seem daunting to non-technical users and make them stick to established SaaS solutions longer than needed. This is why we put a lot of effort into finding easy "1-click" options to deploy an Offen instance. In Milestone 3 we have created a 1-click solution for deploying Offen to Heroku: [https://github.com/offen/heroku](https://github.com/offen/heroku). Using free resources only, people interested in running Offen can now deploy a production ready instance to Heroku in less than 1 minute. We hope this encourages website operator to consider self-hosted software and Offen as a real option. Required changes for this were implemented in [PR 287](https://github.com/offen/offen/pull/287).
Self hosted software is a great fit for privacy focused software like Offen. Yet, it can seem daunting to non-technical users and make them stick to established SaaS solutions longer than needed. This is why we put a lot of effort into finding easy "1-click" options to deploy an Offen instance. In Milestone 3 we have created a 1-click solution for deploying Offen to Heroku: [https://github.com/offen/heroku](https://github.com/offen/heroku). Using free resources only, people interested in running Offen can now deploy a production ready instance to Heroku in less than 1 minute. We hope this encourages website operator to consider self hosted software and Offen as a real option. Required changes for this were implemented in [PR 287](https://github.com/offen/offen/pull/287).
<img class="screencast mt3 mb2" alt="browser setup" src="/theme/images/offen-blog-0050_oneClickDeploy.gif"/>

View File

@ -44,7 +44,7 @@ This has been implemented in PRs [362](https://github.com/offen/offen/pull/362),
### Improved demo
For self-hosted software like Offen, giving potential users an idea of what the software looks like without having to do a proper install. Many softwares do this by sharing the credentials for a demo account on their website, but in the case of Offen we do not want to do this as it would expose the usage data of our real world users - which is what we are trying to protect with Offen.
For self hosted software like Offen, giving potential users an idea of what the software looks like without having to do a proper install. Many softwares do this by sharing the credentials for a demo account on their website, but in the case of Offen we do not want to do this as it would expose the usage data of our real world users - which is what we are trying to protect with Offen.
This is why we built a downloadable demo of Offen that you can run on your local machine. This demo exists for a while now, but with Milestone 4 we made major improvements to this feature:
@ -122,7 +122,7 @@ describe('Consent', function () {
Now that we have a basic idea of how such a test looks like, let's add interaction and check for their immediate effects on the UI:
```jsx
it('displays a link to the Auditorium after opt in only', function () {
it('displays a link to the Auditorium after opt-in only', function () {
cy.visit('/')
cy.contains('Open Auditorium').should('not.exist')
cy.contains('Yes please').click()
@ -151,10 +151,10 @@ it('allows users to opt out and delete all of their data', function () {
cy.contains('Open Auditorium').click()
cy.url().should('include', '/auditorium/')
cy.contains('Opt out').should('exist')
cy.contains('Opt out').click()
cy.contains('Opt-out').should('exist')
cy.contains('Opt-out').click()
cy.contains('Opt out').should('not.exist')
cy.contains('Opt-out').should('not.exist')
cy.contains('Unique websites').prev('p').should('eq', '0')
})
```

View File

@ -5,11 +5,12 @@ slug: hosting-offen-on-budget
sitemap_priority: 0.7
image_url: /theme/images/offen-blog-0070-budget.jpg
author: Frederik Ring
must_read: True
bottom_cta: blog
# Hosting Offen on a budget
Using self-hosted software like Offen when you're on a budget can seem daunting as you usually don't know too much about the performance requirements of the software you are planning to use beforehand. Once you do know, you might have locked in yourself already.
Using self hosted software like Offen when you're on a budget can seem daunting as you usually don't know too much about the performance requirements of the software you are planning to use beforehand. Once you do know, you might have locked in yourself already.
In this article we collect a few real world options and scenarios for hosting Offen on a budget and compare how they relate in terms of ease of deployment, performance and pricing.

View File

@ -23,7 +23,7 @@ We as Offen are convinced that all these 'privacy friendly' approaches are an im
Users continue to be unaware what kind of data is collected and how it is being used. They still cannot access or delete it. This leaves them in the dark about their situation and does not help to reduce the latent distrust against web operators. A problem that GDPR also addresses explicitly under the headline 'Rights of the data subject'.
This is why we develop a fair and open web analytics tool that finally treats *operators and users as equal parties.*
Usage data is only collected after opt in. If users choose to opt in, they have full access to their data and can also delete it. The collected data is presented to the user with explanations that describe why a particular metric is relevant and what the privacy implications are.
Usage data is only collected after opt-in. If users choose to opt in, they have full access to their data and can also delete it. The collected data is presented to the user with explanations that describe why a particular metric is relevant and what the privacy implications are.
At the same time essential metrics give operators the chance to gain valuable insights. They can improve their services without violating the privacy of their users.
By the way, Offen is in beta phase now. [Please take a look and give it a try.](/try-demo/)

View File

@ -13,11 +13,11 @@ bottom_cta: fair
Matomo was started around 2007 as a successor to phpMyVisites and *open-source alternative to Google Analytics.* The project founded by Matthieu Aubry used to be called Piwik until it was rebranded to its current name in 2018. According to Wikipedia it is installed on about 1.5 million websites, making it one of the best known open source web analytics applications on the market.
Operators interested in open and privacy friendly web analytics particularly appreciate Matomo's ability to be self-hosted. The respective app variant called "Matomo On-Premise" has no license costs, but paid plugins are necessary for extensive use.
Operators interested in open and privacy friendly web analytics particularly appreciate Matomo's ability to be self hosted. The respective app variant called "Matomo On-Premise" has no license costs, but paid plugins are necessary for extensive use.
### Room for improvement
Despite the general popularity, there are some problems with Matomo's decisions regarding privacy. By default, the software only offers an opt out feature for website users. This way, *consent is practically a preset.* In addition, access to usage data is not automated and therefore can be very complex and laborious for users. A common problem which the GDPR mandates explicitly under the heading ["Rights of the data subject"](https://en.wikipedia.org/wiki/General_Data_Protection_Regulation#III_Rights_of_the_data_subject){: target="_blank"}.
Despite the general popularity, there are some problems with Matomo's decisions regarding privacy. By default, the software only offers an opt-out feature for website users. This way, *consent is practically a preset.* In addition, access to usage data is not automated and therefore can be very complex and laborious for users. A common problem which the GDPR mandates explicitly under the heading ["Rights of the data subject"](https://en.wikipedia.org/wiki/General_Data_Protection_Regulation#III_Rights_of_the_data_subject){: target="_blank"}.
On the technical side, the following issues are particularly apparent. Installing Matomo can be a bit of a pain as there are many dependencies that must be pre-installed on the system. This also applies to the requirement to use a dedicated MySQL database, which makes installation even more complex. Last but not least, the tracking script that Matomo uses is extensive and therefore delays the loading of the pages considerably.
@ -27,7 +27,7 @@ On the technical side, the following issues are particularly apparent. Installin
To address the above mentioned issues we develop a fair and lightweigt web analytics tool that treats operators and users as equal parties. It is called Offen and is [available as a beta version.](https://www.offen.dev/get-started/)
*Offen's default is to NOT collect any data.* Usage data is collected after opt in only. If users choose to opt in, they have full access to their data. They can delete it any time or opt out completly.
*Offen's default is to NOT collect any data.* Usage data is collected after opt-in only. If users choose to opt in, they have full access to their data. They can delete it any time or opt out completly.
The collected data is presented to users with explanations that describe why a particular metric is relevant and what the privacy implications are. This helps to strengthen trust in operators.

View File

@ -11,7 +11,7 @@ bottom_cta: blog
It feels a little surreal to write this, but: this post marks the end of Milestone 6, which is the last one defined in our initial product plan defining the scope of our support by the [NGI Zero PET initiative](https://nlnet.nl/thema/NGIZeroPET.html){: target="_blank"}.
In these last weeks we focused on packaging and testing, which - who would have thought - uncovered some issues we didn't know about yet. But it also felt very rewarding to see the work of the last ~9 months paying off, now that we and others can deploy and use Offen easily. Having designed Offen as a self-hosted solution from the start, we managed to establish a unique characteristic when comparing Offen with other solutions out there: if you're looking to self host your analytics software, it won't get much easier. If you are unsure about that claim, check out the rest of this post to see what that actually means.
In these last weeks we focused on packaging and testing, which - who would have thought - uncovered some issues we didn't know about yet. But it also felt very rewarding to see the work of the last ~9 months paying off, now that we and others can deploy and use Offen easily. Having designed Offen as a self hosted solution from the start, we managed to establish a unique characteristic when comparing Offen with other solutions out there: if you're looking to self host your analytics software, it won't get much easier. If you are unsure about that claim, check out the rest of this post to see what that actually means.
During Milestone 6 we have released the following versions:

View File

@ -1,13 +1,14 @@
title: Opt in for quality insights
title: Opt-in for quality insights
description: Collecting data only with user consent has a less obvious implication: the quality of insights from web analytics increases.
date: 2020-10-28
slug: opt-in-quality
sitemap_priority: 0.7
image_url: /theme/images/offen-blog-0120-opt-in-quality.jpg
author: Hendrik Niefeld
must_read: True
bottom_cta: matomo
# Opt in for quality insights
# Opt-in for quality insights
### Fair web analytics
@ -17,13 +18,13 @@ Collecting data only with *user consent has a significant impact on the quality
### Analyzing our own turf
Our own homepage [offen.dev](https://www.offen.dev/), on which of course an Offen instance is installed, can be described as rather small. It currently has an average of 280 unique users after opt in and 660 verified page views per month.
Our own homepage [offen.dev](https://www.offen.dev/), on which of course an Offen instance is installed, can be described as rather small. It currently has an average of 280 unique users after opt-in and 660 verified page views per month.
We estimate our opt in rate, meaning the percentage of website users who agree to the data collection, to be about 40%. This figure is a subjective estimate and derived solely from the personal feedback of a relatively small group of test users.
We estimate our opt-in rate, meaning the percentage of website users who agree to the data collection, to be about 40%. This figure is a subjective estimate and derived solely from the personal feedback of a relatively small group of test users.
We cannot and do not want to measure the actual rate for obvious data protection reasons. What we are sure about is that it depends very much on the content offered. In our particular case, where product and presentation are so closely interwoven, it should be rather high compared to other content.
However, we do not think it really matters to know what your opt in rate exactly is. But more about this later.
However, we do not think it really matters to know what your opt-in rate exactly is. But more about this later.
### Collecting data differently
@ -55,15 +56,15 @@ Common web analytics tools try to solve this problem by blocking single traffic
### Real human users
We don't think so. An "opt in only" policy for data collection, which is necessary anyway for privacy reasons, solves the problem along the way. Even if you wanted to, the opt in banner can only be bypassed with a lot of engineering effort. This assures real human users with a very high probability. The best starting point for the optimization of your website.
We don't think so. An "opt-in only" policy for data collection, which is necessary anyway for privacy reasons, solves the problem along the way. Even if you wanted to, the opt-in banner can only be bypassed with a lot of engineering effort. This assures real human users with a very high probability. The best starting point for the optimization of your website.
Talking about these real users brings us back to the question of whether it is important to know your exact opt in rate. For an answer, consider for which users you want to optimize your website and what kind of users you want to attract.
Talking about these real users brings us back to the question of whether it is important to know your exact opt-in rate. For an answer, consider for which users you want to optimize your website and what kind of users you want to attract.
*Those who consent are most likely interested in your content.* They support you with their usage data and may therefore be willing to support you in any other way. The exact share of these users is less interesting.
### Deeper insights for optimization
Nevertheless, common web analytics tools that collect data without user consent provide at least better results than the analysis of your server logs. Yet their quality is bound to be lower compared to the results obtained with the smaller amount of data generated by opt in only data collection. This is caused by the fact that some further issues are simply not manageable without some form of consent banner.
Nevertheless, common web analytics tools that collect data without user consent provide at least better results than the analysis of your server logs. Yet their quality is bound to be lower compared to the results obtained with the smaller amount of data generated by opt-in only data collection. This is caused by the fact that some further issues are simply not manageable without some form of consent banner.
Many users are recorded even though they have visited your website with very little or no interest. Some bounce off immediately and may just have been there by mistake. Still, all these data points are included in your analytics and will give you a distorted impression. The resulting false assumptions distract you from the important users and make it difficult for you to keep the necessary focus.

View File

@ -0,0 +1,127 @@
title: Privacy focus? Consider the cookie
description: Using cookies does not necessarily equal tracking your users. Learn how you can use cookies to respect the privacy of your users.
date: 2020-12-28
slug: privacy-cookies
sitemap_priority: 0.7
image_url: /theme/images/offen-blog-0140-privacy-cookies.jpg
author: Frederik Ring
must_read: True
bottom_cta: quality
## Privacy focus? Consider the cookie
Whoever [drafted the idea for HTTP cookies](https://tools.ietf.org/html/rfc2109){: target="_blank"} back in 1997 likely did not anticipate having created a technology that is as disputed, discussed and also disliked as it is today. A non-technical user of the internet might be under the impression that cookies are an utterly useless privacy disaster that bring you nothing but consent banners filled with dark patterns, and enable advertisers to track you on literally every website ever.
And while there are definitely problems with the modern day usage of cookies, with very good reasons to regulate their usage, they can also be used to enhance privacy on the web. Using cookies does not necessarily equal tracking your users or invading their privacy. In this article we would like to show you how you can use cookies to respect and enhance the privacy of your users.
> *Using cookies does not necessarily equal tracking your users or invading their privacy.*
---
### Collecting data should require consent, no matter your implementation details
Inside the European union the so called "[Cookie Directive](https://en.wikipedia.org/wiki/Privacy_and_Electronic_Communications_Directive_2002){: target="_blank"}" mandates acquiring consent from users for setting non-essential cookies. Similar laws exist for example in California. The internet being a global phenomenon, you are very likely to be subject to these regulations in one way or the other the moment you serve any non-trivial website. Many developers like to complain vocally about so called "cookie banners", and the number of sleazy patterns that try to trick users into consenting makes these complaints relatable. A solution that does not require user consent must surely be the better option for privacy, right?
It's not that easy though. If you think user privacy from the ground up, how do the technical details of your implementation matter? We'd argue they do not matter much. If you want to collect non-essential data from your visitors (analytics data in the case of Offen) in a privacy friendly way, you should be asking for user consent. No matter how your technical solution for doing so looks like, and no matter what regulations currently say. If you're not doing this and instead come up with something that allows you to avoid "the cookie banner" for collecting non-essential data, you are not building a privacy friendly solution, you are building a regulations friendly solution.
Think about it in this way maybe: if you feel like you really do not want ask users for consent, then maybe this is a good hint to reevaluate if you really need to collect that data you would need user consent for. Privacy values choices, and simply not making use of non-essential features should be an option for users always. Not convinced? Think about why ad blockers are so popular.
In case your conclusion is that you do need to collect the data, don't be afraid about that consent banner too much. There is absolutely nothing that requires you to use the overly complex solutions you can find on the internet way too often. Consent banners can be unobtrusive, concise and clear starting the moment when you accept a "No" just as much as you accept a "Yes".
> *Consent banners can be unobtrusive, concise and clear starting the moment when you accept a "No" just as much as you accept a "Yes".*
---
### Essential, non-essential, and what's the difference?
Regulations around data protection and collection often distinguish essential and non-essential features, and this makes a lot of sense. If a user can log in to your service and you have to store a session identifier in a cookie to enable this, it is perfectly fine to do so without consent. Having to provide credentials over and over again for every request made against your server would render your service unusable, hence it is an essential feature.
Non-essential features are usually revolving around performance and analytics. Collecting analytics data for a website definitely is not required for the user to use your service. This means it is non-essential usage and you should be asking for consent before doing so. Regulations around this topic only cover cookies, but taking privacy seriously, you would apply this principle to all techniques. On a side note, [quantity does not necessarily mean quality in web analytics](https://www.offen.dev/blog/opt-in-quality/).
Most importantly, both essential and non-essential segments require making sure their technical implementation is secure and respects user privacy as much as possible.
---
### Technical considerations for using cookies in a privacy friendly manner
Offen is a fair web analytics software. This is a promise we can only deliver with an opt-in only solution. Not having to work around a "cookie banner" (for us, that's a feature) we are free to solve any task at hand in the most privacy friendly way we can come up with. And in many cases, this means using cookies. The following collects a few guidelines we've been following when building Offen.
#### Choosing privacy friendly identifiers and values
Cookies are essentially a key-value store. It might seem tempting to store detailed and highly specific information in the values here, but let's have a look at what that would mean from a privacy perspective.
For example let's say you wanted to write a feature test, checking for whether you can set cookies in the first place, you might come up with a mechanism that writes a random value to a certain key and tries to read it again. If the value can be read and is not altered the check succeeds. However, this means the feature test does also make the user identifiable by that random token, which is a privacy implication that is not tolerable for such a basic task. Instead, you can use a static value and also a static key for all users that ever run the feature test, thus making them indistinguishable. The guideline therefore is to always use static values that are the same for each and every user, unless you really need to identify users.
If you find yourself in the situation where you do need to create an identifier that is unique to a user, cookies will give you the privacy advantage of being able to create a truly random and anonymous value (e.g. a UUID) that is not tied to any user or device specific information (as compared with for example tracking sessions by hashing a combination of IP address and User Agent string on the server, [which leaks a lot of private information, even when stored in its hashed form only](https://edps.europa.eu/data-protection/our-work/publications/papers/introduction-hash-function-personal-data_en){: target="_blank"}). Ensure you use a well-tested library for creating such identifiers. Also, consider the option of periodically rotating such tokens so that others that inadvertently get hold of such a token can only make use of it for a limited period of time.
> *Cookies will give you the privacy advantage of being able to create a truly random and anonymous value that is not tied to any user or device specific information.*
#### Allow users to delete their cookies
One of the best privacy features of cookies is: users can delete them at any time, disassociating themselves with the data tied to the previous identifiers instantly. This will never work if you use server side solutions relying in UA strings and/or IP addresses. Many users might know how to do this, but if you take privacy seriously and you are using cookies for your service, why not implement such a feature within?
#### Do not use Third Party cookies
A cookie is always bound to the domain it has been issued from. In a scenario where a page loads resources from different domains, this means that some of these resources may set or use cookies bound to a different domain than the host document is served from.
These cookies are called third-party cookies and are pretty bad for privacy, considering they can be used to follow users around the web when such third party resources are being loaded on a multitude of websites.
Luckily, usage of third party cookies is already being heavily restricted by browser vendors, and there are concrete plans to disallow their usage entirely until 2022.
However, when designing an application you might find yourself in situations where using third party cookies might become a requirement. In case such a requirement pops up, it's probably best to take a step back and reconsider the overall architecture of your application's HTTP schema. Using a third party cookie shows your application would be leaking information (both essential and non-essential) across domain boundaries. Consider consolidating all logic that requires to share such data under a single domain so that data can be neatly protected by other mechanisms such as `SameSite`.
#### Same site cookies
To preserve privacy for the values stored in the cookies you set yourself, you will want to restrict their usage to to a first-party or same-site context. In order to allow for fine grained control of this behavior, [the `SameSite` attribute](https://web.dev/samesite-cookies-explained/){: target="_blank"} got introduced in [RFC6265bis](https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03#section-4.1){: target="_blank"}.
This allows you to now set a value of either `Strict`, `Lax` or `None` for the `SameSite` attribute, limiting the scenarios in which your browser will send cookie information with requests to your domain.
Considering this article is about building secure and privacy focused applications, using `None` should not be an option here. The major difference between `Lax` and `Strict` is that `Lax` allows for cookies to be sent along with so called "top level" requests, i.e. if your site is using cookies to store a session identifier for login and a 3rd party site links to your site, using `Lax` will allow users to click that link and be logged in instantly, whereas using `Strict` would not send those cookies on the first request, but only on those initiated by the document loaded from your domain itself.
Depending on your use case, both options are valid choices and make sure you respect your users' privacy.
> *One of the best privacy features of cookies is: users can delete them at any time, disassociating themselves with the data tied to the previous identifiers instantly.*
#### Secure by default
Cookies are designed to be sent in the headers of HTTP requests. This means that when not using an encrypted connection over TLS, the values sent in plaintext and are subject to possible eavesdropping by third parties in between your user and your server.
Even while using HTTPS is becoming the default nowadays, HTTP still does exist and it's totally possible in certain setups to accidentally make HTTP requests, even when HTTPS would be available.
To protect cookie values to be sent over insecure, plain-text connections, set the `Secure` attribute on your cookies. This way, the browser will make sure to send cookies only when a request is using the `https` protocol.
#### HTTP cookies and JavaScript cookies
Cookies can be set and read in two different manners, either by using client side JavaScript, using the `document.cookie` interface or by using the `Cookie` and `Set-Cookie` HTTP Headers.
By default, cookies set by one method can be read by the other and vice-versa. This does create privacy implications though: as modern websites can load a large amount of third party code in the client, this exposes information stored in cookies to everyone who can run code on your website, e.g. third party widgets or similar.
To avoid a situation like this, the `HttpOnly` attribute can be used. When set on a cookie, it means reading from and writing to it is not possible using client side JavaScript, it can only be accessed by the server, which gives you much tighter control over the data contained.
`HttpOnly` should be the default setting when issuing cookies. Only disable when there is no other way to achieve what you need to achieve. When you have to do so, consider the information stored in that cookie public, so do never store any user identifiers, session data or similar information in a cookie that is not `HttpOnly`.
#### Scope access using domains and paths
Access rules for a cookie can be defined by using the `Domain` and `Path` parameters. The `Domain` defines the domain a cookie is sent to and `Path` limits its submission to certain sub-paths of that domain. So for example a cookie with a domain of `www.offen.dev` and a path of `/blog` would be sent along with requests of a URL beginning with `https://www.offen.dev/blog` only.
There are some interesting details about the `Domain` parameter: it is optional and when not specified at all, the cookie will be bound to the very domain that is setting the cookie. No sibling or subdomains will be allowed to access its value. When you specify a domain, this domain and all of its subdomains will be allowed to access that cookie.
Sometimes, you will also see domain values starting with a dot like `.offen.dev`, which used to indicate that the cookie should be sent to all subdomains, yet modern browsers will treat the domain [with or without the leading dot in the same way](https://tools.ietf.org/html/rfc6265#section-4.1.2.3){: target="_blank"}. It is not needed anymore.
These two mechanisms should be leveraged from the start when you are using cookies. Start by not specifying a domain and the most restrictive `Path` value you can use and only relax these rules if it is strictly necessary for your application to function. Be extra stringent about this when handling cookies that contain identifiers.
#### Expire cookies you do not need
Cookies come in two flavors: Session cookies and persistent cookies. Session cookies will be purged by your browser once your [browsing session](https://html.spec.whatwg.org/dev/history.html#browsing-session){: target="_blank"} ends, persistent cookies define a point of time where they expire themselves. Technically, it's not possible to issue a cookie that is never expiring, although you can create one that expires in a 100 years, resulting in the same effect for the end user.
Once again using the principle of [Datensparsamkeit](https://martinfowler.com/bliki/Datensparsamkeit.html){: target="_blank"} as a guideline, it's a good habit to start with all cookies being session cookies. Only make those persistent where the benefits justify the consequences of storing possibly sensitive data like user identifiers on a user's device for a prolonged period of time. Consider the trade-offs for your users when defining the expiry and err on the side of security and privacy. If you really need a very long lived cookie, look into if you could periodically refresh its value so that it does not create a potentially unwanted tracking identifier for others.
> *Start with all cookies being session cookies. Only make those persistent where the benefits justify the consequences of storing possibly sensitive data.*
---
### Wrapping up
If you find yourself building a product where privacy is important - just like we do when building Offen - feel encouraged to consider cookies as an option for your tasks. Very often, it's a robust and simple choice that is beneficial for your user's privacy when done right, and the implicit requirement for acquiring user consent is a major privacy feature.
Do you have comments or feedback about this article or about Offen in general? Tweet at us [@hioffen](https://twitter.com/hioffen){: target="_blank"} or email us at [hioffen@posteo.de](mailto:hioffen@posteo.de).

View File

@ -1,25 +1,74 @@
title: About | Offen
description: Who we are, who supports us and how you can can get in touch.
description: Who we are, what we do, who supports us and how you can can get in touch.
slug: about
bottom_cta: matomo
bottom_cta: fair
## About
### What is this thing called "my data" and why does seemingly everyone want to get hold of it?
It has a ring, gives a slight spine-chilling sensation and generates a whole lot of clicks: consumer magazines like German "Computer Bild" caution about ["Google espionage"](https://www.computerbild.de/artikel/cb-Ratgeber-Kurse-Wissen-Was-weiss-Google-ueber-Sie-2799009.html){: target="_blank"} just like the internet has countless tutorials on turning off numerous ["data leeches"](https://praxistipps.chip.de/datenkrake-windows-10-so-schalten-sie-auffaellige-funktionen-ab_99652){: target="_blank"}. Interestingly, diving into these realms will have you accidentally catching the next toolbar, malware infection or [even worse](https://blog.malwarebytes.com/cybercrime/2012/10/pick-a-download-any-download/){: target="_blank"}.
Yet, many internet users still do not know what really is happening to their data. Public relation activities trying to calm the public - as recently undertaken by Facebook [for example](https://www.zeit.de/digital/datenschutz/2019-01/social-media-facebook-mark-zuckerberg-ads-privacy-business-model-transparency){: target="_blank"} - end up being rather disturbing instead of creating transparency or adding any value to the public debate. Denelle Dixon, COO of Mozilla, just publicly [warned the European Commission](https://blog.mozilla.org/blog/2019/01/31/mozilla-raises-concerns-over-facebooks-lack-of-transparency/){: target="_blank"} about the dangerous effects an opaque apparatus such as Facebook can have on society. Updated Terms and Conditions only parenthetically mention that newly created Google accounts will now hand over real names to third parties for [advertising purposes](https://www.propublica.org/article/google-has-quietly-dropped-ban-on-personally-identifiable-web-tracking){: target="_blank"}.
<div class="flex justify-end pb5">
<img class="smaller-image" alt="Detour" src="/theme/images/gfx-deepdive-A.png"/>
</div>
As a regular user of the internet, are you really being spied upon? *What exactly is "my data"?* Can a website operator see my name when I'm using it? Does it know about my Email address or my phone number? Does it know which other websites I have been visiting, which search query led me to the site in the first place, what I have recently purchased online, or who I am acquainted with?
> "If you have something that you don't want anyone to know, maybe you shouldn't be doing it in the first place."
>
> [Eric Schmidt](https://www.eff.org/de/deeplinks/2009/12/google-ceo-eric-schmidt-dismisses-privacy){: target="_blank"} (at this time CEO of Google), 2009
We would like to turn the tables on this much quoted statement and apply it to the operators of services and websites instead of their users. The analytics software Offen *transparently and uncompromisingly discloses what data is being collected and what it is being used for* to the users.
---
### For users
Visiting a website or using a web application that utilizes Offen, the user gains access to and ownership of the usage data collected. As a guiding principle, data collection is Opt-In only. Consent can be revoked at any time, just like users can choose delete their data retroactively. The cookie used by Offen allows viewing all of the associated metrics so that users can *assert themselves what is being collected and what isn't*. Data is being displayed in an accessible and articulate manner and each metric comes with explanations about its usage, relevance and possible privacy implications.
<img class="smaller-image-2 mt3" alt="Lots of ways to break your software" src="/theme/images/gfx-deepdive-B.png"/>
### For operators
Operators of small and mid-sized websites and web applications are faced with growing challenges not only since the introduction of GDPR: how do they gain insights into what users are interested in and which of the features offered are being used? Is it possible to showcase *transparent and considerate handling of user data* - i.e. neither being spy or data leech - without surrendering and abandoning usage metrics altogether?
Choosing Offen, websites and web applications obtain a free, open and robust tool for collecting and analyzing relevant usage data. The insights gained enable continuous improvement of these services while still respecting their user's privacy. *Opening up the data to the users does not constitute a disadvantage, but strengthens the relationship with them* by being entirely transparent.
### Part of the public debate
Transparently handling usage data in the open creates mutual trust while still enabling operators to collect needed usage statistics. Offen is designed to be a mediating agent only, and does not side with either users or operators. Sharing knowledge between the two parties creates opportunities for an *open and fact based discussion* about user data and privacy. Users gain insights into what data is being collected and what these data points are used for, just like they learn about which kind of data is not part of the collection. They are enabled to reach self-determined decisions about what they consent with and what they disagree with when it comes to privacy on the web, also in other contexts than analytics.
We want to exemplify that it is time to depart the age of ["data capitalism"](https://www.zeit.de/digital/datenschutz/2019-01/datenschutz-nick-couldry-datenkolonialismus-datenhandel/komplettansicht){: target="_blank"} and to create *technologies and infrastructure that are transparent, open and oriented towards the common good*
<div class="flex justify-end">
<img class="smaller-image mt2" alt="Detour" src="/theme/images/gfx-deepdive-C.png"/>
</div>
### Offen as a technology
At runtime, Offen is just mediating exchange between users and operators. Usage data is collected in conformance to GDPR and with the concept of ["Datensparsamkeit"](https://martinfowler.com/bliki/Datensparsamkeit.html){: target="_blank"} in mind. All user data is encrypted in the browser so that it can only ever be accessed by the users themselves or the matching operator. While being collected in the context of a website or application, neither operators nor third party scripts have any possibility to access the usage data. Offen itself doesn't have any way of decrypting, processing or even selling the gathered data at any point.
The software itself, as well as *all the used tools are open source*, [project planning and technical specification](https://github.com/offen/offen){: target="_blank"} take place in the open and actively solicit feedback from the general public.
Users and operators are given intuitive and accessibility-focused tools for analyzing and managing their data in the form of a web application and a browser extension. Operators deploy the service using a simple script tag.
---
### Modus Operandi
Developing and running Offen can only work out when it is entirely *free of any kind of economic constraints or goals* and its only objective is *contributing to the common good*. Development of a prototype is reliant on public grants or similar funding sources. Long term development and maintenance of the software is tied to resources granted by foundations or being donated by the public.
### Status Quo
Offen is created by [Frederik Ring][frederik-ring]{: target="_blank"} and [Hendrik Niefeld][hendrik-niefeld]{: target="_blank"} and is currently being conceptually designed and in active development, both as a product as well as as a software.
[hendrik-niefeld]: http://niefeld.com/
[frederik-ring]: https://www.frederikring.com/
Offen is created by [Frederik Ring](https://www.frederikring.com/){: target="_blank"} and [Hendrik Niefeld](http://niefeld.com/){: target="_blank"} and is currently being conceptually designed and in active development, both as a product as well as as a software.
[![NLnet Foundation](/theme/images/nlnet-logo.svg){:width="160px" height="60px" class="mt4"}](https://nlnet.nl/){: target="_blank"}
We are happy to work with [NLnet Foundation,][nlnet-foundation]{: target="_blank"} which actively supports our efforts as part of its [Next Generation Internet][next-generation-internet]{: target="_blank"} initiative.
We are happy to work with [NLnet Foundation,](https://nlnet.nl/){: target="_blank"} which actively supports our efforts as part of its [Next Generation Internet](https://nlnet.nl/NGI/){: target="_blank"} initiative.
[nlnet-foundation]: https://nlnet.nl/
[next-generation-internet]: https://nlnet.nl/NGI/
---
### Contact

View File

@ -1,79 +0,0 @@
title: Deep dive | Offen
description: What do users know about their data? How can they access it? Do operators benefit from a careful handling of user data? Does Offen work in accordance with GDPR?
slug: deep-dive
sitemap_priority: 0.7
bottom_cta: quality
## Deep dive
### What is this thing called "my data" and why does seemingly everyone want to get hold of it?
It has a ring, gives a slight spine-chilling sensation and generates a whole lot of clicks: consumer magazines like German "Computer Bild" caution about "Google espionage" [^1] just like the internet has countless tutorials on turning off numerous "data leeches"[^2]. Interestingly, diving into these realms will have you accidentally catching the next toolbar, malware infection or even worse [^3].
[^1]: Gegen Google-Spionage wehren <https://www.computerbild.de/artikel/cb-Ratgeber-Kurse-Wissen-Was-weiss-Google-ueber-Sie-2799009.html>
[^2]: Datenkrake Windows 10: So schalten Sie auff&auml;llige Funktionen ab <https://praxistipps.chip.de/datenkrake-windows-10-so-schalten-sie-auffaellige-funktionen-ab_99652>
[^3]: Pick a Download, Any Download! <https://blog.malwarebytes.com/cybercrime/2012/10/pick-a-download-any-download/>
Yet, many internet users still do not know what really is happening to their data. Public relation activities trying to calm the public - as recently undertaken by Facebook for example [^4] - end up being rather disturbing instead of creating transparency or adding any value to the public debate. Denelle Dixon, COO of Mozilla, just publicly warned the European Commission [^5] about the dangerous effects an opaque apparatus such as Facebook can have on society. Updated Terms and Conditions only parenthetically mention that newly created Google accounts will now hand over real names to third parties for advertising purposes [^6].
[^4]: Sometimes People Assume Facebook Does Things It Doesn't Do <https://www.zeit.de/digital/datenschutz/2019-01/social-media-facebook-mark-zuckerberg-ads-privacy-business-model-transparency>
[^5]: Mozilla Raises Concerns Over Facebook's Lack of Transparency <https://blog.mozilla.org/blog/2019/01/31/mozilla-raises-concerns-over-facebooks-lack-of-transparency/>
[^6]: Google Has Quietly Dropped Ban on Personally Identifiable Web Tracking <https://www.propublica.org/article/google-has-quietly-dropped-ban-on-personally-identifiable-web-tracking>
<div class="flex justify-end pb5">
<img class="smaller-image" alt="Detour" src="/theme/images/gfx-deepdive-A.png"/>
</div>
As a regular user of the internet, are you really being spied upon? *What exactly is "my data"?* Can a website operator see my name when I'm using it? Does it know about my Email address or my phone number? Does it know which other websites I have been visiting, which search query led me to the site in the first place, what I have recently purchased online, or who I am acquainted with?
> If you have something that you don't want anyone to know, maybe you shouldn't be doing it in the first place. [^7]
>
> Eric Schmidt (at this time CEO of Google), 2009
[^7]: Google CEO Eric Schmidt Dismisses the Importance of Privacy <https://www.eff.org/de/deeplinks/2009/12/google-ceo-eric-schmidt-dismisses-privacy>
We would like to turn the tables on this much quoted statement and apply it to the operators of services and websites instead of their users. The analytics software Offen *transparently and uncompromisingly discloses what data is being collected and what it is being used for* to the users.
---
### For users
Visiting a website or using a web application that utilizes Offen, the user gains access to and ownership of the usage data collected. As a guiding principle, data collection is Opt-In only. Consent can be revoked at any time, just like users can choose delete their data retroactively. The cookie used by Offen allows viewing all of the associated metrics so that users can *assert themselves what is being collected and what isn't*. Data is being displayed in an accessible and articulate manner and each metric comes with explanations about its usage, relevance and possible privacy implications.
<img class="smaller-image-2 mt3" alt="Lots of ways to break your software" src="/theme/images/gfx-deepdive-B.png"/>
### For operators
Operators of small and mid-sized websites and web applications are faced with growing challenges not only since the introduction of GDPR: how do they gain insights into what users are interested in and which of the features offered are being used? Is it possible to showcase *transparent and considerate handling of user data* - i.e. neither being spy or data leech - without surrendering and abandoning usage metrics altogether?
Choosing Offen, websites and web applications obtain a free, open and robust tool for collecting and analyzing relevant usage data. The insights gained enable continuous improvement of these services while still respecting their user's privacy. *Opening up the data to the users does not constitute a disadvantage, but strengthens the relationship with them* by being entirely transparent.
### Part of the public debate
Transparently handling usage data in the open creates mutual trust while still enabling operators to collect needed usage statistics. Offen is designed to be a mediating agent only, and does not side with either users or operators. Sharing knowledge between the two parties creates opportunities for an *open and fact based discussion* about user data and privacy. Users gain insights into what data is being collected and what these data points are used for, just like they learn about which kind of data is not part of the collection. They are enabled to reach self-determined decisions about what they consent with and what they disagree with when it comes to privacy on the web, also in other contexts than analytics.
We want to exemplify that it is time to depart the age of "data capitalism" [^8] and to create *technologies and infrastructure that are transparent, open and oriented towards the common good*
[^8]: Vielleicht wird in Zukunft auch mit Gewalt um Daten gek&auml;mpft <https://www.zeit.de/digital/datenschutz/2019-01/datenschutz-nick-couldry-datenkolonialismus-datenhandel/komplettansicht>
<div class="flex justify-end">
<img class="smaller-image mt2" alt="Detour" src="/theme/images/gfx-deepdive-C.png"/>
</div>
### Offen as a technology
At runtime, Offen is just mediating exchange between users and operators. Usage data is collected in conformance to GDPR and with the concept of "Datensparsamkeit" [^9] in mind. All user data is encrypted in the browser so that it can only ever be accessed by the users themselves or the matching operator. While being collected in the context of a website or application, neither operators nor third party scripts have any possibility to access the usage data. Offen itself doesn't have any way of decrypting, processing or even selling the gathered data at any point.
[^9]: Datensparsamkeit <https://martinfowler.com/bliki/Datensparsamkeit.html>
The software itself, as well as *all the used tools are open source*, [project planning and technical specification][github-org]{: target="_blank"} take place in the open and actively solicit feedback from the general public.
[github-org]: https://github.com/offen
Users and operators are given intuitive and accessibility-focused tools for analyzing and managing their data in the form of a web application and a browser extension. Operators deploy the service using a simple script tag.
---
### Modus Operandi
Developing and running Offen can only work out when it is entirely *free of any kind of economic constraints or goals* and its only objective is *contributing to the common good*. Development of a prototype is reliant on public grants or similar funding sources. Long term development and maintenance of the software is tied to resources granted by foundations or being donated by the public.

View File

@ -1,6 +1,5 @@
import os
from datetime import datetime
from pelican_decorate_content import decorate_content
# If your site is available via HTTPS, make sure SITEURL begins with https://
RELATIVE_URLS = False
@ -27,7 +26,8 @@ DEFAULT_PAGINATION = False
THEME = './theme'
# Delete the output directory before generating new files.
DELETE_OUTPUT_DIRECTORY = True
DELETE_OUTPUT_DIRECTORY = False
CACHE_CONTENT = True
DIRECT_TEMPLATES = ['sitemap', 'archives']
@ -45,7 +45,7 @@ PAGE_SAVE_AS = '{slug}/index.html'
ARTICLE_SAVE_AS = 'blog/{slug}/index.html'
PLUGIN_PATHS = ['./plugins']
PLUGINS = [decorate_content, 'assets']
PLUGINS = ['decorate_content', 'assets']
MARKDOWN = {
'extension_configs': {
@ -74,12 +74,13 @@ DECORATE_CONTENT = {
'a:not([data-button])': ['gray'],
'h1': ['f2', 'normal', 'lh-title', 'mt3', 'ma0', 'mb3'],
'h2': ['f25', 'normal', 'lh-title', 'mt4', 'ma0', 'mb3'],
'h3': ['f5', 'normal', 'mt5', 'ma0', 'mb3', '.cclr-fnt-black-mid'],
'h4': ['f5', 'normal', 'mt4', 'ma0', 'mb1'], # text over button
'h5': ['f5', 'normal', 'mt2', 'ma0', 'mb1'], # not used
'h3': ['f4', 'normal', 'mt5', 'ma0', 'mb3'],
'h4': ['f5', 'normal', 'mt4', 'ma0', 'mb3'],
'h5': ['f5', 'normal', 'mt5', 'ma0', 'mb1'], # text over button
'h6': ['f5', 'lh-solid', 'normal', 'ma0', 'light-silver'], # not used
'p': ['ma0', 'pb3'],
'blockquote': ['f5', 'i', 'ma0', 'ml4-ns', 'ml3'],
'blockquote': ['f4', 'ma0', 'ph4-ns', 'pv3'],
'blockquote p': ['nb2'],
'hr': ['mt5', 'mb3', 'b--black-05']
}
@ -97,8 +98,7 @@ HEROKU_DIRECT_URL = 'https://heroku.com/deploy?template=https://github.com/offen
UBERSPACE_DIRECT_URL = 'https://lab.uberspace.de/guide_offen.html'
YUNOHOST_DIRECT_URL = 'https://github.com/offen/offen_ynh'
OFFEN_AUDITORIUM_URL = 'https://offen.offen.dev/auditorium/'
DOCS_URL_CAMPAIGN_TOP = 'https://docs.offen.dev/?utm_campaign=top'
DOCS_URL_CAMPAIGN_BOTTOM = 'https://docs.offen.dev/?utm_campaign=bottom'
DOCS_URL = 'https://docs.offen.dev/'
DOCS_GETSTARTED_URL = 'https://docs.offen.dev/running-offen/'
DOCS_GETSTARTED_URL_CAMPAIGN = 'https://docs.offen.dev/running-offen/?utm_campaign=get-started'
DOCS_TRYDEMO_URL = 'https://docs.offen.dev/running-offen/test-drive/'

View File

@ -0,0 +1 @@
from .decorate_content import *

View File

@ -0,0 +1,33 @@
from json import loads
from pelican import signals
from pelican.contents import Article, Page, Static
from bs4 import BeautifulSoup
def content_object_init(instance):
if isinstance(instance, (Article, Page, Static)):
plugin_settings = instance.settings.get("DECORATE_CONTENT", {})
content_overrides = (
instance.metadata.get("decorate_content", None)
if instance.metadata is not None
else None
)
settings = plugin_settings.copy()
settings.update(
loads(content_overrides) if content_overrides is not None else {}
)
soup = BeautifulSoup(instance._content, "html.parser")
for selector, class_names in settings.items():
elems = soup.select(selector)
for elem in elems:
elem["class"] = elem.get("class", []) + class_names
instance._content = soup.decode()
def register():
signals.content_object_init.connect(content_object_init)

View File

@ -1,5 +1,4 @@
pelican==4.0.1
pelican==4.5.3
markdown==3.1.1
git+git://github.com/miracle2k/webassets#d1f3455e383446ca4ab0c644f326ee937e68e809
beautifulsoup4==4.8.1
pelican-decorate-content==0.1.1

View File

@ -395,7 +395,9 @@ IMAGES
----------------------------------------------------*/
/* Put article image outside of container margins */
.larger-image {
/*
margin-top: -4rem;
*/
margin-left: -1rem;
margin-right: -1rem;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 166 KiB

After

Width:  |  Height:  |  Size: 587 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 KiB

After

Width:  |  Height:  |  Size: 231 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

View File

@ -1,6 +1,6 @@
{% extends "base.html" %}
{% set title = 'Blog | Offen' %}
{% set title = 'Fair Analytics Blog | Offen' %}
{% set description = 'We are Frederik and Hendrik. Here we post about how we are building a fair and open web analytics tool and what we discovered along the way.' %}
{% set href = 'blog/' %}
{% set no_stats = False %}
@ -11,7 +11,7 @@
<div class="mw8 center cclr-bg-white-responsive mt5-ns">
<div class="dib gray bg-white ph3 ph5-ns pt5">
<h2 class="f25 normal lh-title ma0 mt4 mb3">
Offen Blog
Fair Analytics Blog
</h2>
<div class="w-75-l">
<p class="ma0 mb5">
@ -23,12 +23,9 @@
<div class="flex flex-wrap">
{% for article in articles %}
<div class="w-100 w-50-l">
{% if loop.index != 1 %}
<hr class="b--none db dn-l">
{% endif %}
<article class="w-100 mt5 mt0-l mt0-l gray">
<div class="mw8 center pv5 ph3 ph5-m pr0-l pl5-l bg-white">
<figure class="larger-image mb4">
<article class="w-100 mt0-l mt0-l gray">
<div class="mw8 center pt3 pb5 ph3 ph5-m pr0-l pl5-l bg-white">
<figure class="larger-image ma0 mb4">
<a href="/blog/{{ article.slug }}/">
<img alt="{{ article.title }}" src="{{ article.image_url }}"/>
</a>
@ -36,9 +33,15 @@
<h6 class="f5 lh-solid normal ma0 light-silver">
{{ article.date | strftime('%d %b %Y') }}{% if article.modified %}(article.updated {{ article.modified | strftime('%d %b %Y') }}){% endif %}, {{ article.author }}
</h6>
<h1 class="f26 normal lh-title mt3 ma0 mb3 light-silver">
<a href="/blog/{{ article.slug }}/" class="link b dim gray">{{ article.title }}</a>
</h1>
<h1 class="f26 normal lh-title mt3 ma0 mb3 light-silver">
{% if not article.must_read %}
<a href="/blog/{{ article.slug }}/" class="link b dim gray">{{ article.title }}</a>
{% else %}
<em>
<a href="/blog/{{ article.slug }}/" class="link b dim gray">{{ article.title }}</a>
</em>
{% endif %}
</h1>
<p>
{{ article.description }} <a href="/blog/{{ article.slug }}/" class="link b dim gray">Read more</a>
</p>

View File

@ -47,15 +47,14 @@
<nav>
<div class="nav-mobile"><span id="nav-toggle"><span></span></span></div>
<ul class="nav-list">
{% if not index %}
<li>
<a class="b link dim cclr-fnt-black-mid" href="/">Summary</a>
</li>
{% endif %}
<li>
<a class="b link dim cclr-fnt-black-mid" href="/blog/">Blog</a>
</li>
<li>
<a class="b link dim cclr-fnt-black-mid" href="/deep-dive/">Deep dive</a>
</li>
<li>
<a class="b link dim cclr-fnt-black-mid" href="{{ ROADMAP }}" rel="noopener" target="_blank">Roadmap</a>
</li>
@ -66,7 +65,7 @@
<a class="b link dim cclr-fnt-black-mid" href="{{ GITHUB_REPO }}" rel="noopener" target="_blank">GitHub</a>
</li>
<li>
<a class="b link dim cclr-fnt-black-mid" href="{{ DOCS_URL_CAMPAIGN_TOP }}" rel="noopener" target="_blank">Docs</a>
<a class="b link dim cclr-fnt-black-mid" href="{{ DOCS_URL }}" rel="noopener" target="_blank">Docs</a>
</li>
<li>
<a class="b link dim" href="/get-started/">Get started</a>
@ -138,14 +137,14 @@
<div class="w-100 w-50-l">
<figure class="ma0 pr3-l mb3 mb0-l">
<a href="/blog/opt-in-quality/">
<img alt="Opt in for quality insights" src="/theme/images/offen-blog-0120-opt-in-quality.jpg">
<img alt="Opt-in for quality insights" src="/theme/images/offen-blog-0120-opt-in-quality.jpg">
</a>
</figure>
</div>
<div class="w-100 w-50-l cclr-bg-yellow-mid">
<div class="pl3-l">
<h3 class="f3 normal lh-title ma0 mb2">
<a href="/blog/opt-in-quality/" class="link b dim cclr-fnt-black-mid">Opt in for quality insights</a>
<a href="/blog/opt-in-quality/" class="link b dim cclr-fnt-black-mid">Opt-in for quality insights</a>
</h3>
<p class="ma0">
Collecting data only with user consent has a less obvious implication: the quality of insights from web analytics increases. <a href="/blog/opt-in-quality/" class="link b dim cclr-fnt-black-mid">Read more</a>
@ -261,7 +260,7 @@
<a class="link b dim gray" href="/blog/">Blog</a>
</p>
<p class="ma0">
<a class="link b dim gray" href="{{ DOCS_URL_CAMPAIGN_BOTTOM }}" rel="noopener" target="_blank">Docs</a>
<a class="link b dim gray" href="{{ DOCS_URL }}" rel="noopener" target="_blank">Docs</a>
</p>
<p class="ma0">
<a class="link b dim gray" href="{{ GITHUB_REPO }}" rel="noopener" target="_blank">GitHub</a>

View File

@ -1,4 +1,5 @@
{% extends "page.html" %}
{% set index = True %}
{% block content %}
<div class="w-100 mt5-ns cclr-bg-yellow-mid">
@ -88,7 +89,7 @@
</em>
</h2>
<p class="wx18 center ma0">
Opt in only. <i>Users must actively give their consent to data collection. All data is</i> encrypted end-to-end.
Opt-in only. <i>Users must actively give their consent to data collection. All data is</i> encrypted end-to-end.
</p>
</div>
@ -128,7 +129,7 @@
</p>
<div class="mw7 center">
<p class="f5 ma0 mt3 mb6 mh0 mh3-m mh5-l">
Web analytics <i>is still an unfair and impenetrable business.</i> A proper alternative to common tools <i>is missing. Therefore we develop one.</i> <a class="b link dim cclr-fnt-black-mid" href="/deep-dive/">Deep dive</a>
Web analytics <i>is still an unfair and impenetrable business.</i> A proper alternative to common tools <i>is missing. Therefore we develop one.</i> <a class="b link dim cclr-fnt-black-mid" href="/blog/">Learn more</a>
</p>
</div>
</div>
@ -637,7 +638,7 @@
</tr>
<tr class="bg-near-white">
<td class="tl truncate pv2 pl2 pr1">Opt in only data collection</td>
<td class="tl truncate pv2 pl2 pr1">Opt-in only data collection</td>
<td class="truncate pv2 pl2 pr1">
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="7.5" cy="7.5" r="7.5" fill="#CCCCCC"/>