---
title: "Gatehouse - Member Portal and Login Pages: setup guide"
description: This is the setup guide for HubSpot admins installing Gatehouse - Member Portal and Login Pages, a HubSpot theme by All Gusto.
image: https://allgusto.com/hubfs/brand-2026/allgusto-og-1200x630.png
---

[Skip to content](https://allgusto.com/gatehouse/setup-guide#main)

[![All Gusto](https://allgusto.com/hs-fs/hubfs/All%20Gusto%20-%20Logo%20-%20Black%20-%20Transparent-1.png?width=340&height=226)](https://allgusto.com/)

- [Home](https://allgusto.com/)
- [About](https://allgusto.com/about)
- [Blog](https://allgusto.com/blog)
- [Contact](https://allgusto.com/contact-us)

# Gatehouse - Member Portal and Login Pages: setup guide

This is the setup guide for HubSpot admins installing **Gatehouse - Member Portal and Login Pages**, a HubSpot theme by [All Gusto](https://allgusto.com). Support: [info@allgusto.com](mailto:info@allgusto.com). Live demo: [https://gatehouse.allgusto.com/](https://gatehouse.allgusto.com/)

The theme is the layout, header and footer, colors and fonts, sign-in pages, blog templates and system pages. It does not read CRM data and it names no buyer. The optional data pack, from section 3 on, is a separate install. It is not part of the marketplace theme download. A note marked **Check in your account** is a HubSpot account detail to confirm in your own account before you rely on it.

**Deals and "Projects".** This guide says "deals", HubSpot's name for the object. Members see deals labeled **Projects** by default (headings, empty states, captions). The label is an editable field on the Member portal module.

Last updated October 2026. UI labels in **bold** match HubSpot's menus or Gatehouse's own fields. If a label differs in your account, follow the linked HubSpot page.

## What you get

The product comes in two parts:

| Part | What it does | Reads CRM data |
| --- | --- | --- |
| **Gatehouse (theme)** | Layout, header and footer, colors and fonts, sign-in, registration and password pages, a password prompt page, a styled 404 page, a member dashboard page shell, a **resources page** with a Resource list module (it lists files and links; the files themselves stay at public URLs), a **"request a change" profile page** with a standard HubSpot form, a page intro module and a help card. | No |
| **Data pack** | A single **Member portal** module that shows a signed-in member's own records (dashboard cards, a records list, or one record's details), three ready-made portal page templates, an optional sign-out page, an access-denied page and the schema for the access rules table. | Yes |

Gatehouse works without the data pack. Without it, the member dashboard shell shows a sign-in prompt and an empty area for your own content. A records page (a list of a member's records) comes only with the data pack. The data pack isn't part of the marketplace download. It's installed separately (see section 3).

## 1. Check the prerequisites

1. **Subscription for members-only pages.** Content Hub Professional or Enterprise is required to set up private content on pages or blog posts. Legacy CMS Hub Professional accounts don't support memberships. Service Hub Professional or Enterprise covers private content for knowledge base articles and customer portals, not website pages. Source: [https://knowledge.hubspot.com/website-pages/require-member-registration-to-access-private-content](https://knowledge.hubspot.com/website-pages/require-member-registration-to-access-private-content)
2. **Access group limits.** Professional accounts can have up to two access groups. Enterprise accounts can have up to 100. (Same KB page.)
3. **HubDB.** The access rules live in a HubDB table. Content Hub Professional or Enterprise is required to use HubDB on pages. Source: [https://knowledge.hubspot.com/website-and-landing-pages/create-and-hubdb-tables](https://knowledge.hubspot.com/website-and-landing-pages/create-and-hubdb-tables)
4. **Custom objects (optional).** Showing a custom object in the portal needs Content Hub Enterprise. Custom objects in the portal need Content Hub Enterprise. Source: [https://developers.hubspot.com/docs/cms/start-building/features/data-driven-content/crm-objects](https://developers.hubspot.com/docs/cms/start-building/features/data-driven-content/crm-objects)
5. **A connected domain.** Private content works only on connected subdomains that are set as the primary or secondary subdomain for the content type. Default HubSpot domains (for example `hs-sites.com`) aren't supported. Source: [https://knowledge.hubspot.com/website-pages/require-member-registration-to-access-private-content](https://knowledge.hubspot.com/website-pages/require-member-registration-to-access-private-content)
6. **Permissions.** Installing from the marketplace needs Template Marketplace access permissions. Publishing pages needs Edit and Publish permission for pages. Creating the rules table needs HubDB table settings permission, and editing or publishing it needs HubDB permission. Editing access groups needs Edit permission for segments. Sources: the KB pages above and [https://knowledge.hubspot.com/marketplace/install-themes-and-modules-from-the-hubspot-marketplace](https://knowledge.hubspot.com/marketplace/install-themes-and-modules-from-the-hubspot-marketplace)

## 2. Install the theme

1. In your HubSpot account, click the marketplace icon in the top navigation bar, then select **HubSpot Marketplace**.
2. Click **Templates** and search for Gatehouse.
3. On the listing, click **Purchase** and follow the steps.
4. To change colors, fonts, corner radius and logo later: click the marketplace icon, select **Marketplace Downloads**, then use the **Actions** dropdown next to the theme and select **Edit theme settings**.

Source: [https://knowledge.hubspot.com/marketplace/install-themes-and-modules-from-the-hubspot-marketplace](https://knowledge.hubspot.com/marketplace/install-themes-and-modules-from-the-hubspot-marketplace)

**Using the data pack? Read section 3 first.** The data pack needs the theme uploaded as `gatehouse`, with the pack beside it. A marketplace install puts the theme somewhere else, and the pack can't find it there (see "Marketplace installs and the data pack" in section 3).

**Theme settings**: **Colors** (Primary, Text on primary, Accent, Text, Background, Surface, Error, Success, Link, Link hover, button text and background, form and form-button colors), **Typography** (Heading font, Body font, a font for each of h1–h6, Link font, Form font, Button font, Base text size: 16, 17 or 18px, set relative to the browser's default so a member's browser text-size setting still enlarges the page), **Shape** (Corner radius, Card shadow: none, subtle or raised), **Layout** (Content width: narrow 1040px, standard 1152px or wide 1280px), **Branding** (Logo), **Header** (Logo, background, text color, font), **Footer** (Logo, background, text color, font). Primary color and the header logo default to your brand settings. The default Slate palette (grey page, white cards) meets WCAG AA contrast. If you change them, keep text at a 4.5:1 contrast ratio or better against its background.

**Global header** (edit it once and it applies everywhere): **Portal name**, **Dashboard link**, **Member menu**, **Navigation name for screen readers**, the sign-in and sign-out button text, **Show register link to logged-out visitors**, and **Skip link text**. **Footer**: **Copyright holder**, **Support link**, **Support link text**.

## 3. Install the data pack

All Gusto installs the data pack separately from the theme. This section explains what it adds so you know what to expect.

> **Required: the data pack needs the theme uploaded as `gatehouse`, with the pack beside it.** In the design manager root you need exactly these two folders, side by side:
> 
> `/gatehouse the Gatehouse theme (label "Gatehouse - Member Portal and Login Pages") /allgusto-portal-data the data pack`
> 
> With the HubSpot CLI, upload the theme folder from your download as `gatehouse` (`hs cms upload <theme folder> gatehouse`) and the pack folder as `allgusto-portal-data` (`hs cms upload <pack folder> allgusto-portal-data`). Any other theme location (a renamed folder, a subfolder, or a marketplace install) breaks every data pack template.

1. The data pack is a separate folder, `allgusto-portal-data`, that sits next to the theme folder at the root of the design manager.
2. The pack's templates point at the theme by a fixed folder path, `/gatehouse`. Don't rename or move the theme folder after installing: the pack's templates and the theme modules they use would stop working. The pack can only use a fixed theme path, so the path can't be made a setting. This also means the pack works only with the theme uploaded directly as `/gatehouse`. A theme installed from the HubSpot Marketplace is not at that path (see "Marketplace installs and the data pack" below); email [info@allgusto.com](mailto:info@allgusto.com) before installing the pack.
3. The pack contains: - The **Member portal** module. It's the only module that reads CRM or HubDB data, and it runs in one of three modes: **Dashboard cards**, **Records list**, or **Record detail (reads ?id=)**. - Three page templates: member dashboard with data cards, member records list, and member record detail. Each one places the Member portal module in a fixed slot. - An optional sign-out page template. It isn't for marketplace installs, because HubSpot restricts that template type there. - An access-denied page template (`Gatehouse data pack - membership access denied`). Assign it on a data-pack install (section 4). A marketplace install uses HubSpot's default page, because marketplace validation rejects this template type. - The schema for the access rules table (`ag_portal_rules`).
4. **One data module per page.** The Member portal module doesn't appear in the page editor's module picker, by design. Don't add a second copy to a portal page in the design manager. A second data module uses up the page's data requests and the member sees **This page isn't set up correctly**.

### Marketplace installs and the data pack

A theme installed from the HubSpot Marketplace lives under `@marketplace/<publisher>/<theme>/`, not at `/gatehouse`. Data pack templates and modules use fixed paths under `/gatehouse`, so they do not work with a marketplace install on their own.

**Supported setup for the data pack:** upload the theme as `gatehouse` with the pack beside it (see above). If you installed Gatehouse from the Marketplace and also need the data pack, email [info@allgusto.com](mailto:info@allgusto.com) before installing the pack. We will set up the pack to work with your install.

## 4. Turn on private content and pick the templates

1. Click the settings icon in the top navigation bar.
2. In the left sidebar, go to **Content \> Private Content**.
3. Click **Choose a domain to edit** and select the domain your portal runs on.
4. In **Website admin**, enter the email address members should contact when they have trouble signing in.
5. Leave **Self-registration** off unless you want people to sign up on their own. If you turn it on, also turn on **Show register link to logged-out visitors** in the global header.
6. Open the **Pages** tab and choose these templates: - **Sign in page**: `Gatehouse - membership login` - **Registration page**: `Gatehouse - membership registration` - **Request password reset page**: `Gatehouse - membership reset password request` - **Create new password page**: `Gatehouse - membership reset password` - **Access denied page**: on a data-pack install, select `Gatehouse data pack - membership access denied` here, under **Content \> Private Content** (memberships, the Pages templates). A marketplace install has no such template; leave HubSpot's default page. - **Sign out page**: HubSpot's default, or the data pack's optional template on non-marketplace installs.
7. Under **Destinations**, set **After someone signs in** to your portal dashboard page (created in section 7).
8. Save.
9. On a data-pack install, open the design manager template **Gatehouse data pack - membership access denied** and set the **Support button** field **Button URL** to a site path (`/…`), an `https://` link, or a `mailto:` address. Leave **Button URL** empty to hide that button: nothing is left in its place. The heading and intro do not depend on a support link, so the page still reads correctly with the URL empty. A marketplace install has no such template.

Source: [https://knowledge.hubspot.com/website-pages/manage-private-content-settings](https://knowledge.hubspot.com/website-pages/manage-private-content-settings)

Then pick the password prompt and 404 pages:

1. Click the settings icon, then go to **Content \> Pages**.
2. Click the **System Pages** tab.
3. Set **404 error page** to `Gatehouse - 404 page not found` and **Password prompt page** to `Gatehouse - password prompt`.
4. Click **Save**.

Source: [https://knowledge.hubspot.com/design-manager/use-system-templates-to-customize-error-subscription-and-password-prompt-pages](https://knowledge.hubspot.com/design-manager/use-system-templates-to-customize-error-subscription-and-password-prompt-pages)

Don't skip the 404 page. When a member opens a record they can't see, or a link with a wrong or deleted id, the portal returns a real 404 and HubSpot shows your site's 404 page instead. Gatehouse's 404 page uses your branding and keeps the member menu. Keep it generic: don't add data modules, personalization tokens or contact fields to it. Because members get this 404 page, the record detail's **Not found heading** and **Not found text** only show in the page editor and preview.

## 5. Create the access group

1. In your HubSpot account, go to **Content \> Memberships** (under **More** if it appears).
2. Click **Create access group**.
3. Enter an **Access group name**, for example "Portal members".
4. Select **Static** (you add contacts by hand or from static segments) or **Dynamic** (contacts are added by filters), then click **Next**.
5. Add contacts or set your filters, click **Next**, review the list, then click **Create group**.

Source: [https://knowledge.hubspot.com/website-pages/require-member-registration-to-access-private-content](https://knowledge.hubspot.com/website-pages/require-member-registration-to-access-private-content)

Example of a dynamic group: filter on a contact property you control, such as a checkbox named "Portal access" that a workflow sets to true. The property name is only an example; the theme doesn't need a specific one.

Before you connect the group to a page:

- When an access group is first linked to private content, every contact in it gets a registration email. A contact added later gets one when they join.
- HubSpot sends at most 25,000 registration emails when a group is first linked to content.
- Each contact can receive at most five membership emails a day (invitations, password resets and similar). The limit resets at 12:00 AM UTC.

Removing a contact from the access group usually takes effect within about a minute. During that minute, the member's portal pages may briefly flip between denied and their own data. They never see another member's data.

For a faster cut-off, also delete the contact's membership registration in HubSpot.

## 6. Create and publish the access rules table

Members always see their own tickets and their own contact details. Everything else (deals, the company card, custom objects, tickets shared through a company) appears only when an enabled rule in this table allows it. With no rules, members see their tickets and nothing else.

### Create the table

1. Go to **Content \> HubDB** and click **Create table**.
2. Enter a **Table label** (for example "Portal access rules") and **Table name** `ag_portal_rules`. You can't change the name after you publish. To use a different name, enter it in the Member portal module's **Access rules table (HubDB table name)** field on every portal page.
3. Click **Create**.
4. Leave the table private. In **Actions \> Manage settings**, keep **Allow public API access** and **Enable creation of dynamic pages using row data** turned off.

Source for the steps and labels: [https://knowledge.hubspot.com/website-and-landing-pages/create-and-hubdb-tables](https://knowledge.hubspot.com/website-and-landing-pages/create-and-hubdb-tables)

### Add the columns

Use **Actions \> Add column** for each column. Column names must match exactly.

| Column name | Type | What to enter |
| --- | --- | --- |
| `enabled` | Boolean | On for active rules. |
| `object` | Text | `deal`, `ticket`, `company`, or `custom:<key>` (Content Hub Enterprise). |
| `path` | Text | `P1` = the contact is associated with the record. `P2` = the contact is associated with a company under a specific label, and the record belongs to that company. |
| `category` | Text | `HUBSPOT_DEFINED`, `USER_DEFINED` or `INTEGRATOR_DEFINED`. |
| `type_id` | Number | The association type ID, contact to object direction (for P2: contact to company). |
| `permission` | Text | `list` (shown in lists and cards), `list+detail` (can also be opened on a detail page) or `profile` (the company card). |
| `properties` | Text | Comma-separated internal property names. Required: a rule with no list is ignored. Only these properties are fetched and shown. |
| `note` | Text | Your own note. Never shown to members. |
| `allow_all_associated` | Number | P2 only. Write `0` (default) or `1`. See the warning below. |

You can also import rows from a CSV with **Actions \> Import** (same KB page).

### Example rows

| enabled | object | path | category | type\_id | permission | properties | allow\_all\_associated | What it does |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| on | company | P1 | HUBSPOT\_DEFINED | 1 | profile | name,domain,phone,city | 0 | Company card shows the member's primary company. This is the default rule. Turn it off to hide the card. |
| on | deal | P1 | HUBSPOT\_DEFINED | 4 | list+detail | dealname,dealstage,amount,closedate | 0 | Members see every deal they're associated with, under any label. Broad by design. |
| on | deal | P1 | USER\_DEFINED | your label's ID | list+detail | dealname,dealstage,amount,closedate | 0 | Members see only deals where they carry one of your own association labels (for example "Approver"). |
| on | deal | P2 | HUBSPOT\_DEFINED | 931 | list | dealname,dealstage,closedate | 0 | Members labeled "Billing Contact" on a company see that company's deals. **Check in your account:** confirm that 931 is Billing Contact (or use the ID your account shows for that label). |

Rules for a valid row (anything else is ignored without an error):

- The row is enabled, `type_id` is above 0, `category` is one of the three values, `permission` is one of the three values, and `properties` isn't empty.
- `P2` rows work only for `deal` or `ticket`, with `list` or `list+detail`. P2 doesn't support custom objects.
- **Warning for P2.** HubSpot adds the unlabeled and Primary company associations to contacts automatically. A P2 rule on `HUBSPOT_DEFINED` `279` (unlabeled) or `1` (Primary) would show a company's deals or tickets to nearly every contact at that company. The module ignores such a row unless `allow_all_associated` is `1`. Write `1` or `0`, never `true` or `false`. Use a specific label instead, such as Billing Contact or one of your own.
- **Changes take a few seconds to apply everywhere.** After you publish a change that removes access (you turn a rule off, narrow it, or set `allow_all_associated` to `0`), a member may still see the old records for a few seconds, sometimes on one page load and not the next. This is known HubSpot caching behaviour. The module reads only the published table, never your unpublished edits.
- **Direction matters.** `type_id` must be the contact to object ID. An ID that belongs to a different pair of objects returns nothing, with no error, so members just see an empty list.
- Each page reads up to 10 valid rules for the objects it uses. If more match, the affected card or list shows the partial results note. Rules for objects a page doesn't use don't count toward its 10.
- Keep the table under 200 rows. At 200 or more, every rule-driven card shows the partial results note.

Finding a type ID: the developer docs list HubSpot's defaults (contact to company 1, contact to deal 4, contact to ticket 15) at [https://developers.hubspot.com/docs/api-reference/latest/crm/associations/associate-records/guide](https://developers.hubspot.com/docs/api-reference/latest/crm/associations/associate-records/guide) . IDs for your own labels come from HubSpot's associations labels API. If you cannot find an ID in the UI, email [info@allgusto.com](mailto:info@allgusto.com).

### Publish the table

1. Open the table and click **Publish** in the top right.
2. In the dialog box, click **Publish**.

New tables start as drafts, and saving a change doesn't reach live pages until you publish again. If a live page still shows old data after publishing, republish the page. Source: [https://knowledge.hubspot.com/website-and-landing-pages/create-and-hubdb-tables](https://knowledge.hubspot.com/website-and-landing-pages/create-and-hubdb-tables)

## 7. Create the portal pages

1. Create these pages (paths are suggestions): - `/portal` from the data pack's member dashboard template. - `/portal/tickets` and `/portal/records` (the deals list; members see "Projects") from the data pack's member records list template (the theme has no records template). In each page's Member portal module, set **Records to show** to **Tickets** or **Deals**. - `/portal/tickets/view` and `/portal/projects/view` from the member record detail template. Set **Record type** to match.
2. Connect the pages: - On the dashboard and records pages, set **Detail page path** to the matching detail page (for example `/portal/tickets/view`). Links appear only for records the member may open. - On each detail page, set **Back link path** to its list page. - On the dashboard, the **Records page path (for 'See all')** defaults to `/portal/records`, the deals list created in step 1. If your deals list lives elsewhere, change it; clear it to hide the link. The **See all** link appears only when the member reaches deals through more than one group of companies (company rules, section 8); with one group every deal is already on the card, so there's no link. - The 404 page's **Go to your portal** button links to `/portal`. If your dashboard lives somewhere else, change it.
3. For each page, open **Settings**, click **Audience Access**, select **Access group membership required**, and select your access group. If more than ten registration emails will go out when you publish, tick the checkbox that appears. Then publish. Source: [https://knowledge.hubspot.com/website-pages/require-member-registration-to-access-private-content](https://knowledge.hubspot.com/website-pages/require-member-registration-to-access-private-content)
4. Create a navigation menu with your portal pages (Settings \> Content \> Navigation menus) and select it in the global header's **Member menu** field. Members see it only when signed in. Use **at most 6 top-level items**: on phones the menu becomes one row that scrolls sideways, and items past the sixth are easy to miss.

### Theme-only member pages (no data pack needed)

- **Resources** (`/portal/resources`, template *Gatehouse - member resources page (private pages only)*): in the page editor, open **Resource list** and add one entry per file or link: title, one-line description, a file from File manager or a URL, optional **File details** (type and size, e.g. "PDF, 1.2 MB", read out with the link) and an optional icon. An entry without a link shows its title as text. Only web (`https://`, `http://`), email (`mailto:`) and site links (`/…`, `#…`) are kept; anything else, such as a `javascript:` link, is removed. Links that open in a new tab say so to screen readers. The list shows only to signed-in members, wherever you place it.
- **The files themselves are not protected.** The members-only page hides the *list*, not the files: every File manager file has a public URL that anyone with the link can open, and by default search engines can index it (HubSpot: "files uploaded to the files tool are hosted on a public file URL and indexed by search engines"). Set each file's visibility to **Public - noindex**, and don't put confidential or per-member files here: HubSpot's *Private* files need a signed link and can't be listed on a page, and per-member documents belong on the member's CRM record (the data pack), not in the theme.
- **Your details** (`/portal/profile`, template *Gatehouse - member profile / request a change page (private pages only)*): a form page where members ask for a change. The theme shows no contact values on this page.
- **What actually happens when someone submits.** Every field on a HubSpot form is a contact property, and a submission isn't tied to the member's sign-in. HubSpot writes the submitted values onto whichever contact owns the email typed into the form, replacing what was there (or creates a new contact for a new email). The form's ID is public, so anyone can submit it with anyone's email. *Always create contacts for new email addresses* (below) only changes what happens for a new email or a cookie mismatch: typing an existing member's email still writes to that member's record. So keep the form to **Email plus one dedicated property** and nothing else:
    - create one contact property just for this, such as **Portal change request** (multi-line text), and a form with **Email** and **Portal change request** only. Don't add first name, last name, phone, job title or any other live field: a submission would overwrite them on the contact that owns the typed email;
    - a submission overwrites **Portal change request** on that contact, replacing any earlier request. It can be someone else's contact if a visitor typed someone else's email;
    - turn on the form's notification email (or a workflow) so your team sees each request;
    - in the page editor, open **Update details form** and pick that form (signed-out visitors never see it; the slot shows in the editor so you can set it);
    - treat every request as unconfirmed: anyone can type a member's email. Before changing anything, your team confirms the request with the member by writing to the email address **already on their record** (not a reply-to or any address given in the request), and makes the change by hand only after the member confirms;
    - keep the form's thank-you message plain text: **no personalization tokens** (such as a first name or email). On a shared or cookie-mismatched browser a token can show another person's details.
- **Turn off pre-population.** HubSpot fills form fields from the browser's tracking cookie, not from the member's sign-in, so on a shared computer the next person can see the previous visitor's details. HubSpot turns this on by default for new forms, and the theme can't turn it off. Do all of these:
    - account-wide: **Settings \> Marketing \> Forms**, then turn on **Disable form field pre-population** (HubSpot's account-level switch) (**check in your account:** exact menu path);
    - on the form: turn on **Always create contacts for new email addresses** (HubSpot: this also turns off pre-population and stops a cookie being re-linked to another contact), turn **off** *Pre-populate fields with known values*, and turn **on** *Add link to reset the form* ("Not you?") (HubSpot: [https://knowledge.hubspot.com/forms/form-fields-pre-populated-with-your-own-or-someone-else-s-information](https://knowledge.hubspot.com/forms/form-fields-pre-populated-with-your-own-or-someone-else-s-information)).
- All Gusto tests this page by signing in as a test member and checking that the form shows, has exactly Email plus one change-request field with labels, and starts empty (no pre-filled values). Run the same check yourself in section 9: open the page signed in as a test member and confirm no field is pre-filled.
- Give both pages the same **Audience Access** (your access group) as the other portal pages and add them to the member menu if you want (at most 6 items).
- **Access denied:** a visitor who isn't allowed to view a private page, signed in or not, is sent to `/_hcms/mem/denied`. **Data-pack installs** assign `Gatehouse data pack - membership access denied` under **Settings \> Content \> Private Content** (memberships, the Pages templates), then set that template's **Support button** URL (section 4, step 9). The page copy does not assume the visitor is signed in and does not depend on the support link. **Marketplace installs** use HubSpot's default page: the theme cannot ship that template type, because marketplace validation rejects it as restricted. The default page shows a large "403" and "Sorry, you don't have access", and the HTTP status is **200**. Don't pick a 404 or 500 template for it.
- **No per-group sections.** Sections can switch on *signed in* versus *signed out* (the page intro does), not on which access group or list a member is in. HubSpot's documented `request_contact.list_memberships` is empty for members whose access comes from an access group rather than a list, so the theme cannot tell members apart by group.

Only use the data pack templates on members-only pages. On a public or password-protected page the module still shows a signed-in member only their own data, and shows nothing to signed-out visitors, but members-only pages are the supported setup.

### What each card needs

| Card or list | Shows when |
| --- | --- |
| Tickets | Always, for the member's own tickets. By default it hides stage `4` (Closed in HubSpot's default support pipeline). Change this in **Hide tickets in these stages**. The stage IDs `1` to `4` assume HubSpot's default support pipeline; use your pipeline's IDs if it differs. |
| Profile | Always, from the member's own contact record. |
| Company | **Show the company card** is on and an enabled `company` rule with `profile` permission exists. Only properties that are also in the rule's list are shown. |
| Deals (members see "Projects") | **Show the deals card** is on (it's off by default) and an enabled `deal` rule exists. Only columns that are also in the rule's list are shown. |
| Records list | Tickets: always. Deals or custom objects: only with an enabled rule. |
| Record detail | Tickets: the member's own. Deals or custom objects: only with a `list+detail` rule. |

**Stage label map.** Each card and list turns stage IDs into stage labels with its **Stage label map** field (one per line, `ID=Label`). The defaults match HubSpot's default pipelines. Find your stage IDs in Settings \> Objects \> \[object\] \> Pipelines (path from the module's help text). The ticket defaults (`1` to `4`) assume HubSpot's default support pipeline; if your tickets use another pipeline, change **Stage label map** and **Hide tickets in these stages** to its IDs.

**Stage label maps on detail pages.** The Record detail settings have their own **Stage label map** field, and each detail field has a **Show as** choice: **Plain text** or **Stage label**. A field shown as **Stage label** shows the label for the stage ID. The detail map defaults to HubSpot's default ticket pipeline, which suits ticket detail pages. On a deal detail page you must replace it: set **Show as** to **Stage label** for `dealstage` and paste your deal pipeline's `ID=Label` lines into the detail **Stage label map**.

**Dates and amounts.** Each column and detail field has a *Show as* choice:

- **Date** for date-and-time properties such as Create date, Last modified date, Close date (deals) and Close date (tickets). These print as *Oct 7, 2026* in your account's time zone (Settings \> Account defaults \> Report settings), so a ticket created at 10:46 pm New York time on Oct 8 shows Oct 8, not the UTC date Oct 9.
- **Date (date picker property)** for date-only properties, which HubSpot stores as midnight UTC. Don't use plain **Date** for them: it shows the day before in time zones west of UTC. In the page editor and preview, a note under the table names any column that looks set up wrong.
- **Amount** for money: *$24,000.00* in your account currency. If a deal rule allowlists `deal_currency_code`, each deal shows in its own currency.

Month names use HubSpot's default locale for the page; only English pages have been checked. The portal reads the raw value from HubSpot and formats it itself. It never reorders text that is already formatted, and a value it can't read (empty, text, or a date picker value that isn't midnight) leaves the cell empty rather than showing a guessed date. The defaults already use Date for the date columns and Amount for amount. A date property left on *Plain text* shows HubSpot's raw number (milliseconds), and an amount left on *Plain text* shows a bare number such as 24000, so pick Date or Amount for them. If a row's first column is empty, its link shows *Link text for an empty first column* (default *View details*). An empty value (a project with no close date) leaves the cell empty, and on phones the whole line is hidden instead of showing a bare label.

**Unmapped stages.** A stage ID with no line in **Stage label map** shows as the raw ID in a muted, dashed badge (for example `contractsent`). It's never left blank and never guessed from a similar ID, and a line with an empty label (`contractsent=`) counts as no line. In the page editor and in preview only, the module adds a note under the list or details naming each unmapped ID (the **Unmapped stage hint** field holds its text). Members never see that note.

**Generate the map instead of typing it.** All Gusto can produce the exact **Stage label map** text from HubSpot's pipelines API: one `ID=Label` line per stage, for every pipeline, in HubSpot's order, ready to paste into the field. Labels come out in sentence case by default ("Contract Sent" becomes "Contract sent"; words in capitals such as NDA are kept), the same style as the field defaults, or in HubSpot's own capitalisation on request. Archived stages aren't listed; a record still in one shows its raw ID. Email [info@allgusto.com](mailto:info@allgusto.com) to ask about this.

## 8. Know the rule limits (P1 rules per object on detail pages)

HubSpot allows each page 10 calls of each CRM data function. The Member portal module counts its calls and stops at 10 rather than showing a short list without saying so. Source for the limit: [https://developers.hubspot.com/docs/cms/reference/hubl/functions](https://developers.hubspot.com/docs/cms/reference/hubl/functions)

**The P1 rule limit (record detail pages).** When the module checks whether a member may open a record, it tries the P1 rules for that object one by one, in table order, before any P2 rule. Only rules with `list+detail` permission count; `list`-only rules are skipped. On ticket pages the module first spends 1 call checking the member's own tickets. A P2 check takes 3 calls when the member and the record share one company, plus 1 for each extra shared company it has to check, and fetching the record takes 1 more. With too many P1 rules ahead of a P2 rule, the page runs out of calls, and a member who should see the record through the company (P2) gets the 404 page. It never shows a partial or wrong record.

| Object | Most `list+detail` P1 rules, with P2 rules | Without P2 rules |
| --- | --- | --- |
| Deals (and custom objects) | 6 | 9 |
| Tickets | 5 | 8 |

The P2 numbers assume the record shares one company with the member and the first P2 rule grants access; each extra shared company, or a P2 rule ahead that doesn't grant, lowers the limit by at least 1. Stay under the limit with room to spare.

If you hit it:

1. Turn off P1 rules you don't need for that object, or merge them. For example, one `HUBSPOT_DEFINED` `4` rule replaces several deal label rules, but it's broader: every associated deal becomes visible.
2. Put the P1 rules that grant the most access first in the table. A record allowed by an early rule needs fewer calls.
3. Move access that really runs through the company into a P2 rule rather than several P1 label rules.
4. Publish the table, then test as a member who should only see the record through the company.

Other limits:

- Each page reads up to 10 matching rules. Extra rules for the page's objects show the partial results note.
- HubSpot returns at most 100 records per call. A company with more than 100 matching records shows a note in the list, and records past 100 in one company can't be reached by paging.
- A member labeled on more than 100 companies through one P2 rule gets the partial note on lists, and detail pages fail closed (404).
- The dashboard deals card shows the first group of P2 companies only and adds a **See all** link to the records page.
- Records list paging goes up to page 999, and no further than 10,000 records deep (for example page 400 at 25 rows).
- A record reachable through two rules is listed once per page, but it can appear on two different pages. A page can show more rows than **Maximum records to show** when several rules add records.

## 9. Test as a member

1. Create a test contact with an inbox you can read and add it to the access group. HubSpot sends a registration email.
2. Open the email in a normal browser and set a password. Registration needs JavaScript, so use a normal browser.
3. In a private browser window, open `/portal`. Signed out, you should be sent to your sign-in page.
4. Sign in. Check that: - The tickets card shows the test contact's open tickets and none from other contacts. - The profile card shows the test contact's details. - The company card follows the company rule (turn the rule off, publish, reload: the card disappears). - Deals appear only after you add an enabled deal rule and publish.
5. Open a record, then change the `?id=` in the address bar to another contact's record, a random number and `abc`. Each one should show your 404 page.
6. Sign in as a second test contact at another company and repeat. Neither should see the other's records.
7. Click **Sign out** in the header and confirm the portal pages send you back to sign in.

## 10. Troubleshooting

| What you see | Likely cause and fix |
| --- | --- |
| Sign-in or password pages look like HubSpot's defaults | Pick Gatehouse's templates on the **Pages** tab of **Content \> Private Content** for the right domain. |
| Private content settings don't apply | The site is on a default HubSpot domain. Connect your own domain. |
| A member sees "Sign in to continue" after signing in | The page isn't set to **Access group membership required**, the member isn't in the access group, or they haven't finished registering. |
| No registration or reset email | Check the spam folder. Each contact gets at most five membership emails a day; the limit resets at 12:00 AM UTC. |
| Deals card or list is empty | **Show the deals card** is off, there is no enabled deal rule, the rule has no `properties`, the `type_id` is for the wrong pair of objects, or the table isn't published. |
| Company card is missing | The `company` / `profile` rule is off or missing. That is how you hide it on purpose. |
| A column is missing | That property isn't in the matching rule's `properties` list. Columns no rule allows are left out. |
| A note says not everything could be loaded | The page ran out of data calls or matched more than 10 rules. Reduce rules for that object, lower **Maximum records to show**, or split lists across pages. |
| "This page isn't set up correctly" | A second data module is on the page. Use the data pack templates as they are. |
| A record link opens the 404 page | Expected for records the member can't open. If they should see it: the rule needs `list+detail`, the detail page's **Record type** must match, and check the P1 rule limit (section 8). |
| HubSpot's plain 404 page appears | Select Gatehouse's 404 page under **Content \> Pages \> System Pages**. |
| Status shows a number or a muted ID on a detail page | A muted, dashed badge: that stage ID has no line in **Stage label map** (the editor and preview name it). Plain text: the field's **Show as** isn't **Stage label**. Add `ID=Label` for your pipeline, or generate the map (section 7, "Generate the map instead of typing it"). |
| Rule changes don't show up | Publish the table. If the live page is still old, republish the page. |
| Counts end in "+" | Normal. The exact total is known only when one source fills the list. |

## 11. Field guidance (longer notes behind the editor help text)

The editor shows one short help line per field. Here are the details behind them.

**Partial results note**. HubSpot allows each page 10 calls of each CRM data function. When the Member portal module reaches that limit, it shows this note instead of quietly showing fewer records. If members see it often:

- Use paging: lower **Maximum records to show** on lists.
- Move some lists to another page.
- Reduce the number of enabled rules for the objects that page uses.

A typical dashboard uses 2 contact lookups, 1 rules table read, 1 call for tickets, 1 per enabled deal rule and 1 for the company rule.

**Configuration error**. The module's first call reads the signed-in member's own contact record. If that comes back empty, usually because a second data module on the page used up the calls, the module shows this message and stops. Fix it by using the data pack templates as they are, with one Member portal module per page.

**Access rules table**. The default is `ag_portal_rules`. With no enabled rules, members see only their own tickets. For P2 rules, use a specific contact-to-company label (for example Billing Contact or your own label), never HubSpot's unlabeled (279) or Primary (1) types unless the row sets `allow_all_associated` to 1. With P2 rules, keep `list+detail` P1 rules to at most 6 for deals and 5 for tickets (section 8). See section 6 for the columns.

**Tickets card.** With stages hidden, the card fetches up to 100 tickets and hides the listed stages afterwards. The count then shows "N+" when there may be more, and the "more tickets" note appears. Without hidden stages the count is HubSpot's exact total.

**Records "more" note**. Appears only for access through a company (P2) when one company in the current page's group has more than 100 matching records. Records past 100 in one company can't be reached by paging.

**Deals card and list.** Deals appear only through an enabled deal rule, and only properties in that rule's `properties` list are fetched or shown. Columns no rule allows are left out. When access through companies spans more than one group, the dashboard shows the first group and links to the records page.

**Company card.** Shown only when an enabled `company` rule with `profile` permission exists (the default rule uses the member's primary company). Only properties that are both in the card's fields and in the rule's list appear.

**Property names.** Use internal names from Settings \> Properties. Letters, numbers and underscores only; anything else is removed.

**Paths** (detail page, records page, back link). Use site-relative paths that start with `/`, for example `/portal/tickets/view`. Full URLs aren't accepted. Use members-only pages.

**Maximum records to show.** 1 to 100. HubSpot returns at most 100 records per call.

**Custom objects.** HubL can read custom objects only on Content Hub Enterprise, and they show only with an enabled rule whose `object` is `custom:<key>`. P2 rules don't support custom objects. Leave the option off on Professional.

## Support

Questions about Gatehouse: [info@allgusto.com](mailto:info@allgusto.com). Support is by email.

© 2026 All Gusto, LLC

- [Home](https://allgusto.com/)
- [About](https://allgusto.com/about)
- [Blog](https://allgusto.com/blog)
- [Contact](https://allgusto.com/contact-us)
- [Privacy](https://allgusto.com/privacy)
- [Terms](https://allgusto.com/terms)