Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@

# Never store certificates.
*.pem

# npm manifest
package-lock.json
39 changes: 39 additions & 0 deletions README.npm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# GoatCounter

This package contains the source of [GoatCounter's](https://www.goatcounter.com/) `count.js` and its corresponding TypeScript definitions.

## Installation

```bash
npm install goatcounter
```

## Usage

This package facilitates [self-hosting](https://www.goatcounter.com/help/countjs-host) and/or provides TypeScript definitions. It does not intend to be imported as a conventional module.

### Self-Hosting

1. Programmatically copy `./node_modules/goatcounter/public/count.js` to a public webroot directory during your application's build process.

2. Reference the script via relative URL:

```html
<script
data-goatcounter="https://MYCODE.goatcounter.com/count"
async
src="/count.js"
></script>
```

### TypeScript

To extend the global `Window` interface with a typed `goatcounter` property, configure TSConfig [`types`](https://www.typescriptlang.org/tsconfig/#types):

```json
{
"compilerOptions": {
"types": ["goatcounter"]
}
}
```
146 changes: 146 additions & 0 deletions count.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
interface Window {
/**
* GoatCounter JavaScript API
*
* @see https://www.goatcounter.com/help/js
*/
goatcounter:
| (GoatCounter.Settings &
GoatCounter.DataParameters &
GoatCounter.Methods)
| undefined;
}

declare namespace GoatCounter {
/**
* Settings that can be defined via:
*
* - `window.goatcounter` object, declared _before_ loading `count.js`
* - `<script>` tag `data-goatcounter-settings` attribute (will override settings in `window.goatcounter`)
*/
interface Settings {
/** Don’t do anything on page load, for cases where you want to call `count()` manually. Also won’t bind events. */
no_onload?: boolean;
/** Don’t bind events. */
no_events?: boolean;
/** Allow requests from local addresses (`localhost`, `192.168.0.0`, etc.) for testing the integration locally. */
allow_local?: boolean;
/** Allow requests when the page is loaded in a frame or iframe. */
allow_frame?: boolean;
/** Customize the endpoint for sending pageviews to (overrides the URL in `data-goatcounter`). Only useful if you have `no_onload`. */
endpoint?: string;
}

interface DataParameters {
/**
* Page path (without domain) or event name.
*
* Default is the value of `<link rel="canonical">` if it exists, or
* `location.pathname + location.search`.
*
* Alternatively, a callback that takes the default value and
* returns a new value. No pageview is sent if the callback returns
* `null`.
*
* @see https://www.goatcounter.com/help/modify
*/
path?: string | ((defaultValue: string) => string | null);

/**
* Human-readable title.
*
* Default is `document.title`.
*
* Alternatively, a callback that takes the default value and
* returns a new value.
*/
title?: string | ((defaultValue: string) => string);

/**
* Where the user came from; can be an URL (`https://example.com`)
* or any string (`June Newsletter`).
*
* Default is the `Referer` header.
*
* Alternatively, a callback that takes the default value and
* returns a new value.
*/
referrer?: string | ((defaultValue: string) => string);

/**
* Treat the path as an event, rather than a URL.
*/
event?: boolean;
}

interface Methods {
/**
* Send a pageview or event to GoatCounter.
*
* @param vars merged in to the global `window.goatcounter`, if it exists
*/
count(vars?: DataParameters): void;

/**
* Get URL to send to the server.
*
* @param vars merged in to the global `window.goatcounter`, if it exists
*/
url(vars?: DataParameters): string | undefined;

/**
* Determine if this request should be filtered.
*
* This will filter some bots, pre-render requests, frames (unless
* `allow_frame` is set), and local requests (unless `allow_local`
* is set).
*
* @returns string with the reason or `false`
*/
filter(): string | false;

/**
* Bind a click event to every element with `data-goatcounter-click`.
*
* Called on page load unless `no_onload` or `no_events` is set. You
* may need to call this manually if you insert elements after the
* page loads.
*
* @see https://www.goatcounter.com/help/events
*/
bind_events(): void;

/**
* Get a single query parameter from the current page’s URL.
*
* @returns `undefined` if the parameter doesn’t exist.
*/
get_query(name: string): string | undefined;

/**
* Display a page’s view count by appending an HTML document or image.
*
* @see https://www.goatcounter.com/help/visitor-counter
*/
visit_count(opt?: VisitCountOptions): void;
}

interface VisitCountOptions {
/** HTML selector to append to, can use CSS selectors as accepted by `querySelector()`. Default is `body`. */
append?: string;
/** Output type. Default is `html`. */
type?: "html" | "svg" | "png";
/** Path to display; normally this is detected from the URL, but you can override it. */
path?: string;
/** Don’t display “by GoatCounter” branding */
no_branding?: boolean;
/** HTML attributes to set or override for the element, only when type is `html`. */
attr?: Record<string, string>;
/** Extra CSS styling for HTML or SVG; only when `type` is `html` or `svg`. */
style?: string;
/** Start date; default is to include everything. As `year-month-day` or `week`, `month`, `year` for this period ago. */
start?: string;
/** End date; default is to include everything. As `year-month-day`. */
end?: string;
}
}
30 changes: 30 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "goatcounter",
"version": "4.0.0",
"description": "Easy web analytics. No tracking of personal data.",
"keywords": [
"go",
"golang",
"analytics"
],
"main": "public/count.js",
"types": "count.d.ts",
"scripts": {
"prepack": "cp README.md git.README.md && mv README.npm.md README.md",
"postpack": "mv README.md README.npm.md && mv git.README.md README.md"
},
"repository": {
"type": "git",
"url": "git+https://github.com/arp242/goatcounter.git"
},
"author": "Martin Tournoij <martin@arp242.net>",
"license": "ISC",
"bugs": {
"url": "https://github.com/arp242/goatcounter/issues"
},
"homepage": "https://www.goatcounter.com",
"files": [
"public/count.js",
"count.d.ts"
]
}
2 changes: 2 additions & 0 deletions tpl/help/countjs-host.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ inside `<script>` tags. You won’t get any new features or other updates, but t
To host `count.js` somewhere else just copy it from https://gc.zgo.at/count.js
and adjust the URL in `src`.

For convenience, the script is also published as an [npm package](https://www.npmjs.com/package/goatcounter). Once installed, it can be programmatically copied from `./node_modules/goatcounter/public/count.js` to a public webroot directory during your application's build process.

If you include it in the page's body then be sure to include the
`data-goatcounter` attribute on the script tag, or set `goatcounter.endpoint` so
GoatCounter knows where to send the pageviews to:
Expand Down
19 changes: 19 additions & 0 deletions tpl/help/js.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,22 @@ Note there is also a *Campaign Parameters* setting, which is probably easier for
most people. This is just if you want to get the campaign on only some pages, or
want to do some more advanced filtering (such as only including your own
campaigns).

TypeScript
----------

An [npm package](https://www.npmjs.com/package/goatcounter) contains `count.js` and its corresponding TypeScript definitions.

To extend the global `Window` interface with a typed `goatcounter` property:

1. Install package:

npm install goatcounter

2. Configure TSConfig [`types`](https://www.typescriptlang.org/tsconfig/#types):

{
"compilerOptions": {
"types": ["goatcounter"]
}
}