+ );
+}
+
function LicenseCard() {
const isPro = useEntitlementStore((state) => state.isPro);
const expiresAt = useEntitlementStore((state) => state.expiresAt);
@@ -84,17 +128,20 @@ function LicenseCard() {
<> Your entitlement auto-renews by {new Date(expiresAt).toLocaleDateString()}.>
)}
- {aiStatus.mode === "byok" ? (
-
- AI: using your Anthropic key — not metered.
-
- ) : (
- quotaLimit > 0 && (
+
+ {aiStatus.mode === "byok" ? (
- AI quota this month: {aiQuotaRemaining} of {quotaLimit} remaining.
+ AI: using your Anthropic key — not metered.
- )
- )}
+ ) : (
+ quotaLimit > 0 && (
+
+ AI quota this month: {aiQuotaRemaining} of {quotaLimit} remaining.
+
+ )
+ )}
+
+
{billingPortalError && (
{billingPortalError}
@@ -126,11 +173,14 @@ function LicenseCard() {
Enter your Optia Pro license key to unlock AI without an Anthropic key and advanced
analysis.
+ Free AI quota this month: {freeAiRemaining} of {freeAiLimit} remaining.
+
+ )}
+
+
diff --git a/app/src/sidepanel/App.test.tsx b/app/src/sidepanel/App.test.tsx
new file mode 100644
index 0000000..9ee6225
--- /dev/null
+++ b/app/src/sidepanel/App.test.tsx
@@ -0,0 +1,117 @@
+import { render, screen, waitFor } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
+import { describe, it, expect, vi, beforeEach } from "vitest";
+import App from "./App";
+import { useStore } from "@/lib/store";
+import { fetchAndAnalyzePage } from "@/lib/fetch-page";
+import { recordAnalysis, reportUsageIfDue } from "@/lib/usage";
+import type { PageSEOData } from "@/types/seo";
+
+// The harness path (no chrome.tabs in jsdom) fetches the page by URL; stub the
+// fetch and the usage layer so this suite only sees how App drives them.
+vi.mock("@/lib/fetch-page", () => ({ fetchAndAnalyzePage: vi.fn() }));
+vi.mock("@/lib/usage", () => ({
+ recordAnalysis: vi.fn(),
+ reportUsageIfDue: vi.fn(),
+}));
+vi.mock("canvas-confetti", () => ({ default: vi.fn() }));
+
+const fetchAndAnalyzePageMock = vi.mocked(fetchAndAnalyzePage);
+const recordAnalysisMock = vi.mocked(recordAnalysis);
+const reportUsageIfDueMock = vi.mocked(reportUsageIfDue);
+
+const pageData: PageSEOData = {
+ url: "https://example.com/",
+ title: "Example Domain",
+ metaDescription: "An example page",
+ metaKeywords: "",
+ canonical: "https://example.com/",
+ h1: ["Example Domain"],
+ h2: [],
+ h3: [],
+ h4: [],
+ h5: [],
+ h6: [],
+ images: [],
+ ogTags: {},
+ twitterTags: {},
+ wordCount: 120,
+ internalLinks: 1,
+ externalLinks: 1,
+ lang: "en",
+ paragraphs: ["This domain is for use in examples."],
+ resources: { js: [], css: [] },
+ schemaMarkup: { types: [], count: 0 },
+ ogImage: "",
+ imageFileSizes: [],
+ fetchWarnings: [],
+};
+
+async function analyze(user: ReturnType) {
+ await user.click(screen.getByRole("button", { name: /optimize my seo/i }));
+}
+
+beforeEach(async () => {
+ // Past onboarding, on the setup screen with a URL and keyword filled in.
+ await chrome.storage.local.set({ onboarding_dismissed: true });
+ useStore.setState({
+ view: "setup",
+ analysis: null,
+ activeCategory: null,
+ error: null,
+ settings: {
+ keyword: "example",
+ secondaryKeywords: "",
+ pageType: "homepage",
+ language: "en",
+ advancedMode: false,
+ targetUrl: "https://example.com/",
+ },
+ });
+ fetchAndAnalyzePageMock.mockResolvedValue(pageData);
+ recordAnalysisMock.mockResolvedValue(undefined);
+ reportUsageIfDueMock.mockResolvedValue(undefined);
+});
+
+describe("App analysis usage counting", () => {
+ it("counts each completed analysis exactly once, then checks for a due report", async () => {
+ const user = userEvent.setup();
+ render();
+
+ await analyze(user);
+ await screen.findByRole("button", { name: /new analysis/i });
+
+ expect(recordAnalysisMock).toHaveBeenCalledTimes(1);
+ await waitFor(() => expect(reportUsageIfDueMock).toHaveBeenCalledTimes(1));
+
+ await user.click(screen.getByRole("button", { name: /new analysis/i }));
+ await analyze(user);
+ await screen.findByRole("button", { name: /new analysis/i });
+
+ expect(recordAnalysisMock).toHaveBeenCalledTimes(2);
+ await waitFor(() => expect(reportUsageIfDueMock).toHaveBeenCalledTimes(2));
+ });
+
+ it("does not count an analysis that failed", async () => {
+ const user = userEvent.setup();
+ fetchAndAnalyzePageMock.mockRejectedValue(new Error("Could not fetch the page"));
+ render();
+
+ await analyze(user);
+
+ expect(await screen.findByText(/could not fetch the page/i)).toBeInTheDocument();
+ expect(recordAnalysisMock).not.toHaveBeenCalled();
+ expect(reportUsageIfDueMock).not.toHaveBeenCalled();
+ });
+
+ it("still shows the results when the local count cannot be saved", async () => {
+ const user = userEvent.setup();
+ recordAnalysisMock.mockRejectedValue(new Error("storage unavailable"));
+ render();
+
+ await analyze(user);
+
+ expect(await screen.findByRole("button", { name: /new analysis/i })).toBeInTheDocument();
+ expect(reportUsageIfDueMock).not.toHaveBeenCalled();
+ });
+});
diff --git a/app/src/sidepanel/App.tsx b/app/src/sidepanel/App.tsx
index 74c740b..c93531c 100644
--- a/app/src/sidepanel/App.tsx
+++ b/app/src/sidepanel/App.tsx
@@ -7,6 +7,7 @@ import { fetchAndAnalyzePage } from "@/lib/fetch-page";
import { detectLanguage } from "@/lib/languages";
import { generateRecommendation, generateAllH2Suggestions } from "@/lib/ai";
import { aiStatusNow } from "@/lib/entitlement-store";
+import { recordAnalysis, reportUsageIfDue } from "@/lib/usage";
import {
saveKeywordForUrl,
getKeywordForUrl,
@@ -381,6 +382,14 @@ export default function App() {
setAnalysis(analysis);
+ // Count the completed analysis, then send the once-a-day anonymous usage
+ // report if one is due (#80). Fire-and-forget: it never delays results.
+ void recordAnalysis()
+ .then(() => reportUsageIfDue())
+ .catch(() => {
+ // Usage counting is non-critical
+ });
+
// Auto-generate AI recommendations in the background (non-blocking) only
// for unmetered/high-cap paths. Free users generate on demand per
// recommendation so a single analysis doesn't drain their monthly allowance.
diff --git a/docs/architecture.md b/docs/architecture.md
index f8a9ac3..66af59b 100644
--- a/docs/architecture.md
+++ b/docs/architecture.md
@@ -19,6 +19,7 @@ Optia is **open-core**. The split is by trust, not by convenience:
| Licensing | The **client** half: entitlement verification, caching, refresh, the paywall/account UI, checkout *initiation* | The **authority** half: license minting, Ed25519 **signing** (private key), seat activation, revocation |
| Billing | Opens Checkout/portal URLs the backend returns | Stripe integration: Checkout session creation (price allowlist), Billing Portal, webhook ingestion — webhooks are the source of truth for license state |
| AI | The routing facade (`app/src/lib/ai.ts`) and the BYO-key direct path | The hosted AI proxy `/ai/generate`: server-funded Anthropic key, per-subject metering (D1), rate limiting (KV), per-check prompts |
+| Usage counts | Counts page analyses per month locally and reports the running total at most once a day (`app/src/lib/usage.ts`) | `POST /usage/analysis`: keeps the highest count per install and month (D1) |
| Secrets | **None.** Public verification keys only | Anthropic API key, Stripe secret + webhook secret, the entitlement signing JWK |
The extension's full gating logic is public on purpose. Hiding it would add
@@ -38,6 +39,7 @@ flowchart LR
LIC["/license activate · refresh · deactivate Ed25519 entitlement signing"]
BILL["/billing checkout · portal · webhook"]
AIP["/ai/generate metered proxy"]
+ USG["/usage/analysis monthly analysis counts"]
D1[("D1 licenses · usage")]
KV[("KV rate limits")]
end
@@ -52,10 +54,12 @@ flowchart LR
EXT -- "BYO key (Pro): direct, never transits the backend" --> ANTH
EXT --> LIC
EXT -- "start checkout / portal" --> BILL
+ EXT -- "at most daily: install id, month, count" --> USG
BILL <--> STRIPE
STRIPE -- "webhooks (license truth)" --> BILL
LIC --- D1
AIP --- D1
+ USG --- D1
AIP --- KV
STRIPE -- "redirects after pay/cancel" --> PAGES
```
@@ -63,6 +67,12 @@ flowchart LR
Notes the diagram can't carry:
- **SEO analysis is fully local.** Scoring never sends the page anywhere.
+- **The only usage signal is a count.** At most once a day, right after an
+ analysis, the side panel sends `{ installId, period, count }` (the month's
+ running total of pages analyzed) to `POST /usage/analysis`. The backend keeps
+ the highest count per install and month, so a re-sent total changes nothing.
+ "Share anonymous usage counts" in Options stops the reports; the local count
+ continues. Nothing enforces a limit on analyses (#80, optia-backend#30).
- **BYO-key requests never touch the backend** — the proxy deliberately ignores
any `Authorization` header, so user keys cannot transit our infrastructure
even by accident.
diff --git a/docs/chrome-web-store-data-disclosure.md b/docs/chrome-web-store-data-disclosure.md
index cf24983..537577a 100644
--- a/docs/chrome-web-store-data-disclosure.md
+++ b/docs/chrome-web-store-data-disclosure.md
@@ -12,14 +12,14 @@ For each category the dashboard asks about, declare:
| Dashboard category | Collected? | Detail |
|---|---|---|
-| Personally identifiable information | **No** | No name, address, email, or ID is collected by the extension. (Stripe collects billing details during Pro checkout on Stripe-hosted pages — outside the extension.) |
+| Personally identifiable information | **No** | No name, address, email, or identification number is collected by the extension; the random install ID is not linked to identity. (Stripe collects billing details during Pro checkout on Stripe-hosted pages — outside the extension.) |
| Health information | No | — |
| Financial and payment information | **No** | Payment is handled entirely by Stripe's hosted checkout/portal; the extension never sees card data. |
| Authentication information | **Yes** | A Pro license key and a signed entitlement token are sent to our backend to activate/refresh the license. A user's optional Anthropic API key is stored locally only and sent only to Anthropic — never to us. |
| Personal communications | No | — |
| Location | No | No location data; standard IP handling by our CDN/backend is not used for geolocation features. |
| Web history | **No** | The extension does not record browsing history. It reads a page's content only when the user runs an analysis on that page. |
-| User activity | **No** | No analytics, telemetry, clickstream, or usage tracking. The only counters are anonymous quota counts (install ID / license) needed to meter the AI allowance. |
+| User activity | **Yes** | One anonymous usage count: the number of pages the user analyzed this month, sent at most once a day after an analysis with the random install ID and the month, and nothing else (no URLs, page content, keywords or scores). On by default; the user turns it off in Options ("Share anonymous usage counts"). No clickstream, keystroke, mouse or scroll data, and no analytics SDK. The AI allowance is also metered by anonymous counts (install ID / license). |
| Website content | **Yes** | When the user requests an AI recommendation, the target keyword and the relevant page snippets (title/heading/alt-text context) are sent to our AI service — or directly to Anthropic in bring-your-own-key mode — solely to generate the suggestion. |
## Certifications (check all three)
@@ -30,13 +30,13 @@ For each category the dashboard asks about, declare:
## Limited Use
-Optia's use of website content complies with the Limited Use policy: data sent to the AI service is used only to provide the user-requested feature (generating the SEO suggestion), is not used for advertising, and is not sold.
+Optia's use of website content complies with the Limited Use policy: data sent to the AI service is used only to provide the user-requested feature (generating the SEO suggestion), is not used for advertising, and is not sold. The anonymous usage count is used only to see how much the extension is used and to set the free tier's limits; it is not used for advertising and is not sold.
## Remote code
Declare **No remote code**. All executable code ships in the package. Network calls fetch data (JSON) only:
-- `https://api.optia-api.com` — AI proxy, license activation/refresh, billing portal session (production)
+- `https://api.optia-api.com` — AI proxy, license activation/refresh, billing portal session, and the once-a-day anonymous usage count (production)
- `https://api.anthropic.com` — direct AI calls in Pro bring-your-own-key mode only
- `https://checkout.stripe.com` / billing portal — opened as pages, not fetched into the extension
diff --git a/docs/chrome-web-store-listing.md b/docs/chrome-web-store-listing.md
index f2af59b..bfa0329 100644
--- a/docs/chrome-web-store-listing.md
+++ b/docs/chrome-web-store-listing.md
@@ -62,7 +62,7 @@ Note: Optia Pro is purchased from us and billed securely through Stripe — not
**PRIVACY FIRST**
-All SEO analysis happens locally in your browser. When you request an AI recommendation, only the relevant page snippets (like the current title and your keyword) are sent to our AI service to generate the suggestion — nothing else, and never in the background. No accounts required for the free tier. No tracking, no ads, no analytics, and your data is never sold. Pro users who bring their own Anthropic key talk to Anthropic directly; the key never leaves the browser.
+All SEO analysis happens locally in your browser. When you request an AI recommendation, only the relevant page snippets (like the current title and your keyword) are sent to our AI service to generate the suggestion — nothing else, and never in the background. At most once a day, Optia also sends one anonymous number: how many pages you analyzed this month, with a random install ID. No URLs, page content or scores, and you can turn it off in Options. No accounts required for the free tier. No tracking, no ads, no analytics services, and your data is never sold. Pro users who bring their own Anthropic key talk to Anthropic directly; the key never leaves the browser.
Full privacy policy: https://pmdevsolutions.github.io/Optia/privacy.html
diff --git a/docs/privacy-policy.md b/docs/privacy-policy.md
index 4a34b49..c6e3614 100644
--- a/docs/privacy-policy.md
+++ b/docs/privacy-policy.md
@@ -1,7 +1,7 @@
# Optia Privacy Policy
**Effective date:** 2026-08-20
-**Last updated:** 2026-08-20
+**Last updated:** 2026-10-24
> Published at **https://pmdevsolutions.github.io/Optia/privacy.html** (rendered from `site/privacy.html` — keep the two in sync; the HTML version is the user-facing one). Grounded in the extension's actual data flows (see `docs/free-vs-pro-gating.md` and the backend design records). **A qualified lawyer's review is still recommended** — tracked in `docs/launch-checklist.md` Phase 0.
@@ -11,14 +11,15 @@ Optia ("we", "our") is a Chrome extension that analyzes web pages for SEO issues
- SEO analysis runs **locally in your browser**. Pages you visit are not sent anywhere just by browsing.
- When you explicitly request an AI recommendation, the relevant page snippets are sent to our AI service (or directly to Anthropic if you use your own API key) to generate the suggestion.
-- We require **no account** for the free tier, and we use **no analytics, no ads, and no trackers**. We never sell your data.
+- At most once a day, Optia sends us one **anonymous usage count**: a random install ID, the month, and how many pages you analyzed that month. No URLs, page content, keywords or scores. You can turn it off in Optia's options.
+- We require **no account** for the free tier, and we use **no analytics services, no ads, and no trackers**. We never sell your data.
- Your own Anthropic API key (Pro option) is stored only in your browser and **never sent to our servers** — this is enforced server-side: our backend does not accept caller API keys.
## Data we handle, and where it goes
### 1. Page content you analyze (stays local by default)
-When you run an analysis, Optia's content script reads the current page's SEO-relevant elements (title, meta tags, headings, image alt attributes, link structure, body text) **inside your browser** and computes the score locally. This data is not transmitted.
+When you run an analysis, Optia's content script reads the current page's SEO-relevant elements (title, meta tags, headings, image alt attributes, link structure, body text) **inside your browser** and computes the score locally. This data is not transmitted. Running an analysis adds one to the monthly count described in section 4; nothing about the page itself goes with it.
### 2. AI recommendation requests (sent only when you click)
@@ -27,19 +28,23 @@ When you request an AI suggestion, Optia sends the minimum needed to generate it
- **Hosted mode (default, free and Pro):** sent to our backend (`api.optia-api.com`, Cloudflare Workers), which forwards it to Anthropic's Claude API to generate the suggestion. Our backend meters usage counts; it does not build profiles from request content. Anthropic processes the snippets as our AI provider ([Anthropic's privacy policy](https://www.anthropic.com/legal/privacy)).
- **Bring-your-own-key mode (Pro):** sent directly from your browser to Anthropic using your key. Our servers are not involved at all.
-### 3. Install identifier (free-tier metering)
+### 3. Install identifier
-Free-tier AI requests include a random install ID generated by your extension. It exists solely to meter the free monthly allowance, is not linked to your identity, and resets if you reinstall.
+Your extension generates a random install ID. It is sent with hosted AI requests, where it meters the monthly allowance; with Pro checkout and license activation, where it ties a license seat to this browser; and with the usage count in section 4. It is not linked to your identity and resets if you reinstall.
-### 4. License and billing data (Pro only)
+### 4. Anonymous usage count (on unless you turn it off)
+
+Optia counts the pages you analyze each month, on your device. At most once a day, after you run an analysis, it sends that count to our backend (`api.optia-api.com`). The report contains only three things: your install ID, the month (for example `2026-11`), and how many pages you have analyzed that month. It never contains URLs, page content, keywords or scores. This applies on every plan. We use the counts to see how much Optia is used, so the free tier's limits are set from real numbers. To stop the reports, turn off **Share anonymous usage counts** in Optia's options. Optia keeps counting on your device, so the options page can still show you the number, but sends nothing.
+
+### 5. License and billing data (Pro only)
If you purchase Optia Pro, checkout and payment are handled by **Stripe** — we never see your card details ([Stripe's privacy policy](https://stripe.com/privacy)). Our backend stores what's needed to operate your license: your license key, subscription status, and billing-portal linkage. Activating Pro stores a signed entitlement token in your browser, refreshed periodically.
-### 5. Your Anthropic API key (Pro, optional)
+### 6. Your Anthropic API key (Pro, optional)
Stored only in Chrome's local extension storage on your device. Used exclusively for direct browser→Anthropic requests. Never transmitted to our backend, logged by us, or synced.
-### 6. Settings and history (local)
+### 7. Settings and history (local)
Your keyword history, per-site options, language preference, and toggles are stored in Chrome's local extension storage on your device. Nothing is synced to us.
@@ -53,7 +58,7 @@ Your keyword history, per-site options, language preference, and toggles are sto
## Data retention
- Local data (settings, keys, entitlement tokens): retained until you clear it or uninstall the extension.
-- Backend metering counters (install ID / license usage): retained per monthly quota period for billing/abuse-prevention purposes.
+- Backend usage counters (AI requests per install ID or license, and pages analyzed per install ID): kept as one total per month, for billing, abuse prevention and setting the free tier's limits.
- Backend request logs: operational logs are short-lived and used for reliability and abuse prevention, not profiling.
## Your rights
diff --git a/site/index.html b/site/index.html
index 447e7bd..62f3f8c 100644
--- a/site/index.html
+++ b/site/index.html
@@ -93,7 +93,7 @@
Optia Pro$50/yr = 2 months free
Privacy first
-
All SEO analysis runs locally in your browser. When you request an AI suggestion, only the relevant page snippets are sent to generate it — nothing else, never in the background. No analytics, no tracking, no ads, and your data is never sold. Pro users who bring their own Anthropic key talk to Anthropic directly; the key never touches our servers.
+
All SEO analysis runs locally in your browser. When you request an AI suggestion, only the relevant page snippets are sent to generate it — nothing else, never in the background. At most once a day, Optia also sends one anonymous number: how many pages you analyzed this month, with a random install ID. No URLs, page content or scores, and you can turn it off in Options. No analytics services, no tracking, no ads, and your data is never sold. Pro users who bring their own Anthropic key talk to Anthropic directly; the key never touches our servers.
diff --git a/site/privacy.html b/site/privacy.html
index c562497..e0b73aa 100644
--- a/site/privacy.html
+++ b/site/privacy.html
@@ -27,7 +27,7 @@
← Optia home
Optia Privacy Policy
-
Effective date: August 20, 2026 · Last updated: August 20, 2026
+
Effective date: August 20, 2026 · Last updated: October 24, 2026
Optia ("we", "our") is a Chrome extension operated by Paul Mulligan Development Solutions (PMDS) that analyzes web pages for SEO issues and generates AI-powered recommendations. This policy explains what data Optia handles, where it goes, and the choices you have.
@@ -35,14 +35,15 @@
The short version
SEO analysis runs locally in your browser. Pages you visit are not sent anywhere just by browsing.
When you explicitly request an AI recommendation, the relevant page snippets are sent to our AI service (or directly to Anthropic if you use your own API key) to generate the suggestion.
-
We require no account for the free tier, and we use no analytics, no ads, and no trackers. We never sell your data.
+
At most once a day, Optia sends us one anonymous usage count: a random install ID, the month, and how many pages you analyzed that month. No URLs, page content, keywords or scores. You can turn it off in Optia's options.
+
We require no account for the free tier, and we use no analytics services, no ads, and no trackers. We never sell your data.
Your own Anthropic API key (Pro option) is stored only in your browser and never sent to our servers — enforced server-side: our backend does not accept caller API keys.
Data we handle, and where it goes
1. Page content you analyze (stays local by default)
-
When you run an analysis, Optia's content script reads the current page's SEO-relevant elements (title, meta tags, headings, image alt attributes, link structure, body text) inside your browser and computes the score locally. This data is not transmitted.
+
When you run an analysis, Optia's content script reads the current page's SEO-relevant elements (title, meta tags, headings, image alt attributes, link structure, body text) inside your browser and computes the score locally. This data is not transmitted. Running an analysis adds one to the monthly count described in section 4; nothing about the page itself goes with it.
2. AI recommendation requests (sent only when you click)
When you request an AI suggestion, Optia sends the minimum needed to generate it — your target keyword and the relevant page snippet (e.g., the current title, a heading, or an image reference), plus any page-type or secondary-keyword context you configured:
@@ -51,16 +52,19 @@
2. AI recommendation requests (sent only when you click)
Bring-your-own-key mode (Pro): sent directly from your browser to Anthropic using your key. Our servers are not involved at all.
-
3. Install identifier (free-tier metering)
-
Free-tier AI requests include a random install ID generated by your extension. It exists solely to meter the free monthly allowance, is not linked to your identity, and resets if you reinstall.
+
3. Install identifier
+
Your extension generates a random install ID. It is sent with hosted AI requests, where it meters the monthly allowance; with Pro checkout and license activation, where it ties a license seat to this browser; and with the usage count in section 4. It is not linked to your identity and resets if you reinstall.
-
4. License and billing data (Pro only)
+
4. Anonymous usage count (on unless you turn it off)
+
Optia counts the pages you analyze each month, on your device. At most once a day, after you run an analysis, it sends that count to our backend (api.optia-api.com). The report contains only three things: your install ID, the month (for example 2026-11), and how many pages you have analyzed that month. It never contains URLs, page content, keywords or scores. This applies on every plan. We use the counts to see how much Optia is used, so the free tier's limits are set from real numbers. To stop the reports, turn off Share anonymous usage counts in Optia's options. Optia keeps counting on your device, so the options page can still show you the number, but sends nothing.
+
+
5. License and billing data (Pro only)
If you purchase Optia Pro, checkout and payment are handled by Stripe — we never see your card details (Stripe's privacy policy). Our backend stores what's needed to operate your license: your license key, subscription status, and billing-portal linkage. Activating Pro stores a signed entitlement token in your browser, refreshed periodically. Pro is billed by us through Stripe, not through the Chrome Web Store.
-
5. Your Anthropic API key (Pro, optional)
+
6. Your Anthropic API key (Pro, optional)
Stored only in Chrome's local extension storage on your device. Used exclusively for direct browser-to-Anthropic requests. Never transmitted to our backend, logged by us, or synced.
-
6. Settings and history (local)
+
7. Settings and history (local)
Your keyword history, per-site options, language preference, and toggles are stored in Chrome's local extension storage on your device. Nothing is synced to us.
What we don't do
@@ -74,7 +78,7 @@
What we don't do
Data retention
Local data (settings, keys, entitlement tokens): retained until you clear it or uninstall the extension.
-
Backend metering counters (install ID / license usage): retained per monthly quota period for billing and abuse prevention.
+
Backend usage counters (AI requests per install ID or license, and pages analyzed per install ID): kept as one total per month, for billing, abuse prevention and setting the free tier's limits.
Backend request logs: operational logs are short-lived and used for reliability and abuse prevention, not profiling.