Privacy policy
This is the privacy policy for decisiontrackr.com/privacy. It describes the Decision Trackr Figma and FigJam plugin, the licensing API, and the hosted data API in this repository. It is written from the code. It is not a legal opinion.
Contact: licences@decisiontrackr.com
The plugin id is 1432332696794120370. The manifest name is Decision Trackr.
Who we are
Decision Trackr lets a person log a design decision against a layer in a Figma or FigJam file and keep a Decision History page in that file. Pro is a per-seat subscription. Stripe (via Link, Stripe Managed Payments) is the merchant of record for Pro purchases and handles payment, tax and receipts. The licensing API and the data API run in AWS, region us-east-1.
Data that stays in the Figma file
Logging a decision stores it in the file as plugin data on the Decision History page (plugin id 1432332696794120370). Each record can contain:
- the layer's Figma node id and the layer path
- the title, details, why, alternatives, success metric, status, supporting link, and decision-maker names the user typed
- the date and time
- a version number and earlier versions of that record
The plugin also draws a page named Decision History. That page contains the same titles, details, maker names, dates, and layer names as ordinary text. Anyone who can open the file can read that page. They do not need a Decision Trackr account or a paid seat. Other plugins cannot read the plugin-data key, but Figma's own docs say plugin data is not a security boundary.
The free plan stores those decisions in the file. It does not create a Decision Trackr account, and it does not upload the decisions to AWS.
Data on the device
The plugin uses figma.clientStorage, which Figma documents as storage on the user's machine for this plugin id. It is not in the file and it is not synced to other people. This build uses:
| Key | Contents |
|---|---|
dt_licence_v1 | The licence key and the signed seat token, after a successful activation. |
dt_activation_decision_count | How many decisions this install has logged. A number. |
ga_anonymous_client_id | A random 32-character hex id, only if Figma did not provide figma.currentUser.id. |
ga_event_queue | Analytics events that failed to send. At most 20 events, kept for at most 7 days. |
ga_event_queue_schema | The number 1. |
dt_upsell_dismiss_v1 | Which upgrade prompt was dismissed, the decision count when the Free limit prompt was dismissed, and the hidden-decision count when the history prompt was dismissed. No decision text. |
An older build wrote dt_jwks_v1. This build does not read that cache when it decides whether Pro is on, and it does not write it. Pro is on only when a seat token verifies against the Ed25519 public key compiled into the plugin.
Clearing the browser cache can delete client storage. Figma documents that.
Data stored on AWS in us-east-1
Synced decisions (data API)
A Pro seat whose token has just been checked with the licensing server can upload decisions to the data API. The free plan does not call that API. Each synced decision stores:
- the Figma file key
- a decision id
- title, details, date (
DD/MM/YYYY), time (HH:mm), version, maker names, layer path, and earlier versions of those fields - a status (
logged,proposed,accepted, orsuperseded) - created and updated times
The upload leaves out why, alternatives, success metric, supporting link, and replaces. The rows are stored for the team, not under one Figma user. The API also keeps a change log, dedupe rows, a cursor, and team API key hashes (the full key is shown once at creation). Rate-limit counters expire after about two minutes.
Licence and seat data (licensing API)
Checkout and the subscription webhooks store, for a team:
- the buyer's email address
- Stripe customer id and subscription id
- subscription status, billing interval (month or year), and seat count
- the licence key as a SHA-256 hash, plus the last four characters
- for each activated seat: the Figma user id, an optional Figma display name, and whether the seat is active or revoked
A magic-link sign-in stores a hash of the link, the admin email, and the team id. The link works once and expires after 15 minutes. Webhook event ids are kept for 90 days so a duplicate delivery can be ignored. A short-lived encrypted copy of a new licence key exists only until Amazon SES accepts the message, then it is removed.
Seat tokens last 24 hours. Admin session tokens last 12 hours. They are signed with an Ed25519 key that stays in AWS Secrets Manager. The plugin and the data API hold only the public key.
Licence keys, rotated keys, and seat-admin sign-in links are sent with Amazon SES. The From address configured for this service is licences@decisiontrackr.com. The message contains the licence key or the sign-in link, and it is addressed to the email on the subscription.
Payments
Stripe (via Link, Stripe Managed Payments) is the merchant of record for Pro purchases. Stripe handles payment, tax and receipts. Checkout collects the email address, the billing address, and the payment method. Prices are per seat: EUR 9 a month or EUR 90 a year, from 1 seat to 999 seats. Checkout metadata on the Stripe session and the subscription can include the seat count, the interval, the landing page's starting seat count (seats_initial), and these campaign fields when the pricing page sends them: utm_source, utm_medium, utm_campaign, utm_content, utm_term. Each campaign field is limited to 100 characters. Card numbers are handled by Stripe. This repository does not store them.
Stripe's own privacy policy covers what Stripe keeps: https://stripe.com/privacy.
Analytics
Production builds can send events to Google Analytics 4 Measurement Protocol at https://www.google-analytics.com/mp/collect. The measurement id compiled by default is G-D2DV9DRM33. The API secret is injected at build time so Google will accept the event. It is not user data.
The plugin reads figma.currentUser.id. It does not read the user's photo or email for analytics. client_id and user_id on the request are the same SHA-256 hex digest of:
decision-tracker:1432332696794120370: + the Figma user id
If there is no user id, the random id from ga_anonymous_client_id is hashed the same way. The salt is a fixed string in source. Anyone who already knows a Figma user id can recompute the digest. The value is a stable pseudonymous id, not the raw Figma user id.
The plugin shows a one-time notice before it sends analytics. The notice says that events have no titles, details, or names, and that they use a hashed id. Nothing is sent, including events already queued, until that notice has been shown. Settings has an opt-out. While that opt-out is on, nothing is sent, including queued events. The hashed id is kept. A development build does not send analytics. A production build sends only when it was built with a non-empty GA_API_SECRET_LIVE, the notice has been shown, and the opt-out is off. Omitting that secret turns sending off.
Events and parameters this build can send:
| Event | Parameters |
|---|---|
figma_plugin_opened | editorType |
figma_plugin_closed | editorType |
ui_decision_logged | version, titleLength, detailsLength, makersCount, editorType |
ui_decision_selected | editorType |
first_decision_logged | count |
decision_logged | count |
export_used | count |
report_exported | format (markdown or html), count |
upsell_view | trigger (decision_cap or history_window) |
upsell_click | trigger (decision_cap or history_window) |
titleLength and detailsLength are string lengths, not the text. makersCount and count are numbers. editorType is figma. The plugin runs in Figma Design only. format is the word markdown or the word html. count on report_exported is how many decisions were in that file. trigger is decision_cap or history_window. It names which limit the prompt was about. It is not decision text. Every event also includes plan, which is free or pro from the licence state on this install. It is not a licence key, a seat token, or an email. An event that carries a title, details, a name, a page name, a node id, a path, or an email is dropped and is not queued.
The plugin does not put an IP address in the event body. The request is HTTPS, so Google receives the connection. How long the GA4 property keeps events is Google's setting. It is not set in this repository. Google's policy is at https://policies.google.com/privacy.
How long data is kept
Decisions in the Figma file stay until someone deletes them in the plugin, replaces the plugin data, or deletes the file. The Decision History page is updated in place. Deleting a decision in the plugin removes it from the file. It does not, by itself, remove a copy already synced to AWS.
Synced decisions, the change log, API keys, team records, licence hashes, and seat rows stay until they are deleted as described below. Cancelling Pro in the billing portal is set to take effect at the end of the paid period. When Stripe then deletes the subscription, the team status becomes inactive and the plugin stops issuing Pro for that licence. The stored rows are not deleted by cancellation alone. Offline, a previously verified seat can remain Pro for up to 7 days after the seat token expires if the plugin cannot reach the licensing server.
Magic links expire after 15 minutes. Webhook event records expire after 90 days. Rate-limit counters expire after about 2 minutes. Lambda logs in CloudWatch are kept for 14 days.
How to delete it
Synced decisions for your team. Send DELETE /v1/sync to the data API with the seat token the plugin uses (Authorization: Bearer and the seat token). That deletes the team's synced decisions, change log, dedupe rows, and cursor. It leaves API keys. The call can be repeated. A team that is already empty returns { "deleted": 0 }.
All of a team's hosted data, including API keys. A team admin sends DELETE /v1/team with the admin session token. That deletes the synced rows and the team's API keys. It does not delete another team's data.
Licence, seat, and billing records, and anything the routes above do not cover. Email licences@decisiontrackr.com. Ask for the team, the licence, and the seat rows to be deleted. Stripe billing data has to be deleted in Stripe as well, or through that same address and we will take it to Stripe.
The file. Delete the decisions in the plugin, or delete the file. Removing the plugin does not, by itself, delete plugin data already written there.
Analytics on the device. Clearing Figma's client storage removes the hashed-id source and any queued events that have not been sent. Events already accepted by Google have to be raised with us and, where it applies, with Google.
Hosted history is not free to read
Reading the Decision History page inside a file does not require a seat. The hosted data API does not offer that page to an anonymous or free viewer. Listing or searching synced decisions requires a team API key. The MCP server on POST /mcp uses the same key. A seat token can upload and can delete the team's sync. It cannot list another team's decisions.
Children
The plugin is not directed at children. A user can type any name into Decision makers. That string is stored in the file and, on a Pro sync, in AWS as part of the decision.
What we do not do
Decision Trackr does not sell personal data. The domains a production plugin build is allowed to call are Google Analytics, the licensing API, and the data API. The pricing page is an ordinary link.