chore: add dpa, update terms and privacy

This commit is contained in:
Carl-Gerhard Lindesvärd
2026-03-03 10:59:45 +01:00
parent 83761638f2
commit 9e46099246
9 changed files with 751 additions and 80 deletions

View File

@@ -67,8 +67,9 @@ With the npm package, the replay module is a dynamic import code-split by your b
| Option | Type | Default | Description |
|---|---|---|---|
| `enabled` | `boolean` | `false` | Enable session replay recording |
| `maskAllInputs` | `boolean` | `true` | Mask all input field values with `*` |
| `maskTextSelector` | `string` | `[data-openpanel-replay-mask]` | CSS selector for text elements to mask |
| `maskAllInputs` | `boolean` | `true` | Mask all input field values |
| `maskAllText` | `boolean` | `true` | Mask all text content in the recording |
| `unmaskTextSelector` | `string` | — | CSS selector for elements whose text should NOT be masked when `maskAllText` is true |
| `blockSelector` | `string` | `[data-openpanel-replay-block]` | CSS selector for elements to replace with a placeholder |
| `blockClass` | `string` | — | Class name that blocks elements from being recorded |
| `ignoreSelector` | `string` | — | CSS selector for elements excluded from interaction tracking |
@@ -79,40 +80,72 @@ With the npm package, the replay module is a dynamic import code-split by your b
## Privacy controls
Session replay captures user interactions. These options protect sensitive content before it ever leaves the browser.
Session replay captures user interactions. All text and inputs are masked by default — sensitive content is replaced with `***` before it ever leaves the browser.
### Masking inputs
### Text masking (default on)
All input fields are masked by default (`maskAllInputs: true`). Recorded values appear as `***` in the replay. Disable this only if you have a specific reason—form field contents are almost always personal data.
All text content is masked by default (`maskAllText: true`). This means visible page text, labels, and content are replaced with `***` in replays, in addition to input fields.
### Masking specific text
This is the safest default for GDPR compliance since replays cannot incidentally capture names, emails, or other personal data visible on the page.
Add `data-openpanel-replay-mask` to any element to replace its text with `***` in replays:
### Selectively unmasking text
```html
<p data-openpanel-replay-mask>Sensitive text here</p>
```
Or use a custom selector:
If your pages display non-sensitive content you want visible in replays, use `unmaskTextSelector` to opt specific elements out of masking:
```ts
sessionReplay: {
enabled: true,
maskTextSelector: '.pii, [data-sensitive]',
unmaskTextSelector: '[data-openpanel-unmask]',
}
```
```html
<h1 data-openpanel-unmask>Product Analytics</h1>
<p data-openpanel-unmask>Welcome to the dashboard</p>
<!-- This stays masked: -->
<p>John Doe · john@example.com</p>
```
You can also use any CSS selector to target elements by class, tag, or attribute:
```ts
sessionReplay: {
enabled: true,
unmaskTextSelector: '.replay-safe, nav, footer',
}
```
### Disabling full text masking
If you want to disable full text masking and return to selector-based masking, set `maskAllText: false`. In this mode only elements with `data-openpanel-replay-mask` are masked:
```ts
sessionReplay: {
enabled: true,
maskAllText: false,
}
```
```html
<p data-openpanel-replay-mask>This will be masked</p>
<p>This will be visible in replays</p>
```
<Callout type="warn">
Only disable `maskAllText` if you are confident your pages do not display personal data, or if you are masking all sensitive elements individually. You are responsible for ensuring your use of session replay complies with applicable privacy law.
</Callout>
### Blocking elements
Elements matched by `blockSelector` or `blockClass` are replaced with a same-size grey placeholder in the replay. The element and all its children are never recorded.
```html
<div data-openpanel-replay-block>
This section won't appear in replays
This section won't appear in replays at all
</div>
```
Or with a custom selector and class:
Or with a custom selector:
```ts
sessionReplay: {

View File

@@ -0,0 +1,132 @@
---
title: Data Processing Agreement
description: OpenPanel's Data Processing Agreement (DPA) under Art. 28 GDPR for cloud customers who use OpenPanel to collect analytics on their websites and applications.
---
_Last updated: March 3, 2026_
This Data Processing Agreement ("DPA") is incorporated into and forms part of the OpenPanel Terms of Service between OpenPanel AB ("OpenPanel", "we", "us") and the customer ("Controller", "you"). It applies where OpenPanel processes personal data on your behalf as part of the OpenPanel Cloud service.
## 1. Definitions
- **GDPR** means Regulation (EU) 2016/679 of the European Parliament and of the Council.
- **Controller** means you, the customer, who determines the purposes and means of processing.
- **Processor** means OpenPanel, who processes data on your behalf.
- **Personal Data**, **Processing**, **Data Subject**, and **Supervisory Authority** have the meanings given in the GDPR.
- **Sub-processor** means any third party engaged by OpenPanel to process Personal Data in connection with the service.
## 2. Our approach to privacy
OpenPanel is built to minimize personal data collection by design. We do not use cookies for analytics tracking. We do not store IP addresses. Instead, we generate a daily-rotating anonymous identifier using a one-way hash of the visitor's IP address, user agent, and project ID combined with a salt that is replaced every 24 hours. The raw IP address is discarded immediately and the identifier becomes irreversible once the salt is rotated.
The data we store per event is:
- Page URL and referrer
- Browser name and version
- Operating system name and version
- Device type, brand, and model
- City, country, and region (derived from IP at the time of the request; IP is then discarded)
- Custom event properties you choose to send
No persistent identifiers, no cookies, no cross-site tracking.
Because of this approach, the analytics data OpenPanel collects in standard website tracking mode does not constitute personal data under GDPR Art. 4(1). However, we provide this DPA for customers who require it for their own compliance documentation and records of processing activities.
**Session replay (optional feature)**
OpenPanel optionally supports session replay, which must be explicitly enabled by the Controller. When enabled, session replay records DOM snapshots and user interactions (mouse movements, clicks, scrolls) on the Controller's website using rrweb. This data is stored against the session identifier and may incidentally capture personal data visible in the page (for example, a logged-in user's name displayed in the UI). All text content and form inputs are masked by default. The Controller is responsible for ensuring their use of session replay complies with applicable privacy law, including providing appropriate notice to end users. Additional masking options are available via the SDK configuration.
## 3. Scope and roles
OpenPanel acts as a **Processor** when processing data on behalf of the Controller. You act as the **Controller** for the analytics data collected from visitors to your websites and applications.
## 4. Processor obligations
OpenPanel commits to the following:
- Process Personal Data only on your documented instructions and for no other purpose.
- Ensure that all personnel with access to Personal Data are bound by appropriate confidentiality obligations.
- Implement and maintain technical and organizational measures in accordance with Section 7 of this DPA.
- Not engage a Sub-processor without your prior general or specific written authorization and flow down equivalent data protection obligations to any Sub-processor.
- Assist you, where reasonably possible, in responding to Data Subject requests to exercise their rights under GDPR.
- Notify you without undue delay (and no later than 48 hours) upon becoming aware of a Personal Data breach.
- Make available all information necessary to demonstrate compliance with this DPA and cooperate with audits conducted by you or your designated auditor, subject to reasonable notice and confidentiality obligations.
- At your choice, delete or return all Personal Data upon termination of the service.
## 5. Your obligations as Controller
You confirm that:
- You have a lawful basis for the processing described in this DPA.
- You have provided appropriate privacy notices to your end users.
- You are responsible for the accuracy and lawfulness of the data you instruct OpenPanel to process.
## 6. Sub-processors
OpenPanel uses the following sub-processors to deliver the service. All sub-processors are located within the European Economic Area or provide adequate safeguards under GDPR Chapter V.
| Sub-processor | Purpose | Location |
|---|---|---|
| Hetzner Online GmbH | Cloud infrastructure and data storage | Germany (EU) |
| Cloudflare R2 | Backup storage | EU |
We will inform you of any intended changes to this list (additions or replacements) with reasonable notice, giving you the opportunity to object.
## 7. Technical and organizational measures
OpenPanel implements the following measures under GDPR Art. 32:
**Data minimization and anonymization**
- IP addresses are never stored. They are used only to derive geolocation and generate an anonymous daily identifier, then discarded.
- Daily-rotating cryptographic salts ensure visitor identifiers cannot be reversed or linked to individuals after 24 hours.
- No cookies or persistent cross-device identifiers are used.
**Access control**
- Dashboard access is protected by authentication and role-based access control.
- Production systems are accessible only to authorized personnel.
**Encryption and transport security**
- All data is transmitted over HTTPS (TLS).
**Infrastructure and availability**
- All data is hosted on Hetzner servers located in Germany within the EU.
- Regular backups are performed.
- No data leaves the EEA in the course of normal operations.
**Incident response**
- We maintain procedures for detecting, reporting, and investigating Personal Data breaches.
- In the event of a breach affecting your data, we will notify you within 48 hours of becoming aware.
**Open source**
- The OpenPanel codebase is publicly available on GitHub, allowing independent review of our data handling practices.
## 8. International data transfers
OpenPanel stores and processes all analytics data on Hetzner infrastructure located in Germany. No Personal Data is transferred to countries outside the EEA in the course of delivering the service.
## 9. Data retention and deletion
**Analytics events** are retained for as long as your account is active. We do not currently enforce a maximum retention period on analytics event data. If we introduce a retention limit in the future, we will notify all customers in advance.
**Session replays** are retained for 30 days and then permanently deleted.
You can delete individual projects, all associated data, or your entire account at any time from within the dashboard. Upon account termination we will delete your data within 30 days unless we are required by law to retain it longer.
## 10. Governing law
This DPA is governed by the laws of Sweden and is interpreted in accordance with the GDPR.
## 11. How to execute this DPA
Using OpenPanel Cloud constitutes acceptance of this DPA as part of our Terms of Service.
If your organization requires a signed copy for your records of processing activities, you can download a pre-signed version below. Fill in your company details and countersign — no need to send it back to us.
[Download pre-signed DPA](/dpa/download)
## Contact
For questions about this DPA or data protection at OpenPanel:
- Email: [hello@openpanel.dev](mailto:hello@openpanel.dev)
- Company: OpenPanel AB, Sankt Eriksgatan 100, 113 31 Stockholm, Sweden

View File

@@ -3,6 +3,8 @@ title: Privacy Policy
description: Our privacy policy outlines how we handle your data, including usage information and cookies, to provide and improve our services.
---
_Last updated: March 3, 2026_
This Privacy Policy describes Our policies and procedures on the collection, use and disclosure of Your information when You use the Service and tells You about Your privacy rights and how the law protects You.
We use Your Personal data to provide and improve the Service. By using the Service, You agree to the collection and use of information in accordance with this Privacy Policy.
@@ -23,7 +25,7 @@ For the purposes of this Privacy Policy:
- **Application** refers to Openpanel, the software program provided by the Company.
- **Company** (referred to as either "the Company", "We", "Us" or "Our" in this Agreement) refers to Coderax AB, Sankt Eriksgatan 100, 113 31, Stockholm.
- **Company** (referred to as either "the Company", "We", "Us" or "Our" in this Agreement) refers to OpenPanel AB, Sankt Eriksgatan 100, 113 31, Stockholm.
- **Cookies** are small files that are placed on Your computer, mobile device or any other device by a website, containing the details of Your browsing history on that website among its many uses.
@@ -43,65 +45,44 @@ For the purposes of this Privacy Policy:
- **You** means the individual accessing or using the Service, or the company, or other legal entity on behalf of which such individual is accessing or using the Service, as applicable.
## What we do not collect
OpenPanel is built around the principle of collecting as little data as possible. When you use OpenPanel to track visitors on your websites and applications, the following is true:
- **No IP addresses are stored.** IP addresses are used transiently to derive city-level geolocation and to generate an anonymous visitor identifier. The raw IP address is discarded immediately after.
- **No cookies are used for analytics tracking.** We do not set any tracking cookies on your visitors' browsers.
- **No persistent cross-device identifiers.** Visitor identifiers are generated using a daily-rotating cryptographic hash of the IP address, user agent, and project ID. The hash cannot be reversed and becomes meaningless after 24 hours.
- **No behavioral profiling.** We do not build profiles of individual users or track visitors across different websites.
- **No data sold to third parties.** We will never sell, share, or transfer your data for advertising or any other commercial purpose.
## Collecting and Using Your Personal Data
### Types of Data Collected
#### Personal Data
#### Analytics data (visitor data on your websites)
While using Our Service, We may ask You to provide Us with certain personally identifiable information that can be used to contact or identify You. Personally identifiable information may include, but is not limited to:
When the OpenPanel tracking script is installed on a website, the following aggregated, anonymized data is collected per event:
- Email address
- First name and last name
- Usage Data
- Page URL and referrer
- Browser name and version
- Operating system name and version
- Device type, brand, and model
- City, country, and region (derived from IP at request time; IP then discarded)
- Custom event properties the website owner chooses to send
#### Usage Data
No IP addresses, no cookies, no names, no email addresses, and no persistent identifiers are stored.
Usage Data is collected automatically when using the Service.
#### Account data (OpenPanel dashboard users)
Usage Data may include information such as Your Device's Internet Protocol address (e.g. IP address), browser type, browser version, the pages of our Service that You visit, the time and date of Your visit, the time spent on those pages, unique device identifiers and other diagnostic data.
When you create an OpenPanel account, we collect:
When You access the Service by or through a mobile device, We may collect certain information automatically, including, but not limited to, the type of mobile device You use, Your mobile device unique ID, the IP address of Your mobile device, Your mobile operating system, the type of mobile Internet browser You use, unique device identifiers and other diagnostic data.
- Email address (required for login and transactional notifications)
- Name (optional, used for display purposes)
- Billing information (processed by our payment provider; we do not store full card details)
We may also collect information that Your browser sends whenever You visit our Service or when You access the Service by or through a mobile device.
#### Dashboard session
#### Tracking Technologies and Cookies
We use Cookies and similar tracking technologies to track the activity on Our Service and store certain information. Tracking technologies used are beacons, tags, and scripts to collect and track information and to improve and analyze Our Service. The technologies We use may include:
- **Cookies or Browser Cookies.** A cookie is a small file placed on Your Device. You can instruct Your browser to refuse all Cookies or to indicate when a Cookie is being sent. However, if You do not accept Cookies, You may not be able to use some parts of our Service. Unless you have adjusted Your browser setting so that it will refuse Cookies, our Service may use Cookies.
- **Web Beacons.** Certain sections of our Service and our emails may contain small electronic files known as web beacons (also referred to as clear gifs, pixel tags, and single-pixel gifs) that permit the Company, for example, to count users who have visited those pages or opened an email and for other related website statistics (for example, recording the popularity of a certain section and verifying system and server integrity).
Cookies can be "Persistent" or "Session" Cookies. Persistent Cookies remain on Your personal computer or mobile device when You go offline, while Session Cookies are deleted as soon as You close Your web browser. You can learn more about cookies [here](https://www.termsfeed.com/blog/cookies/#What_Are_Cookies).
We use both Session and Persistent Cookies for the purposes set out below:
- **Necessary / Essential Cookies**
Type: Session Cookies
Administered by: Us
Purpose: These Cookies are essential to provide You with services available through the Website and to enable You to use some of its features. They help to authenticate users and prevent fraudulent use of user accounts. Without these Cookies, the services that You have asked for cannot be provided, and We only use these Cookies to provide You with those services.
- **Cookies Policy / Notice Acceptance Cookies**
Type: Persistent Cookies
Administered by: Us
Purpose: These Cookies identify if users have accepted the use of cookies on the Website.
- **Functionality Cookies**
Type: Persistent Cookies
Administered by: Us
Purpose: These Cookies allow us to remember choices You make when You use the Website, such as remembering your login details or language preference. The purpose of these Cookies is to provide You with a more personal experience and to avoid You having to re-enter your preferences every time You use the Website.
For more information about the cookies we use and your choices regarding cookies, please visit our Cookies Policy or the Cookies section of our Privacy Policy.
We use a single server-side session cookie to keep you logged in to the OpenPanel dashboard. This cookie is strictly necessary for authentication and is not used for tracking or analytics purposes. It is deleted when you log out or your session expires.
### Use of Your Personal Data
@@ -143,13 +124,11 @@ The Company will retain Your Personal Data only for as long as is necessary for
The Company will also retain Usage Data for internal analysis purposes. Usage Data is generally retained for a shorter period of time, except when this data is used to strengthen the security or to improve the functionality of Our Service, or We are legally obligated to retain this data for longer time periods.
### Transfer of Your Personal Data
### Data storage and transfers
Your information, including Personal Data, is processed at the Company's operating offices and in any other places where the parties involved in the processing are located. It means that this information may be transferred to — and maintained on — computers located outside of Your state, province, country or other governmental jurisdiction where the data protection laws may differ than those from Your jurisdiction.
All analytics data is stored on Hetzner infrastructure located in Germany. All backups are stored on Cloudflare R2 within the EU. No analytics data is transferred outside the European Economic Area.
Your consent to this Privacy Policy followed by Your submission of such information represents Your agreement to that transfer.
The Company will take all steps reasonably necessary to ensure that Your data is treated securely and in accordance with this Privacy Policy and no transfer of Your Personal Data will take place to an organization or a country unless there are adequate controls in place including the security of Your data and other personal information.
Account data (email, name, billing) is processed within the EU. Our payment processor and transactional email provider operate under EU data protection standards.
### Delete Your Personal Data
@@ -197,6 +176,10 @@ Our Service may contain links to other websites that are not operated by Us. If
We have no control over and assume no responsibility for the content, privacy policies or practices of any third party sites or services.
## Data Processing Agreement
If you use OpenPanel Cloud to collect analytics on behalf of your own users, OpenPanel acts as a data processor and you act as the data controller. Our Data Processing Agreement (DPA) governs this relationship and forms part of our Terms of Service. You can read and download a signed copy at [openpanel.dev/dpa](/dpa).
## Changes to this Privacy Policy
We may update Our Privacy Policy from time to time. We will notify You of any changes by posting the new Privacy Policy on this page.

View File

@@ -3,6 +3,8 @@ title: Terms of Service
description: Legal terms and conditions governing the use of Openpanel's services and website.
---
_Last updated: March 3, 2026_
Please read these terms and conditions carefully before using Our Service.
## Interpretation and Definitions
@@ -25,7 +27,7 @@ For the purposes of these Terms and Conditions:
- **Country** refers to: Sweden
- **Company** (referred to as either "the Company", "We", "Us" or "Our" in this Agreement) refers to Coderax AB, Sankt Eriksgatan 100, 113 31, Stockholm.
- **Company** (referred to as either "the Company", "We", "Us" or "Our" in this Agreement) refers to OpenPanel AB, Sankt Eriksgatan 100, 113 31, Stockholm.
- **Device** means any device that can access the Service such as a computer, a cellphone or a digital tablet.
@@ -55,6 +57,16 @@ You represent that you are over the age of 18. The Company does not permit those
Your access to and use of the Service is also conditioned on Your acceptance of and compliance with the Privacy Policy of the Company. Our Privacy Policy describes Our policies and procedures on the collection, use and disclosure of Your personal information when You use the Application or the Website and tells You about Your privacy rights and how the law protects You. Please read Our Privacy Policy carefully before using Our Service.
## Data Processing Agreement
Our Data Processing Agreement (DPA) under the European General Data Protection Regulation (GDPR) forms part of these Terms of Service. By using OpenPanel Cloud, you agree to the terms of the DPA. A copy is available at [openpanel.dev/dpa](/dpa).
## Your Data
You retain full ownership of all data you submit to the Service, including analytics data collected from your websites and applications. The Company claims no intellectual property rights over your data.
We will never sell, share, or transfer your data to third parties for advertising, marketing, or any commercial purpose. Your data is used solely to provide and improve the Service for you.
## Subscriptions
### Subscription period
@@ -157,14 +169,6 @@ If You have any concern or dispute about the Service, You agree to first try to
If You are a European Union consumer, you will benefit from any mandatory provisions of the law of the country in which You are resident.
## United States Federal Government End Use Provisions
If You are a U.S. federal government end user, our Service is a "Commercial Item" as that term is defined at 48 C.F.R. §2.101.
## United States Legal Compliance
You represent and warrant that (i) You are not located in a country that is subject to the United States government embargo, or that has been designated by the United States government as a "terrorist supporting" country, and (ii) You are not listed on any United States government list of prohibited or restricted parties.
## Severability and Waiver
### Severability

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@@ -0,0 +1,498 @@
'use client';
import Image from 'next/image';
export default function DpaDownloadPage() {
return (
<div className="min-h-screen bg-white text-black">
{/* Print button - hidden when printing */}
<div className="sticky top-0 z-10 flex justify-end gap-3 border-gray-200 border-b bg-white px-8 py-3 print:hidden">
<button
className="rounded bg-black px-4 py-2 font-medium text-sm text-white hover:bg-gray-800"
onClick={() => window.print()}
type="button"
>
Download / Print PDF
</button>
</div>
<div className="mx-auto max-w-3xl px-8 py-12 print:py-0">
{/* Header */}
<div className="mb-10 border-gray-300 border-b pb-8">
<p className="mb-1 text-gray-500 text-xs uppercase tracking-widest">
OpenPanel AB
</p>
<h1 className="mb-2 font-bold text-3xl">Data Processing Agreement</h1>
<p className="text-gray-500 text-sm">
Version 1.0 &middot; Last updated: March 3, 2026
</p>
</div>
<p className="mb-8 text-gray-700 text-sm leading-relaxed">
This Data Processing Agreement ("DPA") is entered into between
OpenPanel AB ("OpenPanel", "Processor") and the customer identified in
the signature block below ("Controller"). It applies where OpenPanel
processes personal data on behalf of the Controller as part of the
OpenPanel Cloud service, and forms part of the OpenPanel Terms of
Service.
</p>
<Section number="1" title="Definitions">
<ul className="list-none space-y-2 text-gray-700 text-sm">
<li>
<strong>GDPR</strong> means Regulation (EU) 2016/679 of the
European Parliament and of the Council.
</li>
<li>
<strong>Controller</strong> means the customer, who determines the
purposes and means of processing.
</li>
<li>
<strong>Processor</strong> means OpenPanel, who processes data on
the Controller's behalf.
</li>
<li>
<strong>Personal Data</strong>, <strong>Processing</strong>,{' '}
<strong>Data Subject</strong>, and{' '}
<strong>Supervisory Authority</strong> have the meanings given in
the GDPR.
</li>
<li>
<strong>Sub-processor</strong> means any third party engaged by
OpenPanel to process Personal Data in connection with the service.
</li>
</ul>
</Section>
<Section number="2" title="Our approach to privacy">
<p className="mb-3 text-gray-700 text-sm leading-relaxed">
OpenPanel is built to minimize personal data collection by design.
We do not use cookies for analytics tracking. We do not store IP
addresses. Instead, we generate a daily-rotating anonymous
identifier using a one-way hash of the visitor's IP address, user
agent, and project ID combined with a salt that is replaced every 24
hours. The raw IP address is discarded immediately and the
identifier becomes irreversible once the salt is rotated.
</p>
<p className="mb-2 text-gray-700 text-sm">
The data we store per event is:
</p>
<ul className="mb-3 list-disc space-y-1 pl-5 text-gray-700 text-sm">
<li>Page URL and referrer</li>
<li>Browser name and version</li>
<li>Operating system name and version</li>
<li>Device type, brand, and model</li>
<li>
City, country, and region (derived from IP at the time of the
request; IP is then discarded)
</li>
<li>Custom event properties the Controller chooses to send</li>
</ul>
<p className="mb-3 text-gray-700 text-sm">
No persistent identifiers, no cookies, no cross-site tracking.
Because of this approach, the analytics data OpenPanel collects in
standard website tracking mode does not constitute personal data
under GDPR Art. 4(1). We provide this DPA for Controllers who
require it for their own compliance documentation and records of
processing activities.
</p>
<p className="mb-1 text-gray-700 text-sm font-semibold">
Session replay (optional feature)
</p>
<p className="text-gray-700 text-sm">
OpenPanel optionally supports session replay, which must be
explicitly enabled by the Controller. When enabled, session replay
records DOM snapshots and user interactions (mouse movements, clicks,
scrolls) using rrweb. All text content and form inputs are masked by
default. The Controller is responsible for ensuring their use of
session replay complies with applicable privacy law, including
providing appropriate notice to end users.
</p>
</Section>
<Section number="3" title="Scope and roles">
<p className="text-gray-700 text-sm leading-relaxed">
OpenPanel acts as a Processor when processing data on behalf of the
Controller. The Controller is responsible for the analytics data
collected from visitors to their websites and applications.
</p>
</Section>
<Section number="4" title="Processor obligations">
<p className="mb-2 text-gray-700 text-sm">
OpenPanel commits to the following:
</p>
<ul className="list-disc space-y-1 pl-5 text-gray-700 text-sm">
<li>
Process Personal Data only on the Controller's documented
instructions and for no other purpose.
</li>
<li>
Ensure that all personnel with access to Personal Data are bound
by appropriate confidentiality obligations.
</li>
<li>
Implement and maintain technical and organizational measures in
accordance with Section 7 of this DPA.
</li>
<li>
Not engage a Sub-processor without prior general or specific
written authorization and flow down equivalent data protection
obligations to any Sub-processor.
</li>
<li>
Assist the Controller, where reasonably possible, in responding to
Data Subject requests to exercise their rights under GDPR.
</li>
<li>
Notify the Controller without undue delay (and no later than 48
hours) upon becoming aware of a Personal Data breach.
</li>
<li>
Make available all information necessary to demonstrate compliance
with this DPA and cooperate with audits conducted by the
Controller or their designated auditor, subject to reasonable
notice and confidentiality obligations.
</li>
<li>
At the Controller's choice, delete or return all Personal Data
upon termination of the service.
</li>
</ul>
</Section>
<Section number="5" title="Controller obligations">
<p className="mb-2 text-gray-700 text-sm">
The Controller confirms that:
</p>
<ul className="list-disc space-y-1 pl-5 text-gray-700 text-sm">
<li>
They have a lawful basis for the processing described in this DPA.
</li>
<li>
They have provided appropriate privacy notices to their end users.
</li>
<li>
They are responsible for the accuracy and lawfulness of the data
they instruct OpenPanel to process.
</li>
</ul>
</Section>
<Section number="6" title="Sub-processors">
<p className="mb-3 text-gray-700 text-sm">
OpenPanel uses the following sub-processors to deliver the service:
</p>
<table className="mb-3 w-full border-collapse text-sm">
<thead>
<tr className="border border-gray-300 bg-gray-50">
<th className="border border-gray-300 px-3 py-2 text-left font-semibold">
Sub-processor
</th>
<th className="border border-gray-300 px-3 py-2 text-left font-semibold">
Purpose
</th>
<th className="border border-gray-300 px-3 py-2 text-left font-semibold">
Location
</th>
</tr>
</thead>
<tbody>
<tr>
<td className="border border-gray-300 px-3 py-2">
Hetzner Online GmbH
</td>
<td className="border border-gray-300 px-3 py-2">
Cloud infrastructure and data storage
</td>
<td className="border border-gray-300 px-3 py-2">
Germany (EU)
</td>
</tr>
<tr>
<td className="border border-gray-300 px-3 py-2">
Cloudflare R2
</td>
<td className="border border-gray-300 px-3 py-2">
Backup storage
</td>
<td className="border border-gray-300 px-3 py-2">EU</td>
</tr>
</tbody>
</table>
<p className="text-gray-700 text-sm">
OpenPanel will inform the Controller of any intended changes to this
list with reasonable notice, giving the Controller the opportunity
to object.
</p>
</Section>
<Section number="7" title="Technical and organizational measures">
<div className="space-y-4 text-gray-700 text-sm">
<div>
<p className="mb-1 font-semibold">
Data minimization and anonymization
</p>
<ul className="list-disc space-y-1 pl-5">
<li>
IP addresses are never stored. They are used only to derive
geolocation and generate an anonymous daily identifier, then
discarded.
</li>
<li>
Daily-rotating cryptographic salts ensure visitor identifiers
cannot be reversed or linked to individuals after 24 hours.
</li>
<li>
No cookies or persistent cross-device identifiers are used.
</li>
</ul>
</div>
<div>
<p className="mb-1 font-semibold">Access control</p>
<ul className="list-disc space-y-1 pl-5">
<li>
Dashboard access is protected by authentication and role-based
access control.
</li>
<li>
Production systems are accessible only to authorized
personnel.
</li>
</ul>
</div>
<div>
<p className="mb-1 font-semibold">
Encryption and transport security
</p>
<ul className="list-disc space-y-1 pl-5">
<li>All data is transmitted over HTTPS (TLS).</li>
</ul>
</div>
<div>
<p className="mb-1 font-semibold">
Infrastructure and availability
</p>
<ul className="list-disc space-y-1 pl-5">
<li>
All data is hosted on Hetzner servers located in Germany
within the EU.
</li>
<li>Regular backups are performed.</li>
<li>
No data leaves the EEA in the course of normal operations.
</li>
</ul>
</div>
<div>
<p className="mb-1 font-semibold">Incident response</p>
<ul className="list-disc space-y-1 pl-5">
<li>
We maintain procedures for detecting, reporting, and
investigating Personal Data breaches.
</li>
<li>
In the event of a breach affecting the Controller's data, we
will notify them within 48 hours of becoming aware.
</li>
</ul>
</div>
<div>
<p className="mb-1 font-semibold">Open source</p>
<ul className="list-disc space-y-1 pl-5">
<li>
The OpenPanel codebase is publicly available on GitHub,
allowing independent review of our data handling practices.
</li>
</ul>
</div>
</div>
</Section>
<Section number="8" title="International data transfers">
<p className="text-gray-700 text-sm leading-relaxed">
OpenPanel stores and processes all analytics data on Hetzner
infrastructure located in Germany. No Personal Data is transferred
to countries outside the EEA in the course of delivering the
service.
</p>
</Section>
<Section number="9" title="Data retention and deletion">
<ul className="list-disc space-y-1 pl-5 text-gray-700 text-sm">
<li>
<strong>Analytics events</strong> are retained for as long as the
Controller's account is active. No maximum retention period is
currently enforced. If a retention limit is introduced in the
future, all customers will be notified in advance.
</li>
<li>
<strong>Session replays</strong> are retained for 30 days and then
permanently deleted.
</li>
<li>
The Controller can delete individual projects, all associated data,
or their entire account at any time from within the dashboard. Upon
account termination, OpenPanel will delete the Controller's data
within 30 days unless required by law to retain it longer.
</li>
</ul>
</Section>
<Section number="10" title="Governing law">
<p className="text-gray-700 text-sm leading-relaxed">
This DPA is governed by the laws of Sweden and is interpreted in
accordance with the GDPR.
</p>
</Section>
{/* Exhibit A */}
<div className="mb-8 border-black border-t-2 pt-8">
<p className="mb-1 text-gray-500 text-xs uppercase tracking-widest">
Annex
</p>
<h2 className="mb-4 font-bold text-xl">
Exhibit A: Description of Processing
</h2>
<table className="w-full border-collapse text-sm">
<tbody>
<Row
label="Nature of processing"
value="Collection and storage of anonymized website analytics events (page views, custom events, session data). Optionally: session replay recording of DOM snapshots and user interactions."
/>
<Row
label="Purpose of processing"
value="To provide the Controller with website and product analytics via the OpenPanel Cloud dashboard. Session replay (if enabled) is used to allow the Controller to review user sessions for UX and debugging purposes."
/>
<Row
label="Duration of processing"
value="Analytics events: retained for the duration of the active account (no current maximum). Session replays: 30 days, then permanently deleted. All data deleted within 30 days of account termination."
/>
<Row
label="Categories of data subjects"
value="Visitors to the Controller's websites and applications"
/>
<Row
label="Categories of personal data"
value="Anonymized session identifiers (non-reversible after 24 hours), page URLs, referrers, browser type and version, operating system, device type, city-level geolocation (country, region, city). No IP addresses, no cookies, no names, no email addresses. If session replay is enabled: DOM snapshots and interaction recordings, which may incidentally contain personal data visible on the Controller's pages. All text content and form inputs are masked by default."
/>
<Row
label="Special categories of data"
value="None intended. The Controller is responsible for ensuring no special category data is captured via session replay."
/>
<Row
label="Sub-processors"
value="Hetzner Online GmbH (Germany) cloud infrastructure; Cloudflare R2 (EU) backup storage"
/>
</tbody>
</table>
</div>
{/* Signatures */}
<div className="border-black border-t-2 pt-8">
<p className="mb-1 text-gray-500 text-xs uppercase tracking-widest">
Execution
</p>
<h2 className="mb-6 font-bold text-xl">Signatures</h2>
<div className="grid grid-cols-2 gap-12">
{/* Processor - pre-signed */}
<div>
<div className="col h-32 gap-2">
<p className="font-semibold text-gray-500 text-xs uppercase tracking-widest">
Processor
</p>
<p className="font-semibold text-sm">OpenPanel AB</p>
<p className="text-gray-500 text-xs">
Sankt Eriksgatan 100, 113 31 Stockholm, Sweden
</p>
</div>
<SignatureLine
label="Signature"
value={
<Image
alt="Carl-Gerhard Lindesvärd signature"
className="relative top-4 h-16 w-auto object-contain object-left"
height={64}
src="/signature.png"
width={200}
/>
}
/>
<SignatureLine label="Name" value="Carl-Gerhard Lindesvärd" />
<SignatureLine label="Title" value="Founder" />
<SignatureLine label="Date" value="March 3, 2026" />
</div>
{/* Controller - blank */}
<div>
<div className="flex flex-col h-32 gap-2">
<p className="font-semibold text-gray-500 text-xs uppercase tracking-widest">
Controller
</p>
</div>
<SignatureLine label="Company" value="" />
<SignatureLine label="Signature" value="" />
<SignatureLine label="Name" value="" />
<SignatureLine label="Title" value="" />
<SignatureLine label="Date" value="" />
</div>
</div>
</div>
<div className="mt-12 border-gray-200 border-t pt-6 text-center text-gray-400 text-xs print:mt-4">
OpenPanel AB &middot; hello@openpanel.dev &middot; openpanel.dev/dpa
</div>
</div>
</div>
);
}
function Section({
number,
title,
children,
}: {
number: string;
title: string;
children: React.ReactNode;
}) {
return (
<div className="mb-8">
<h2 className="mb-3 font-bold text-base">
{number}. {title}
</h2>
{children}
</div>
);
}
function Row({ label, value }: { label: string; value: string }) {
return (
<tr className="border border-gray-300">
<td className="w-48 border border-gray-300 bg-gray-50 px-3 py-2 align-top font-semibold text-xs">
{label}
</td>
<td className="border border-gray-300 px-3 py-2 text-xs leading-relaxed">
{value}
</td>
</tr>
);
}
function SignatureLine({
label,
value,
}: {
label: string;
value: string | React.ReactNode;
}) {
return (
<div className="mb-3">
<p className="text-gray-500 text-xs">{label}</p>
<div className="mt-1 flex h-7 items-end border-gray-400 border-b font-mono">
{value}
</div>
</div>
);
}

View File

@@ -124,6 +124,7 @@ export async function Footer() {
<Link href="/sitemap.xml">Sitemap</Link>
<Link href="/privacy">Privacy Policy</Link>
<Link href="/terms">Terms of Service</Link>
<Link href="/dpa">DPA</Link>
<Link href="/cookies">Cookie Policy (just kidding)</Link>
</div>
</div>