Embedding GoGood on your site
Put the interactive map guide or the event submission form on your own pages — iframe snippets, sizing, the resize handshake, theme parameters, and what to check when a frame comes up blank.
Three things can be embedded in your own pages:
| What it is | Needs a key? | |
|---|---|---|
| Guide embed | The interactive map guide — the same one on gogoodtravel.com, scoped to your destination | No |
| Events calendar | Your destination's upcoming events, as a browsable agenda | No |
| Event submission form | A form your visitors use to submit events to the guide | No |
All three are plain <iframe>s. Nothing to install, no script library, no build step. If you want to render event data as native pages on your own site instead of in a frame, that is the read API — see Events API integration.
Staff generate ready-to-paste snippets for any destination from the admin Embeds page. A business owner gets the map guide and the events calendar for their own destination under Add GoGood to your site in their account — that page picks their most local guide automatically, so there is nothing to choose. The submission form is admin-only.
This page documents what those snippets do and what you can change.
1. Guide embed
<!-- GoGood Travel Guide Embed -->
<iframe
src="https://gogoodtravel.com/golden/app"
width="100%"
height="700"
frameborder="0"
style="border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);"
allow="geolocation"
title="GoGood Travel Guide - Golden"
></iframe>
Replace the src with your own guide URL and the title with your destination's name.
Your guide URL
The path depends on how your guide is set up, so copy the URL from the generator rather than assembling it by hand:
| Guide type | URL shape | Example |
|---|---|---|
| Single destination | /<tenant>/app | https://gogoodtravel.com/golden/app |
| Has sub-destinations | /<tenant>/places | https://gogoodtravel.com/colorado/places |
| One sub-destination | /<tenant>/places/<destination> | https://gogoodtravel.com/colorado/places/boulder |
| All of GoGood | /places | https://gogoodtravel.com/places |
Always use the https://gogoodtravel.com origin. Embeds point at production even when a snippet is generated from a preview environment.
Size
width="100%" fills whatever container you drop it into. For a fixed width, set both the attribute and the inline style, and keep max-width: 100% so it still fits on a phone:
width="800"
style="border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); max-width: 100%; margin: 0 auto; display: block;"
Height is fixed at whatever you set. The guide does not report its height to your page, so 700 is a starting point — raise it if the guide feels cramped. Somewhere between 600 and 900 suits most layouts. (The calendar and submission form do auto-resize; see below.)
See it live
Both of these are the real guide, running in this page — not screenshots.
Inside the text column — live, not a screenshotLoading the live guide…
Full width — live, not a screenshotLoading the live guide…
The only difference between them is the width you set above. The map itself adapts; a narrow column shows the list and a wider one shows more map, so pick whichever suits the page you're putting it on.
allow="geolocation"
Keep this. It lets a visitor use "near me" inside the guide.
Geolocation only reaches the frame if your page is allowed to use it too. If your site sets a Permissions-Policy header, it must permit geolocation for the gogoodtravel.com origin, or the button silently does nothing.
Appearance
The guide embed takes no theme or colour parameters. It renders with your destination's own branding, which is configured on our side — if the colours or logo are wrong, that's a settings change we make for you, not a URL parameter.
2. Events calendar
Your destination's upcoming events, without the guide's map and navigation. Same content as the "What's On" page on GoGood, sized to sit inside your own layout.
<!-- GoGood Travel — upcoming events -->
<iframe
id="gogood-calendar"
src="https://gogoodtravel.com/embed/<tenant>/calendar"
width="100%"
height="1100"
frameborder="0"
style="border: 0; width: 100%;"
title="Upcoming events"
></iframe>
<script>
// The calendar grows and shrinks as the visitor changes view; resize to
// match so there's no scrollbar inside the frame.
window.addEventListener('message', function (e) {
var d = e.data
if (!d || d.type !== 'gogood:embed:height') return
if (typeof d.height !== 'number' || !isFinite(d.height)) return
var frames = document.getElementsByTagName('iframe')
for (var i = 0; i < frames.length; i++) {
if (frames[i].contentWindow === e.source) {
frames[i].style.height = d.height + 'px'
return
}
}
var f = document.getElementById('gogood-calendar')
if (f) f.style.height = d.height + 'px'
})
</script>
Replace <tenant> with your tenant slug — the same segment in your guide URL.
What it shows
Published, scheduled events at venues in your destination, looking 90 days ahead and three months back. Visitors can switch between day, week and month views, page backward into events that have already happened (marked "Past" and shown recessed), search, and filter by category. Each event card opens its full listing on GoGood in a new tab, so nobody is navigated away from your site.
Events appear here automatically once approved — there's nothing to sync.
The resize script
Same handshake as the submission form: the embed posts { type: 'gogood:embed:height', height: <number> } on every size change. A calendar changes height a lot — switching to month view, paging to a busier week — so without the listener you get a fixed 1100px box with a scrollbar inside it.
You only need the listener once, even with several GoGood embeds on the page. It matches each message back to the frame that sent it, so the calendar's height is never applied to the submission form.
See it live
The real calendar, in this page. Both of these are capped at 1024px tall and scroll inside their frame so they don't take over this page — on your page they grow to fit instead, with no inner scrollbar.
Inside the text column — live, not a screenshot · scrolls inside the frame here; on your page it grows to fitLoading the live calendar…
Full width — live, not a screenshot · scrolls inside the frame here; on your page it grows to fitLoading the live calendar…
A month grid needs room. In a narrow column the day and week views read better, which is why the snippet opens on the month view only when there's width for it.
Theme parameters
The same two as the submission form:
https://gogoodtravel.com/embed/<tenant>/calendar?accent=1a7f5a&theme=dark
accent takes six hex digits (# optional, and encode it as %23 if you include it); theme=dark switches to dark surfaces.
If it's empty
The calendar opens on today and covers the next 90 days plus the previous three months. It never shows past events unbidden — a visitor reaches them by paging back with the arrows — so an empty state on load means nothing is scheduled ahead, which is the correct result. If you expect events and see none, check they're published, and try paging back before assuming the embed is broken.
3. Event submission form
Lets visitors submit an event to the guide from your own site. Submissions land in a review queue; nothing publishes automatically.
<!-- GoGood Travel — submit an event -->
<iframe
id="gogood-submit-event"
src="https://gogoodtravel.com/embed/<tenant>/submit-event"
width="100%"
height="900"
frameborder="0"
style="border: 0; width: 100%;"
title="Submit an event"
></iframe>
<script>
// The form's height changes as the user fills it in; resize to match so
// there's no scrollbar inside the frame.
window.addEventListener('message', function (e) {
var d = e.data
if (!d || d.type !== 'gogood:embed:height') return
if (typeof d.height !== 'number' || !isFinite(d.height)) return
var frames = document.getElementsByTagName('iframe')
for (var i = 0; i < frames.length; i++) {
if (frames[i].contentWindow === e.source) {
frames[i].style.height = d.height + 'px'
return
}
}
var f = document.getElementById('gogood-submit-event')
if (f) f.style.height = d.height + 'px'
})
</script>
Replace <tenant> with your tenant slug — the same segment that appears in your guide URL.
The resize script is not optional
The form grows and shrinks as it is filled in: date fields expand for recurring events, validation messages appear, the venue picker opens. Without the listener you get a fixed 900px box with a scrollbar inside the iframe, which is the single most common way this embed is set up wrong. There is no error message — it just looks bad.
The embed posts one message to the parent window on every size change:
{ type: 'gogood:embed:height', height: 1240 }
height is an integer in CSS pixels. Nothing else is ever sent, and the embed does not listen for messages from your page.
Keep both checks in the listener. Your page can receive postMessage from any frame it hosts, including ad frames and third-party widgets — the type check and the finite-number check are what stop an unrelated frame from resizing ours. If you adapt the snippet, keep them.
Theme parameters
Two query parameters, both optional:
| Parameter | Values | Default | Effect |
|---|---|---|---|
accent | Six hex digits, # optional | brand green | Buttons, focus rings, links |
theme | dark | light | Dark surfaces and text |
https://gogoodtravel.com/embed/<tenant>/submit-event?accent=1a7f5a&theme=dark
Two things that catch people out:
- Six digits exactly.
accent=f00is silently ignored — writeaccent=ff0000. - Encode the
#as%23if you include it. A literal#in a URL starts the fragment, so?accent=#1a7f5asends nothing at all. Easiest to just leave it off.
theme only recognises dark. Any other value, including light, renders the light theme.
Times are your destination's local time
Submission times are interpreted in your destination's own timezone, derived from its location — so a submitter in Singapore enters Singapore time and a submitter in Golden enters Mountain time. Nothing to configure.
The exception is a guide that spans several countries (a certification collection, for instance): there is no single local time for it, so those fall back to Mountain time. If that applies to you and it matters, tell us and we will set a zone for your guide.
What happens to a submission
- The submitter confirms their email address.
- The event enters a review queue — a human approves it before it appears anywhere.
- Approved events show up in the guide and in the read API.
The form is protected by a honeypot field and per-email and per-IP rate limiting, and venue details are re-validated server-side. You do not need to add a CAPTCHA.
Why an iframe and not a script widget
A script widget would run our JavaScript in your page's origin — access to your cookies, your DOM, and your visitors' input. An iframe cannot do any of that. It also means a change on our side can never break your page's layout beyond the box you gave it.
The form is noindex, so embedding it will not create duplicate content against your own pages.
4. Troubleshooting
Nothing renders / the frame is blank. Check the URL loads directly in a browser tab. A mistyped tenant slug 404s rather than falling back, which is deliberate — otherwise a typo would put the global form on your page and route your visitors' submissions to the wrong destination.
Scrollbar inside the submission form or the calendar.
The resize script is missing. If you adapted it, make sure the id in the script matches the one on the iframe.
The calendar is empty. It opens on today and looks 90 days ahead, so events that have already finished don't appear until you page backward (up to three months). Check the events are published, and use the back arrow if the dates have passed.
"Near me" does nothing in the guide.
Your page's Permissions-Policy isn't allowing geolocation through to the frame. Also note browsers only grant it on HTTPS.
The frame is cut off on mobile.
A fixed pixel width without max-width: 100%. Add it to the inline style.
Our account pages won't embed.
Deliberate. Account, admin and sign-up pages send frame-ancestors 'self' and cannot be framed by another site. Only the guide and the submission form are embeddable.
5. Getting help
Email info@gogoodtravel.com with the page you're embedding on and the snippet you used. If the guide renders standalone but not in your page, include any console errors — a Content Security Policy on your side is the usual cause.