# Client portal

The client portal (`portal-v1`) lets donors sign in with BankID and see
their gifts, change or cancel a monthly donation, switch payment method,
download receipts and keep their details up to date. It's a widget like
the [fundraising embeds](frontend.md#1-fundraising): embed it on your own
page, link to the hosted page, or frame the hosted page.

## What donors can do

| Area | What the signed-in donor can do |
| --- | --- |
| Subscriptions | See monthly gifts and other subscriptions. Change the amount, cancel, resume a cancelled one before it ends, switch payment method or update the card. |
| Orders | Browse past gifts and purchases, download receipts as PDF. |
| Profile | View and edit contact details. |
| Events and forms | See event registrations and submitted forms. |

What shows up depends on the account and the portal's settings. Without
the full client portal on the Octany plan, the portal only lets donors
manage the payment method on their subscriptions. Changing amounts and
cancelling can each be turned off per portal. Only donation subscriptions
can have their amount changed.

## Embed on your page

Recommended, and the option to use when you want to keep your own
header, menu and footer around the portal. Copy the embed code from the
portal in Octany admin:

```html
<div class="octany-portal-widget"></div>
<script
  type="module"
  src="https://give.octany.com/portal-v1/loader.js?api=https://app.octany.com/widget/1234&widget=01HXXXXXXXXXXXXXXXXXXXXXXX"
></script>
```

| Parameter | Required | Description |
| --- | --- | --- |
| `api` | Yes | `https://app.octany.com/widget/{account}`, where `{account}` is your account ID. |
| `widget` | Yes | The portal's widget ID, 26 characters. |
| `lang` | No | Two-letter language code, e.g. `sv` or `en`. Defaults to the portal's language. |

Not an iframe: the portal renders into the container inside a Shadow
DOM, so page styles and portal styles don't affect each other. It fills
the container's width.

On WordPress: `[octany type="portal-v1" account="1234" widget="01HXXXXXXXXXXXXXXXXXXXXXXX"]`
or the Octany widget block. See [wordpress.md](wordpress.md).

## Hosted page

Every portal has its own full-screen page on Octany (the preview link in
Octany admin):

```
https://app.octany.com/widget/{account}/{widget}/portal
```

**Payment reminder emails link here**, not to the page where you embedded
the portal. The link opens the portal on that subscription's payment
method without BankID, with a session that can only change the payment
method on that one subscription. Style the portal (logo, colors, hero
image) even if you only embed it.

## iframe

The hosted page can be framed. Octany doesn't block framing, and sign-in
is kept in the page rather than in cookies, so blocked third-party
cookies are not a problem.

```html
<iframe
  src="https://app.octany.com/widget/1234/01HXXXXXXXXXXXXXXXXXXXXXXX/portal"
  title="My giving"
  style="display:block; width:100%; height:85vh; border:0"
></iframe>
```

- **You set the height.** The portal doesn't report its height to the
  parent page. Use something close to the viewport, like `85vh`, since
  the portal scrolls inside itself.
- **Links leave the frame.** The "Back to" button and the logout
  redirect navigate the whole window.
- **Test BankID on a phone.** Opening the BankID app from inside an
  iframe can behave differently in some mobile browsers.

Prefer embedding when you can.

## Keeping your header

Both the embed and the iframe keep your header, menu and footer around
the portal. Plan for:

- **One screen tall.** The portal is always as tall as the browser
  window. Once signed in, its content scrolls inside the portal, so with
  your header above it the page scrolls to the portal and the portal then
  scrolls on its own. A dedicated page with your header and the portal
  works best; avoid other content below it.
- **Its own header.** The portal shows the account logo, a
  "Back to {your site}" button and "Log out". Leave **Website URL** empty
  to drop the back button. The logo comes from the account's appearance
  settings and shows whenever one is set.
- **The URL hash.** Portal pages live in the hash of your page's URL
  (`#/home`, `#/orders`, …). Don't use it on a page that uses the hash
  for its own routing, and use one portal per page.

## Sign-in

Donors sign in with **BankID** (QR code, or the BankID app on the same
device) as a contact that already exists in Octany. There is no sign-up.

Contacts without a personnummer can't be matched by BankID. With
**Allow email or SMS activation for contacts without personnummer**
turned on, they verify with a code sent to their email or phone, then
confirm with BankID, which adds the personnummer to the contact. After
that they sign in with BankID.

- Email codes are valid for 15 minutes, SMS codes for 10.
- If several contacts share an email or phone, the donor picks which one
  to manage after entering the code.
- A contact that already has a personnummer is always asked to use
  BankID.

## Sessions

The session token is kept in `sessionStorage` on your page's domain, one
per portal. No cookies.

- A reload keeps the donor signed in; a new tab or window asks again.
- Closing the tab signs them out.
- Sessions last at most 30 days and end after 14 days without activity
  by default.
- **Log out** ends the session and, if a logout URL is set, sends the
  whole window there.

Portal sign-in is separate from any login on your own site.

## Settings

| Setting | What it does |
| --- | --- |
| Non-profit portal | Donation wording instead of purchase wording. On by default. |
| Hero image | Image across the top of the portal and the sign-in screen. |
| Colors | Background, titles, tab background and text, active tab background and text. |
| Allow email or SMS activation for contacts without personnummer | See Sign-in. |
| Allow contacts to change subscription amounts | Change-amount action on donation subscriptions. |
| Allow contacts to cancel subscriptions | Cancel action. |
| Website URL | "Back to {site}" button in the portal header. Empty hides it. |
| Logout URL | Where the window goes after logout. Empty stays on the sign-in screen. Use `https://`. |

## Requirements

- Donors need BankID and must already exist as contacts in Octany.
- A page that doesn't use the URL hash for its own routing, with one
  portal on it.
- Room for a full-height portal, ideally on a page of its own.
- If your site sends a Content Security Policy, allow:
  - `script-src https://give.octany.com https://js.stripe.com`
  - `connect-src https://app.octany.com https://api.stripe.com`
  - `img-src https://octany-public.s3.eu-west-1.amazonaws.com data:` (logo, hero image, BankID QR code)
  - `frame-src https://js.stripe.com https://hooks.stripe.com https://*.britepaymentgroup.com` (card updates, autogiro bank selection)
- Style the hosted page even when you embed, since payment reminder
  emails link there.
