Connectors
The Connector Library, how a connection is set up, where credentials are stored, and every metric the six shipped connectors offer.
A connector is a ready-made recipe for one number from one service. You pick the metric, hand Pulsaria a credential once, and the KPI refreshes itself on a schedule. Six connectors ship with the app and offer 33 metrics in total. The request they send is fixed — you cannot point a connector at a different host or ask it for a metric it does not list.
The Connector Library
The library is the catalog you pick a metric from. It opens as a dialog titled Connector Library with a search box across the top, the connector list on the left and the selected connector’s metrics on the right.
Opening it
- Start a new KPI — Create KPI on an empty dashboard, the + KPI button in a group header, on a project card, or New KPI on a project’s detail page.
- In the source step, pick the Connector card. The library opens by itself.
- Later, from an existing KPI: open the KPI dialog and use the Change button next to the metric in the connector panel.
The same dialog also opens from App Settings → the Connections card → Add a connection. Coming from there, only the connector matters — the metric you highlight is ignored, but Use selected metric still stays disabled until you select one.
Finding a metric
The left column groups connectors by category in a fixed order — Analytics, Revenue, Marketing, Development, Other — each with a count in parentheses. As shipped that means Analytics (3), Revenue (2) and Marketing (1).
Typing in Search connectors and metrics… matches connector names and descriptions and metric names and descriptions. While a query is active the right panel shows only the matching metrics, and clicking a connector selects its first match for you.
Each metric card shows the metric name, one line of description, its default unit in monospace, and an amber lower is better badge when a smaller number is the goal. Above the list, Official API docs links to the service’s own API reference.
A dimmed Coming soon block sits under the connector list. It currently names GitHub under Development. It is plain text — not clickable, not a button — and it disappears as soon as you type a search query.
What picking a metric fills in
Click a metric card, then Use selected metric. Pulsaria pre-fills the new KPI from the metric’s defaults:
| Field | Filled with |
|---|---|
| Name | The metric’s suggested name — but only while the name field is still empty |
| Unit | The metric’s default unit (clicks, %, €, min, …) |
| Direction | Up for most metrics, down for average position and bounce rate |
| KPI type | Recurring value — every shipped metric is a snapshot metric |
| Period | Month or year, depending on the metric |
| Cron schedule | 0 9 * * * for every metric except Search Console’s Previous month clicks, which uses 0 9 2 * * |
| Target | Nothing. You always type the target yourself |
Picking a metric also clears any test result you had on screen. Everything it fills in is editable afterwards — the unit is just a label, so if your Polar account bills in dollars you change € to $ on the KPI.
Unlike Bash and HTTP KPIs, a connector KPI needs no approval step. The request is defined in the app, not by you, so there is nothing to confirm.
Connections
A connection is one credential plus the settings that identify your account: a Search Console property, a GA4 property ID, a Plausible domain. It is stored once and reused by every KPI that reads from the same source.
After you confirm a metric, Pulsaria shows a picker whose title names the connector — Pick a Plausible connection, for example. If you already have one for that connector, click it and you are done. Otherwise choose Create a new connection to open the setup wizard.
The setup wizard
Three steps, shown as numbered dots at the top: Auth, Parameters, Test. Next stays disabled until the current step is valid.
Step 1 — Auth. The connector’s written Setup Guide appears here, with numbered steps and buttons that open the relevant console in your browser. Below it sits the credential field.
For Google connectors it is an eight-row JSON box. Pulsaria checks the pasted key before letting you continue and will tell you what is wrong: That doesn’t look like valid JSON, Expected type ‘service_account’ in the JSON, client_email doesn’t look like a Service Account address, private_key doesn’t look like a PEM block. For the other connectors it is a single-line monospace field that requires at least 8 characters, otherwise you get That token looks too short. Under the field: This credential is stored securely in your macOS Keychain.
Step 2 — Parameters. One field per setting the connector needs, each with its help text and its own validator. Stripe declares no parameters at all, so the step shows only the line This connector needs no extra settings — continue to the test — you still press Next.
Step 3 — Test. Give the connection a name (Connection name, help text Just a label — pick something you’ll recognize) and press Run test. The panel is headed Verify access. A green result shows the parsed value; Save connection only becomes clickable once the test succeeded and the name is not empty.
The name is pre-seeded for you: for Google connectors with the client_email from the key, otherwise with the connector’s name.
The test always runs the connector’s first metric, not the one you picked in the library. Search Console tests Monthly clicks, GA4 tests Monthly active users, Plausible tests Visitors (this month), Polar tests MRR, Stripe tests Available balance, Awin tests Pending commission (this month). A green test proves the credential and the parameters work — it does not prove your chosen metric returns data.
Where credentials are stored
Secrets go into the macOS Keychain, never into a Pulsaria file. You can find them in Keychain Access under the service name com.onepixelahead.pulsaria, with an account name of connection.<id>.
What is written to disk is metadata only: the connection’s id, name, connector, creation date, parameters, and a reference to the Keychain entry. That file is pulsaria/connections.json in the app’s Application Support folder.
connections.jsonalways lives in the default Application Support folder. Unlike your KPI data it does not follow a custom data directory, so pointing Pulsaria at an iCloud folder moves the KPIs but leaves the connection metadata behind. See Where your data lives.
macOS may ask for permission the first time Pulsaria reads a Keychain entry. Choosing “Always Allow” makes later reads silent. If you delete a Keychain item by hand, fetches fail with Credentials missing from keychain. Please re-authorize the connection.
Reusing one connection across several KPIs
This is the point of connections. Set up Search Console once, then create clicks, impressions, CTR and position as four separate KPIs — the picker offers the same connection every time and no credential is re-entered.
Each row in the picker shows a status circle, the connection name, its parameter values joined with ·, and a Verified 3 days ago line when a validation timestamp exists. The circle is green normally and turns into an amber warning triangle when the last validation stored an error, or when the last successful validation is more than 60 days old.
The picker does not re-check anything when it opens — the state is only as fresh as the last test or successful fetch. A connection that has never been validated at all, which is what an imported connection looks like, shows the green check.
Managing connections
App Settings → the Connections card lists every connection with its icon, name, connector and parameters, and its verification state. Its description reads Authentication and parameters for external data sources. Credentials live in your macOS Keychain.
Each row has three buttons:
| Button | What it does |
|---|---|
| Test (circular arrow) | Runs a live fetch of the connector’s first metric and shows the full result inline — URL, response body, error, parsed value, HTTP status, duration. Close it with the X. Success stamps the verification date and clears a stored error; failure stores the error, shown in amber under the row name |
| Edit (pencil) | Reopens the setup wizard for that connection |
| Delete (trash) | Opens the confirmation described below |
Editing works like creating, with two differences. The credential field is labelled (leave blank to keep the existing key) or (leave blank to keep the existing token) — leave it empty and the stored secret stays as it is. And changing the secret or any parameter clears a green test result, so you must run the test again.
You cannot save a connection whose test has not passed. That includes renaming one: the wizard still requires a fresh successful test before Save connection enables.
Deleting counts the connector KPIs that depend on the connection and offers a choice: Delete the connection AND the N KPIs, or Delete only the connection (N KPIs will break). With no dependents it just offers Delete connection. The Keychain entry is removed in every case. Orphaned KPIs stay on the dashboard and fail at fetch time with Connection not found (deleted?).
Edit, Delete and Add a connection are disabled once the trial has expired or a licence was revoked — the tooltip reads Requires a license or active trial. Test stays available, because recording a verification result is not tracked data. See Trial & licence.
Google Search Console
Search performance for one Search Console property.
| Metric | What the number is | Unit | Range |
|---|---|---|---|
| Monthly clicks | Clicks from Google search results | clicks | 1st to last day of the current month |
| Monthly impressions | Times your site appeared in results | impressions | 1st to last day of the current month |
| Monthly average CTR | Clicks ÷ impressions, converted to percent | % | 1st to last day of the current month |
| Monthly average position | Average ranking position, lower is better | rank | 1st to last day of the current month |
| Last 28 days clicks | Clicks in the rolling 28-day window | clicks | 28 days ago to today |
| Previous month clicks | Clicks in the full previous calendar month | clicks | 1st to last day of last month |
What you supply. A Google Service Account JSON key, and the Site URL parameter. Pulsaria requests the scope https://www.googleapis.com/auth/webmasters.readonly.
Where to get it. The setup guide has four steps with links to the Cloud Console service-accounts page and to Search Console: create a service account, create a JSON key for it (Keys → Add Key → Create new key → JSON), invite the service account’s …iam.gserviceaccount.com address to your property under Settings → Users and permissions with Restricted permission, then paste the key.
Site URL format. Either a domain property as sc-domain:example.com, or a URL-prefix property as a full URL with a trailing slash: https://www.example.com/. Getting it wrong shows URL-prefix properties need a trailing slash or Use a full https:// URL or ‘sc-domain:example.com’ format.
Pulsaria cannot grant the service account access for you — that step happens in Search Console. When the API returns no finalised rows for the range yet, the value is stored as 0 rather than failing.
Google Analytics 4
Reporting metrics for one GA4 property, read through the Analytics Data API.
| Metric | What the number is | Unit |
|---|---|---|
| Monthly active users | GA4’s activeUsers for the current month | users |
| Monthly sessions | GA4’s sessions for the current month | sessions |
| Monthly new users | GA4’s newUsers for the current month | users |
| Monthly conversions | GA4’s conversions for the current month | events |
| Average session duration | GA4’s averageSessionDuration, divided by 60 | min |
All five cover the 1st to the last day of the current calendar month.
What you supply. A Google Service Account JSON key, and the GA4 Property ID. Scope: https://www.googleapis.com/auth/analytics.readonly.
Where to get it. Four setup steps, with links to the Cloud Console, the Analytics Data API enable page and analytics.google.com: create a service account, enable the Analytics Data API on the project, add the service account email under Admin → Property access management with role Viewer (and untick Notify new users by email), then paste the key.
Property ID format. Digits only, found under Admin → Property Settings → Property Details. It is not the G-XXXX measurement ID. A non-numeric value shows Must be numeric (e.g. 123456789).
These five metrics are all there is. No custom dimensions, no filters, no arbitrary GA4 metric names. An empty result is stored as 0.
Plausible
Aggregate stats for one site on Plausible cloud.
| Metric | What the number is | Unit | Range |
|---|---|---|---|
| Visitors (this month) | Unique visitors | visitors | Calendar month to date |
| Visitors (this year) | Unique visitors | visitors | 1 January to today |
| Pageviews (this month) | Total pageviews | pageviews | Calendar month to date |
| Pageviews (this year) | Total pageviews | pageviews | 1 January to today |
| Bounce rate (this month) | Share of visits that left after one page, lower is better | % | Calendar month to date |
| Avg visit duration (this month) | Average visit duration, seconds divided by 60 | min | Calendar month to date |
What you supply. A Plausible API key and your Site domain.
Where to get it. Three setup steps. Step 1 links to https://plausible.io/settings/api-keys — sign in, go to Account Settings → API Keys, click + New API Key and copy it. The site domain is the one Plausible shows on your dashboard.
Site domain format. The bare domain exactly as Plausible shows it, e.g. example.com. Values starting with http:// or https:// are rejected, as are values with spaces, slashes or no dot at all.
The two site-domain rejections show the raw reason code —
no-protocolorinvalid-domain— instead of a sentence. Both are translation gaps, not errors on your side: drop the protocol, or use a plain domain.
Plausible cloud only. plausible.io is fixed in the request, so self-hosted and Community Edition instances are not supported. Bounce rate and visit duration exist as month metrics only.
Polar
Revenue and subscription metrics for one Polar.sh organization.
| Metric | What the number is | Unit | Range |
|---|---|---|---|
| MRR | Monthly recurring revenue, cents ÷ 100 | € | Current month’s bucket |
| Active subscriptions | Currently active subscriptions | subs | Current month’s bucket |
| Revenue (this month) | Revenue, cents ÷ 100 | € | 1st of the month to today |
| Revenue (this year) | Monthly buckets summed by Pulsaria | € | 1 January to today |
| Orders (this month) | Number of orders | orders | 1st of the month to today |
| Orders (this year) | Monthly buckets summed by Pulsaria | orders | 1 January to today |
What you supply. An Organization Access Token and the Organization ID.
Where to get it. Three setup steps, with a link to https://polar.sh/dashboard. Create the token under Settings → Developers → New Token with the metrics:read scope; it starts with polar_oat_. The Organization ID is under Settings → General.
Organization ID format. A UUID, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. Anything else shows Must be a UUID (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).
MRR and Active subscriptions read the current month’s bucket only and have no year variant. If Polar returns no periods at all, the value is stored as 0.
Stripe
Your current Stripe account balance. Two metrics, both read from GET /v1/balance.
| Metric | What the number is | Unit |
|---|---|---|
| Available balance | Funds available for payout right now, cents ÷ 100 | € |
| Pending balance | Funds still settling, cents ÷ 100 | € |
What you supply. A Stripe API key. Nothing else — this connector declares no parameters.
Where to get it. Two setup steps, with a link to https://dashboard.stripe.com/apikeys. Create a restricted key with Read permission for Balance and everything else set to None. The field placeholder is rk_live_… (restricted, read-only). A full secret key would work technically; a restricted one is what you should use.
Balance is deliberately all this connector offers. Stripe’s list endpoints cap at 100 rows per request and have no grand total, so a “revenue this month” metric would quietly undercount. Only the first entry of the balance array is read — that is your account’s primary currency, and additional currencies on a multi-currency account are ignored.
Awin
Affiliate performance for one Awin publisher account and one market.
| Metric | What the number is | Unit | Range |
|---|---|---|---|
| Pending commission (this month) | pendingComm summed across all advertisers | € | 1st of the month to today |
| Pending commission (this year) | pendingComm summed across all advertisers | € | 1 January to today |
| Sales (this month) | totalNo — number of transactions | sales | 1st of the month to today |
| Sales (this year) | totalNo — number of transactions | sales | 1 January to today |
| Sale volume (this month) | totalValue — value of referred sales | € | 1st of the month to today |
| Sale volume (this year) | totalValue — value of referred sales | € | 1 January to today |
| Clicks (this month) | clicks driven to advertisers | clicks | 1st of the month to today |
| Clicks (this year) | clicks driven to advertisers | clicks | 1 January to today |
Awin’s report returns one row per advertiser, so every metric sums the field across all of them.
What you supply. An Awin API token, your Publisher ID and a Region.
Where to get it. Three setup steps, with a link to https://ui.awin.com/. The token is created under Tools → API. The publisher ID is shown next to your account name.
Formats. Publisher ID is digits only. Region is exactly two letters — DE, GB, US. Anything else shows Use a two-letter region code (e.g. DE, GB, US).
Reports are filtered to a single Awin market, so a publisher active in several regions needs one connection per region. The timezone is fixed to UTC and the date type to transaction date. No transactions in the range gives 0, not an error; an advertiser row missing a field contributes 0, but a non-numeric value anywhere in the array fails the whole fetch.
How the Google connectors sign in
There is no “Sign in with Google” button and no consent screen. Pulsaria uses your Service Account key directly: it signs a JWT with the private key and exchanges it for a short-lived Google access token, all inside the app’s native layer.
The token is cached in memory for the hour it is valid, so several KPIs on the same connection share one token. Nothing is written to disk — restarting the app costs one extra token request. Error messages are scrubbed: anything containing a private key block is replaced with <redacted-private-key> before it reaches the log.
Creating the service account and its key is your job, in the Google Cloud Console. The setup guide walks through it, but Pulsaria cannot do it for you.
What a fetch actually sends
When a connector KPI runs, Pulsaria resolves the metric and connection into one request: it fills your parameters into the URL and body, resolves date placeholders like {{firstDayOfMonth}} against your local calendar day, reads the credential from the Keychain and sends the request natively.
Every request has the same rails: GET or POST only, a 10-second timeout, a 64 KB response cap, http/https only, at most 5 redirects, and the User-Agent pulsaria/<version>. The credential goes into an Authorization: Bearer header.
Non-2xx responses, non-JSON bodies and non-numeric values fail the fetch and no value is written. The one deliberate exception is “no data yet”: when the expected key is missing, null or an empty array, the value is recorded as 0 so a KPI does not error out every month-start.
Failures from connectors get readable messages in the fetch log — a 401 says the token was rejected, a 403 tells you the service account may not have access or the API is not enabled, a 400 points at the parameters. There is no automatic retry: the next scheduled run is the retry. See Schedules & refresh.
Connections in an export
A JSON export carries your connections as metadata — id, name, connector, parameters — but never the secrets. Those stay in the Keychain of the machine you exported from.
After importing on another Mac, Pulsaria opens the setup wizard once per connection that has no credential locally. The title reads Reconnect followed by the connection’s name, with a note like Connection 2 of 3 — re-enter credentials and an amber banner explaining why. In this mode the “leave blank” shortcut is off — you must paste the key or token again. Closing the wizard skips that connection and moves to the next; you can finish it later via App Settings → Connections → the pencil icon.
Have the original keys to hand before you start. Pulsaria has no way to move a secret between machines. Full details in Backup, export & moving Macs.
Requesting a connector
Request a connector sits in the bottom-left of the library dialog. Type the service name (required, up to 80 characters) and, optionally, what you would track, then press Send request.
This opens your email app with a pre-filled message to the Pulsaria team. Nothing is sent automatically, and nothing is stored or counted on any server. The message contains your text plus three lines of diagnostics: the app version, your platform string and your interface language. No KPI or connection data is attached.
What connectors cannot do
- Only these six services. There is no plugin system and no way to add a connector or a metric template yourself — the list is compiled into the app.
- No custom hosts. Every endpoint is fixed, so self-hosted instances are out of reach.
- No currency handling. Money metrics default to a literal
€and the cents conversion is a fixed divide-by-100 — correct for EUR, USD and GBP, wrong by 100× for zero-decimal currencies like JPY. Change the unit label on the KPI; the number itself is not converted. - No targets from the connector. You always type the target yourself.
- Nothing checks that a connector KPI is fully configured before you save it. A KPI saved without a metric or a connection saves fine and fails later with Connector KPI references no metric/connection.
- Connector KPIs only refresh automatically while Pulsaria is running, and only on macOS.
For anything the six connectors do not cover, see Custom HTTP sources and Shell commands.