An install key is public by nature: it is in your HTML. What stops a copied key filling your project with somebody else's traffic is not secrecy, it is the rules below.
The three rules, and what each one is for
| Rule | Where it lives | What it judges | A request with no Origin |
|---|---|---|---|
data-domains |
the script tag | the hostname in the visitor's address bar | not applicable — it never runs |
| A key's allowed origins | Project → Keys, on the key | the request's Origin host |
refused |
| Allowed hostnames | Project → Settings → Shields | the request's Origin host |
accepted |
They stack. The tag stops a copied page from sending at all; the key rule refuses anything that is not a browser on a listed host; the shield refuses a browser request from an unlisted host while still letting your servers send.
Name the hosts on the tag
<script defer src="https://api.datavisitors.com/assets/sg.js" data-key="YOUR-INSTALL-KEY" data-domains="example.com,www.example.com"></script>
The comparison uses exact hostnames. A copied page on another hostname sends nothing. This is the cheapest rule to apply and the easiest to bypass, because it runs in a browser you do not control — treat it as tidiness, not as a defence.
Lock the key to its origins
On the project's Keys page, open a key's rules and list the hosts it may be used from.
example.comwww.example.comapp.example.com
What the field accepts, exactly:
- Hostnames, not URLs. A scheme, a port and a path are stripped, and the result is lowercased.
https://example.com:443/pricingis stored asexample.com. - No wildcards.
*.example.comis not a hostname and is refused. List each subdomain you use. - At most 10 hosts per key. Duplicates are dropped.
- An empty list means no rule at all.
Once the list is not empty, the key refuses any request whose Origin header is absent or unlisted, with 403. A server-side sender has no Origin, so an origin-locked key is a browser key and nothing else — give your servers their own key.
A rule change is applied everywhere at once: the service is told to drop its cached copy of the key in the same transaction that saves the rules.
Or refuse by hostname at the project
Settings → Shields → Allowed hostnames is the project-wide version: a comma-separated list of at most 10 hostnames. An empty list permits every hostname; a non-empty one permits browser requests from the named hostnames only, and refuses the rest with hostname_not_allowed.
Unlike the key rule, this one leaves a request with no Origin alone. A server-side SDK is not a copied snippet, so it is not what this rule is looking for.
Development machines
The tracker already refuses to run on localhost, a file: URL, or a page driven by a robot, so local work does not reach your numbers. Add data-include-localhost to the tag while you test, or — better — create a second project for development and keep the two sets of numbers apart.
When events are refused
Refused events are counted and answered, never silently dropped. The ingest returns 202 with a per-event code, so a missing hostname shows up as a run of hostname_not_allowed rather than as a mystery. A request the key's own rules refuse is a plain 403, before any event is read.