Documentation

Site marketing integrations guide

These optional connections import GitHub commits, X/Reddit brand-search posts and Meta campaign reporting. Search Console connects with Google and automatically finds the website's property. GitHub App installation and Meta business login use operator-owned apps and resource pickers; see provider connection setup. Connect with access token retains customer-owned credentials. Imported activity is correlation, not evidence that a commit or mention caused a visit or payment. No provider API access or paid credits are purchased by AnalyticFast.

Connect and verify

An owner or admin opens the site's Integrations settings and chooses Connect with Google, Install GitHub App or Connect Meta Ads. Google matches the saved website automatically; GitHub and Meta show resources the provider account can access. Provider apps must first be configured by the operator. Connect with access token still supports customer-owned credentials (and is the only option shown until the operator app exists), and X/Reddit have monitoring setup with suggested website names. Saving a manual configuration does not test credentials or make a provider request. Click Sync now to verify and import. Viewers may read status and imported activity but cannot configure, sync, change automatic sync, or disconnect.

Automatic sync is off by default for X, whose API is metered. Saving X credentials leaves it manual-only unless the customer explicitly checks the recurring-requests option. The separate Enable recurring metered X requests action also opts in. Manual requests and recurring requests can consume the customer's existing paid credits; check the provider console before using either. Other providers default to automatic sync, can be switched to manual-only, and still require the operator to wire the scheduler. Turning automatic sync off prevents new scheduled claims; it cannot recall a request already in flight.

Status distinguishes saved/unverified credentials, a successful import, an active sync, and a safe error code. Errors never show a provider response body or credentials. A failed import preserves the last successful data (mention content still expires). Replacing configuration deliberately clears its old data to avoid mixing different repositories, queries or accounts. Disconnect deletes the credential and all imported data for that site/provider. It does not revoke the credential at the provider; revoke it there separately if desired.

GitHub

The primary flow installs the read-only GitHub App and lets you select a repository. The following instructions describe the Connect with access token setup using your own token.

Create a customer-owned fine-grained personal access token, choose Only select repositories, select the one repository, set an expiry, and grant Contents: read-only. Metadata read access is automatic. Do not grant write permissions. Classic ghp_ tokens are rejected. The application cannot introspect all fine-grained token grants: repository selection and the absence of extra permissions must be set by the customer. Every request this implementation makes is a GET to the commits endpoint.

Enter owner/repository and optionally a branch/SHA, path and author filter. Imports cover the last 30 days, at most two pages of 25 commits. Filters use the API's sha, path, author, since and until parameters. Commit timestamps use commit.committer.date; these are commit dates, not deployment dates. Only the first line of the message is stored. Author email, author profile and full commit body are not stored. Links are constructed from the configured repository and returned SHA; html_url is never trusted.

Official reference verified 2026-10-28: List commits, permissions, fields and filters. The verified API version is 2026-03-10. Expired tokens, pending organization approval, repository moves and inaccessible repositories require customer attention; redirects are intentionally rejected.

Use your own approved developer app's app-only bearer token and a narrow search query such as "Your Brand". This integration reads GET https://api.x.com/2/tweets/search/recent with the currently documented post.fields=created_at. It searches the recent seven-day window (starting one minute inside its boundary to allow request transit), in recency order, fetching at most two pages of 25 posts. IDs deduplicate across pages. No scraping, archive search, user account posting or t.co expansion is implemented. Search availability, operators, credits and rate limits depend on the customer's access. Automatic sync stays off unless explicitly enabled.

Use the supplied X campaign URL builder for links you publish: it sets utm_source=x, utm_medium=social and a unique utm_campaign. View that campaign in the existing campaign breakdown. A t.co referrer cannot identify the originating post, and a brand-search result cannot establish revenue attribution.

Official references verified 2026-10-28: recent search, app-only bearer authentication, current metered pricing and credits. No credits were bought and no live requests made during implementation.

Reddit brand mentions

Obtain Reddit approval for your app and intended use, including any required commercial agreement. Use your own registered confidential OAuth application's client ID and secret, plus an honest User-Agent such as web:your.app:v1.0 (by /u/yourusername). Setup requires explicit confirmation of approved access. AnalyticFast does not apply for access, bypass restrictions, use the operator's account, or scrape Reddit.

The client exchanges its credentials at https://www.reddit.com/api/v1/access_token with grant_type=client_credentials. The short-lived bearer token is used only in memory. Search uses the official oauth.reddit.com/search endpoint or /r/<subreddit>/search, sort=new, t=week, and at most two listings of 25 posts. These are post mentions, not comprehensive comment mentions. Only canonical Reddit permalinks are retained; user-submitted destination URLs are ignored. Removed/deleted posts and deleted-author content returned by search are skipped. No author identity is persisted.

Mention snapshots for X and Reddit expire after 48 hours and are suppressed from reads at expiry, even if cron is unavailable. Scheduler maintenance physically deletes at most 1,000 expired rows per invocation. Keep maintenance running and monitor backlog; fresh search is not a complete deletion/compliance feed. Current bounded snapshots replace the earlier mention snapshot after a successful sync.

Official references verified 2026-10-28: search endpoint and listing fields, application-only OAuth, current access, User-Agent, deletion and retention guidance. Reddit's current guidance links the legacy OAuth reference and warns that legacy documentation may change; approved access must be verified externally.

Meta Ads

The primary flow uses Meta business login and an ad-account picker. Its long-lived user grant and app-secret proof stay encrypted on the server; expired access requires reconnecting. The following instructions describe the manual Connect with access token setup.

