Contribute
We're thrilled that you want to contribute to PrivacySpy. This guide will explain how to contribute policies, corrections, suggestions, and code changes.
Note that all contributions to PrivacySpy will take place in our GitHub repository. If you don't have a GitHub account already, you'll need to sign up for one to participate.
To see all of PrivacySpy's existing contributors, check out our contributors page.
Table of Contents
- Sharing suggestions and requests
- Submitting a new product
- Changing an existing product
- Product assessment guide
- Contributors file guide
Sharing suggestions and requests
If you have an idea for PrivacySpy, think you found an error, or just want to bring something up with the team, feel free to create an issue in our GitHub repository. Creating issues in the GitHub repository is the best way to share feedback and comments.
If your issue is a suggestion—such as a request to add a new product to our database or to fix an error—consider making the change yourself and submitting your modifications as a pull request (see changing an existing policy below to learn how). If you're not comfortable implementing the change yourself or don't know how, though, feel free to just create an issue.
Submitting a new product
Submitting a new product to PrivacySpy isn't too hard. The first step is to fork PrivacySpy so that you can submit changes as a pull request—if you're unsure what this means, you can learn about pull requests here.
Once you have a version of PrivacySpy on your own GitHub account, here are the general steps you need to take to add a new product:
Create a new file in the
products/
directory called<product slug>.toml
. (A slug is a short and unique ID.) For example, if you were adding DuckDuckGo, the name of the file would beduckduckgo.toml
. TOML is the file format we use for writing policies; if you're unfamiliar with it, you can learn more about TOML here.Add an icon for your new product to the
icons/
directory. The name of the icon file should correspond to the product slug from Step 1; for example, for DuckDuckGo, you'd want to name the icon fileduckduckgo.png
orduckduckgo.jpg
. Icon images should be square and smaller than 30kb. You may use our script that helps you add icons quickly; to use it, simply runnpm run icons
and manually check if the icon has been downloaded and is correct.Add yourself to
CONTRIBUTORS.toml
if you haven't already. Fill out as much or as little information as you want. For information about how this file works, refer to the contributors file guide below.Fill in all the necessary info in the
<product slug>.toml
file. Refer to the product assessment guide below to learn about how this file works.Make sure all tests pass. You can run tests using the
npm test
command. To ensure high-quality content, PrivacySpy has an automated system to check whether changes are appropriate. While it won't catch all issues, the automated testing system will let you know if you've made any obvious mistakes.Once all tests pass, submit a pull request! To add your changes back to PrivacySpy, submit a pull request. (Be sure to follow the instructions in the Pull Request message template.) Once you do, a member of the PrivacySpy team will look over your changes and either merge or request revisions. Don't worry if your changes aren't accepted on the first try—mistakes are inevitable. Just implement the requested changes, then resubmit the pull request!
That's it! Congratulations—you've contributed a policy to PrivacySpy!
Changing an existing product
To change an existing product on PrivacySpy—to submit a correction or an update—you'll need to submit a pull request. Fortunately, this process is quite simple: just edit the product file in the products/
directory! To edit Google's entry, for example, simply edit the file at products/google.toml
. Then, run the npm test
command and make sure all tests pass. Finally, submit your changes as a pull request. (Be sure to follow the instructions in the Pull Request message template.)
To learn about how the product TOML file works, review the product assessment guide below.
Product assessment guide
Each product on PrivacySpy is stored in the products/
directory as a TOML file. If you're unfamiliar with the TOML file format, you can learn about it here. In short, it's a flexible data serialization format like JSON or YAML that's designed to be written and understood by humans. You can check if your TOML file is valid using this online tool.
If you're ever confused about the file format for products, you can always look at another existing product file for reference (such as this one).
Product metadata
Metadata about the product—the name, description, and hostnames, for example—belongs at the top of the product file. For metadata, we use a simple key = "value"
format.
name
: this field holds the product's human-readable name as a string. Spaces and capitalization are allowed. For example, for DuckDuckGo, the value ofname
would beDuckDuckGo
.description
: this field contains the description of the product as a string. The description should be a complete sentence, and often mentions the owner and/or country of the product.slug
: this field contains the product's slug (its unique ID). The slug can contain only letters, numbers, and dashes. No two products can have the same slug, because the slug determines the URL where the policy will be hosted. (For example, a product with the slugduckduckgo
would be accessible at/product/duckduckgo
.) The slug should be the same as the file but without.toml
.hostnames
: this field contains an array of strings; each string should be a hostname (i.e., domain name) of the product. For example, the value ofhostnames
for 1Password is["1password.com"]
. (Don't worry about subdomains; you don't need to includemy.1password.com
if you include1password.com
.) Usually, this array has only one element, but there are some cases when a product has multiple hostnames (e.g., GitHub, which uses["github.com", "github.io"]
).sources
: this field contains an array of strings; each string should be the URL of a source used in grading the policy. (Almost always, the company's privacy policy itself would be included here as a source. Sometimes you'd want to include the company's security policy as well, if they have one.)contributors
: this field contains an array of strings; each string corresponds to the slug of each contributor (you!) in theCONTRIBUTORS.toml
file. See the contributors file guide below for more information. Usually, people use their GitHub username as their slug.
Example metadata TOML
name = "Twitter"
description = "Twitter is a microblogging social network and is popular among American public figures."
slug = "twitter"
hostnames = [ "twitter.com" ]
sources = [ "https://twitter.com/en/privacy" ]
contributors = [ "milesmcc" ]
Product grading (rubric)
The next section of the product file is the rubric. This is where we encode the score of the product across each of the rubric questions.
Each question is included in the file with the following structure:
[rubric.<question ID>]
value = "<answer ID>"
citations = [
# Direct quotes from the sources that support the value, if applicable. (Strings.)
]
notes = [
# Any special notes you want to include about the selection. (Strings.)
]
Each question has an ID (<question id>
, also known as the question's slug), and each possible value of that question also has an ID. For example, the question that assesses whether the product uses behavioral marketing has the id behavioral-marketing
, and the IDs of the answers are yes
, yes-opt-out
(yes, but you can opt-out), yes-opt-in
(yes, but you must opt-in), and no
.
Note that all questions must be graded, and each grade must have at least one citation or note (as shown above).
Questions & options
behavioral-marketing
— Does the policy allow personally-targeted or behavioral marketing?
Yes (0%)
Yes, but you may opt-out (35%)
Yes, but you must opt-in (70%)
No (100%)
Sample TOML section
[rubric.behavioral-marketing]
value = "yes" / "yes-opt-out" / "yes-opt-in" / "no"
citations = ["Citations, if applicable"]
notes = ["Any notes, if applicable"]
data-breaches
— Does the policy require users to be notified in case of a data breach?
Note that all companies operating in the EU are subject to Art. 33 of the GDPR, which requires companies to notify their data protection authority of a data breach within 72 hours of discovering it.
Not necessarily (0%)
Yes, eventually (70%)
Users will be notified in case of a data breach but within an unspecified amount of time.
Yes, within 72 hours (100%)
N/A (100%)
The service collects so little personal data that notification would not be possible.
Sample TOML section
[rubric.data-breaches]
value = "no" / "eventually" / "yes-72" / "na"
citations = ["Citations, if applicable"]
notes = ["Any notes, if applicable"]
data-collection-reasoning
— Is it clear why the service collects the personal data that it does?
No (0%)
Somewhat (30%)
Mostly (70%)
Yes (100%)
N/A (100%)
The service doesn't collect any personal information.
Sample TOML section
[rubric.data-collection-reasoning]
value = "no" / "somewhat" / "mostly" / "yes" / "na"
citations = ["Citations, if applicable"]
notes = ["Any notes, if applicable"]
data-deletion
— Does the service allow you to permanently delete your personal data?
Even if there is a reasonable delay before the data is fully deleted (as is common), the data still counts as "permanently deleted" and satisfies the parameters for this question.
No (0%)
Yes, by contacting someone (60%)
Yes, using an automated mechanism (100%)
N/A (100%)
The service doesn't collect any personal information.
Sample TOML section
[rubric.data-deletion]
value = "no" / "yes-contact" / "yes-automated" / "na"
citations = ["Citations, if applicable"]
notes = ["Any notes, if applicable"]
history
— Is the policy's history made available?
No (0%)
Only the date it was last modified (50%)
Yes, with revisions or a changelog (100%)
Sample TOML section
[rubric.history]
value = "no" / "last-modified" / "yes"
citations = ["Citations, if applicable"]
notes = ["Any notes, if applicable"]
law-enforcement
— When does the policy allow law enforcement access to personal data?
Always (0%)
This includes cases in which law enforcement either runs the service or has a known backdoor into (or relationship with) the service.
Not specified (0%)
When reasonably requested (60%)
Only when required by a court order or subpoena (80%)
N/A (no personal data to share) (100%)
The service would have no personal data to share with law enforcement.
Never (special legal jurisdiction) (100%)
The service operates in a jurisdiction in which sharing data with law enforcement is never required.
Sample TOML section
[rubric.law-enforcement]
value = "always" / "unspecified" / "reasonable" / "strict" / "na" / "never"
citations = ["Citations, if applicable"]
notes = ["Any notes, if applicable"]
list-collected
— Does the policy list the personal data it collects?
No (0%)
The policy does not claim to not collect personal data, but it also doesn't provide any meaningful insight into the types of personal data it collects.
Only summarily (30%)
The policy uses overly vague language to provide a summary of the types of collected personal data.
Yes, generally (70%)
All general categories of collected personal data are listed, though not all types of personal data are explicitly mentioned (for example, the list might use a phrase like 'such as' when listing types of personal data).
Yes, exhaustively (100%)
All types of collected personal data are listed specifically
N/A (no personal data is collected) (100%)
Sample TOML section
[rubric.list-collected]
value = "no" / "summarily" / "generally" / "exhaustively" / "na"
citations = ["Citations, if applicable"]
notes = ["Any notes, if applicable"]
noncritical-purposes
— Does the service allow the user to control whether personal data is collected or used for non-critical purposes?
Some services allow users to opt-out or opt-in to of non-critical collection or use of personal data, such as collecting data for personalized advertisements.
No (0%)
On an opt-out basis, but only for some non-critical data/uses (30%)
On an opt-out basis, for all non-critical data/uses (60%)
On an opt-in basis (60%)
N/A (no data used for non-critical purposes) (100%)
Sample TOML section
[rubric.noncritical-purposes]
value = "no" / "opt-out-some" / "opt-out-all" / "opt-in" / "na"
citations = ["Citations, if applicable"]
notes = ["Any notes, if applicable"]
revision-notify
— Will affected users be notified when the policy is meaningfully changed?
No (0%)
Yes (100%)
N/A (100%)
The policy doesn't collect any personal data, so notification would be impossible.
Sample TOML section
[rubric.revision-notify]
value = "no" / "yes" / "na"
citations = ["Citations, if applicable"]
notes = ["Any notes, if applicable"]
security
— Does the policy outline the service's general security practices?
No (0%)
Somewhat (30%)
The policy provides only a very vague overview of its security practices.
Yes (60%)
Yes, including audits (80%)
"Reviews," "monitoring," etc. also count as audits.
Yes, including independent audits (100%)
Independent "reviews," "monitoring," etc. also count as independent audits.
N/A (100%)
The service doesn't collect any personal information.
Sample TOML section
[rubric.security]
value = "no" / "somewhat" / "yes" / "yes-audits" / "yes-independent-audits" / "na"
citations = ["Citations, if applicable"]
notes = ["Any notes, if applicable"]
third-party-access
— Does the service allow third-party access to private personal data?
This may come in the form of outright data sharing or by using local third-party analytics software (such as Google Analytics, which collects a plethora of user information).
Note that whether the policy allows sharing aggregated user data does not affect this question.
If the personal data is encrypted when it passes through the third-party, it does not count as third-party access (as the data is inaccessible to that party).
If personal data has been made public by, for example, posting it to a blog, it does not count as private personal information (and is therefore not considered by this question).
Yes (0%)
The policy allows sharing personal data with third parties (not just critical service providers), and does not explicitly list the third parties.
Yes, all parties specified (including non-critical service providers such as advertisers) (30%)
Yes, not all parties specified (but only to critical service providers) (70%)
Yes, all parties specified (only to critical service providers) (80%)
No (100%)
Sample TOML section
[rubric.third-party-access]
value = "yes-unspecified" / "yes-specified-noncritical" / "yes-unspecified-critical" / "yes-specified-critical" / "no"
citations = ["Citations, if applicable"]
notes = ["Any notes, if applicable"]
third-party-collection
— Does the service collect personal data from third parties?
This includes the use of data brokers and independent verification authorities (such as background check providers).
Yes (0%)
Yes, but for critical data only (70%)
For example, a blog providing user avatars or a bank conducting identity verification would count.
No (100%)
Sample TOML section
[rubric.third-party-collection]
value = "yes" / "critical-only" / "no"
citations = ["Citations, if applicable"]
notes = ["Any notes, if applicable"]
Updates
Whenever a product has a major privacy-related event (such as a data breach, an overhaul of their privacy policy, or anything else of this nature), we try to include it as an update on PrivacySpy.
Each product has an array of update objects. An update object (inside the updates
array) looks like this:
[[updates]]
title = "Data Breach"
description = "More than 540 million records about Facebook users were publicly exposed on Amazon's cloud computing service, according to a cybersecurity research firm."
date = 2019-08-28
sources = [ "https://www.cbsnews.com/news/millions-facebook-user-records-exposed-amazon-cloud-server/" ]
As you can probably gather, title
is a string that represents the title of the update; description
is a string that explains what happened (in full sentences); date
is the date of the update; and sources
is an array of URLs that provide information about the update.
Note that to insert the update into the updates
array, we put [[update]]
on top of the object, as per the TOML spec.
Contributors file guide
Contributors like you deserve to be recognized for your additions to PrivacySpy. That's why we maintain the CONTRIBUTORS.toml
file (in the root of the repository) where each contributor is listed with some minimal biographical information.
You aren't required to add any biographical information to the CONTRIBUTORS.toml
file if you don't want to.
Here's a template for what to put in the file:
[your_slug] # usually the same as your GitHub username
name = "Your Name" # optional
website = "http://example.com" # optional
github = "example" # optional
email = "example@example.com" # optional
The only required element is [your_slug]
. You can think of your_slug
as your PrivacySpy "username"—it's what you'd add to the contributors
array in policies you contribute to.