goatcounter
goatcounter copied to clipboard
Embed results as `iframe`
Hey there,
I'm thinking about showing current stats in my admin interface without reinventing the wheel and just embed the main page in an iframe
. Does this work on a non-public goatcounter
page? Has someone done it and would share the setup?
Thanks for any pointers in the right direction on this!
Cheers S1SYPHOS
// Update: If there's another way of getting a nice view of the data (like the default results page) without having to reimplement everything from API results, render graphs etc, I'm grateful for suggestions!
Hello there @arp242,
I just discovered that I may allow "everyone" to see the stat's page, by doing so embedding via iframe
would work BUT since goatcounter
sets X-Frame-Options
to same-origin
, being located at a subdomain prevents iframe
embeds ..
I'd also love to have "iframe-able" site view.
I think absolutely ideal would be:
- just the site view (so no settings, no other sites)
- no X-Frame-options (or even better: safelist for domains & localhost?)
- ideally, some weird hash URL for a tiny bit of security (like
goatcounter.com/embed/{sha256}
or whatever)
goatcounter sets X-Frame-Options to same-origin
This is for a reason: it prevents certain "clickjacking" attacks, we can't "just" remove it.
So need to add a new setting which sets frame-ancestors from CSP. I'll work on that.
just the site view (so no settings, no other sites)
I'm not sure how useful this will be? If you're logged in, you will presumably want the site settings. If you're not logged in, you already don't see anything relating to the settings.
The only thing that might be useful is removing the top navigation where you can set the date range and such, but it adds a lot of if ..
in the template, which is already a bit ugly. I think you can do it with CSS already if you really want to; I'll take a look and add it in the docs.
some weird hash URL for a tiny bit of security (like goatcounter.com/embed/{sha256} or whatever)
It already has this; If you select "Dashboard viewable by" in the settings you can select "logged in users or with secret token". You will need to set that to either that or "public" anyway for embedding to work outside of logged in users.
@arp242 I'm currently working on a Python CLI tool exporting / displaying data from GC's API. This might prove useful with what I had in mind ;) thanks for your effort with the CSP setting though!
See here: https://codeberg.org/RefBW/goatpie
You can now set "Sites that can embed GoatCounter" in the settings; see https://www.goatcounter.com/help/frame for the full docs.
See here: https://codeberg.org/RefBW/goatpie
Cheers, that's pretty neat – I've thought about creating something similar, but never got around to creating it. I couldn't get it to run though, but I'll create an issue on goatpie's issue tracker for that.
I'm working on adding a real API @S1SYPHOS (#629, not yet merged but should be finished fairly soon; mostly just need to finish the docs), which should work better than using the export API for this kind of thing.
Also added goatcounter dashboard
, it's not as nice as goatpie (yet), but it works fairly well. For now it's mostly just so that I can verify the API works for real-world things, but I may work on it a bit more later.
Anyway, just FYI; would be useful for goatpie too, although you'd have to rewrite it quite a bit to use it.
Definitely piqued my interest 😉 you're a really cool fella, you know that?
@arp242 Finally tried to set up the iframe.
I have both "viewable by" and "allowed domains" set correctly:
But the iframe source still returns 303 with redirect to /user/new
. Am I missing something? Is it a DNS cache in the browser? What can be wrong?
Edit: I've tried a quick test with codepen, and also a minimal iframe embed in a pure HTML, and it doesn't work anywhere. I'm now pretty sure the "AccessToken -> Cookie -> Redirect" pattern simply doesn't work for the iframe embed
It seems to work if I try it; e.g. I added:
<iframe src="https://goatcounter.goatcounter.com?access-token=xxxx" style="width: 100%; height: 10em;"></iframe>
To https://new.arp242.net (which is just my alias for localhost) and then it loads in both Firefox and Chrome, with new profiles (just to ensure I don't have a login cookie set):
I'm pretty sure I tested this before, too.
I think the problem is that you use http://
in your example, and you need to use https as browsers will reject the cookie over HTTP (Chrome does so silently IIRC, but Firefox should have a warning in the console).
@arp242 Doesn't seem to work for me - neither safari 15.5 nor latest FF DevEd: https://akgciframe.netlify.app/ (yes, those are my real analytics for my site, I'll just switch it off or change the access-token later)
these are the settings in the goat counter:
I don't know what else could I set up differently.
Update: it works if I switch the counter to public, which, of course, isn't what I want. If switch it on and off, the last publically visible version is cached, but otherwise, it doesn't work for me. Is it possible that it doesn't actually work for "token" analytics and works only for public analytics?
Do you have errors in the browser console? And/or can you send me a link so I can take a look (can email me at [email protected] if you don't want to post it here)
Oh wait, you did include a link; do'h.
It loads for me, but not sure if you have it set to public or "secret" now?
Ah, finally isolated the issue: in safari, it's the "Prevent cross-site tracking" setting (settings > privacy), in the firefox, it's the "Enhanced Tracking Prevention" (the shield next to URL bar) I'm of two minds about this: on one hand, at least in Firefox, it's easy to create an exception, and since iframe embed is probably for your own stuff you otherwise trust, it's good enough.
In Safari, it's either on or off, and you can't create exception.
I'd say this is good enough, but perhaps the note in the docs, something like:
"The iframe embed saves the access-token as a cookie. You need to create an exception for "Cross-site tracking" for the embedding website in your browser"
Ah right; "Cookies" is set to to "Cross-site tracking cookies, and isolate cross-site cookies" for me in Firefox. I'm not sure what the default is. I don't have an Apple device; need to check my VM or BrowserStack later.
The reason it uses a cookie is so that 1) https://mine.goatcounter.com?access-key=kinda-secret doesn't show in the URL bar, can be accidentally screenshotted, copied/pasted, etc. and 2) so I don't need to add access-token=...
to every single URL.
The first isn't really an issue inside frames, because you don't see the URL, although the second issue remains, but that's not necessarily a huge issue; I need to look at it. Just passing the token around as a query is perhaps better, because this entire cookie bonanza is pretty confusing.
@arp242 Thank you for helping me identify the issue.
Now I sort of get the problem of seeing the URL in the browser bar, but I identified another problem with the cookie based approach. I now opened the analytics, to turn off the token visibility for my analytics, but since I have the cookie saved, I don't actually see the "login" header. I needed to open storage, delete the cookie, and only then I was redirected to the login screen :D
Additional thing: the hideui
param & the access-token
won't work at the same time, i.e. xxx.goatcounter.com/?hideui=1&access-token=whatever
still show the UI, since you're redirected to the default /
view.
Thanks again!
@arp242
Could you use noncing techniques ?
the iFrame paeans only has a nonce for stopping attacks
you record a uuid per iFrame
You embed on sone site as an iFrame . The call sends in the last nonce
server marks the uuid as used and creates another one and sends it back to the iFrame
It’s basically acting as a user session tracking system
If you have CSP you are isolating it to the domain the iFrame is running in.
So the used of the nonce is a different thing from an Api key .
the nonce is always changing and so when the third party web site wants to embed an iFrame it’s backend must call to ask for a nonce, then put thst nonce in the iFrame url, so that the iFrame uses it.
Each user of the site is unique and so gets a unique iFrame nonce - yes it’s a backend call on load time again :)
the db just needs to store a nonce per website embed per unique visiting load. They are rolling and so you could just use Redis or other also.
let me know if this is utter garbage for te problem domain though