Supply your own ad account ID (123 or act_123) and an access token with ads_read and reporting access to that account. Do not request ads_management for this integration. App review/advanced access may be needed to access other businesses' accounts; approval, account assignment, token issuance/renewal and provider-specific commercial requirements remain external setup. No OAuth onboarding, token refresh or app-secret proof is implemented. Accounts that require app-secret proof cannot use this token-only connector. No ads, campaigns or budgets are changed.

The importer reads the account's currency and timezone_name, then campaign-level Insights with time_increment=1 for the previous seven completed ad-account calendar days. It requests campaign ID/name, date_start/date_stop, account_currency, spend, clicks and impressions. It makes at most three GETs (account plus two pages), imports at most 50 campaign days in the provider's returned order, and explicitly marks truncation. This is not a complete spend report when more pages exist; it does not claim to select the highest-spend campaigns. No actions, modeled purchases or Meta purchase revenue are treated as AnalyticFast revenue.

Spend is parsed as exact integer minor units for its currency, including zero- and three-decimal currencies. Invalid, negative, over-precision or unsafe-integer monetary values fail the import. Dates are ad-account dates; they can differ from the site's calendar dates. Day boundaries handle fractional offsets, DST and midnight DST gaps.

Add these parameters to the actual destination links in Meta:

utm_source=facebook&utm_medium=paid_social&utm_campaign={{campaign.id}}

Revenue is the signed sum of existing payments/refunds whose stored last non-direct session has that exact campaign ID in utm_campaign, a source of facebook/fb/instagram/ig/meta, and a paid medium of cpc/ppc/paid/paid_social/paidsocial. The session must belong to the same site and identified visitor and precede the payment. The date is the payment/refund date in the ad-account timezone, not a click cohort. Refunds therefore reduce the refund day's revenue only when that campaign day exists in the imported table. Campaign names, a Facebook referrer alone, unlinked payments, organic links, another site's sessions and search mentions do not create attribution.

ROAS divides that revenue by spend only with matching account/site reporting currencies. Other payment currencies are excluded and counted visibly. If site/account currencies differ, revenue and ROAS are unavailable rather than converted. Zero spend produces unavailable ROAS; negative refund revenue can produce negative ROAS. Missing identity/UTMs, consent and blockers leave attribution incomplete. This is observational last-touch reporting, not incremental lift or Meta's attribution model. Switching the existing dashboard's first-touch toggle does not change this connector's explicitly labeled last-touch model.

Successful complete imports replace only their covered seven-day window. Truncated imports update returned rows without deleting omitted campaigns; omitted rows may be stale. Older days remain until a 90-day/1,000-row per-site cap removes them. Reads show at most 50 campaign days, newest date then spend descending. Imports refresh seven days only; older provider corrections and long delayed refunds are not backfilled.

Official sources checked 2026-10-28: Insights, ads_read, Meta's SDK version, Insights fields, account fields, GET Insights parameters. Developer documentation returned 429/unavailable during verification; version v26.0, fields and request parameters were verified against Meta's current official generated SDK sources. No live account/token verification was performed.

Boundaries and troubleshooting

Credentials use the existing Worker-held PROVIDER_ENCRYPTION_KEY (32 random bytes encoded as hex) with AES-GCM and authenticated context integration:<siteId>:<provider>. Only ciphertext is stored; status/activity never returns credentials, ciphertext, revision or lease tokens. Configure this existing secret through the operator's normal secure process; do not paste it into a repository or dashboard.

All endpoints require a browser session and requireSiteAccess. Cookie mutations use existing CSRF protection. Reads allow viewers; setup, automatic sync, manual sync and disconnect require admin/owner. Bearer API tokens, widgets and share links cannot use these endpoints. Analytics reads respect existing entitlement checks. SQL is exclusively in store/integrations.ts.

External requests allow only fixed HTTPS provider endpoint paths, reject redirects, cap JSON at 512 KiB, time out after eight seconds including body reads and never follow provider pagination URLs. Responses with partial provider errors, malformed IDs/dates/currencies/cursors or oversized pages fail before writing. Safe fixed error codes describe rate limiting, access denial, missing resources, expired credentials and missing credits. There are no automatic retries.

Each connection has a two-minute sync lease and a one-minute manual cooldown. Configuration revisions and lease tokens guard every write in an atomic D1 batch, so disconnect, replacement, or a newer sync prevents a stale request from restoring data. Failures preserve prior successful rows. Automatic sync rechecks opt-in atomically when claiming a lease. Cron processes five due connections per invocation by default (maximum twenty), least-recent attempt first; the due interval is six hours. At larger scale, schedule more frequent bounded invocations or add a queue. Manual sync works independently of cron.

Open Settings → Integrations to configure each connection. The private dashboard shows imported activity and adds GitHub commit markers to its main chart. Activity uses the selected dates, capped at the most recent 90 days of long ranges; dashboard filters and the attribution toggle do not change the integration report. Use Settings → Dashboard to hide this card.

Scheduled refresh checks due connections hourly, with a six-hour interval per connection and five connections processed per invocation. X remains manual-only unless explicitly enabled. This guide is also available in the public documentation under /docs/api/integrations/marketing. Provider credentials and approvals must be supplied by the customer; local tests use mocked provider responses and do not prove live access.

Questions, answered.

How do I use site marketing integrations with AnalyticFast?

Follow the Site marketing integrations instructions on this page using your own website’s Site ID and configuration. Verify a real event before relying on the reports.

Where can I get setup help?

Contact support@analyticfast.com with the website domain and a redacted description. Do not send API tokens, signing secrets or personal customer data.