Skip to content
Beta This feature is in beta and may change — contact OnePageCRM support to enable it.

Extension points

Custom Buttons

Add buttons to OnePageCRM contact and deal menus that open your app at the right record, using URL template variables.

Maintained by the OnePageCRM engineering team · Last updated Sep 1, 2026

Custom Buttons let you add your own links to the 3-dots menu on contact and deal views. Each button opens a URL you define, with template variables resolved from the current record — so one click lands the user in your app, on the right customer.

Use it to:

  • Deep-link into your app preloaded with the right context (“Open in Acme” → your customer page for that contact).
  • Trigger an external workflow next to the record it relates to (create an invoice, start a call, open a booking form).
  • Bridge to internal tools that key off an email, phone number, or External ID.

Custom Buttons is currently in beta. Contact OnePageCRM support for enablement if the Custom buttons tab is not visible under Settings.

Set it up

Buttons are configured in the OnePageCRM web app — there’s no public API for managing them.

  1. Go to Settings → Custom buttons (fourth tab, beside Custom fields), or open app.onepagecrm.com/custom_buttons directly.
  2. Click Add, complete the fields below, and save — creating and editing happen on a single page.
  3. Owner or admin access is required; the tab is not shown to other users.
  4. Enabled buttons appear in the 3-dots menu for all account users.

Button fields

FieldRequiredNotes
NameyesThe label shown in the menu.
URL templateyesMust start with http://, https://, or a variable that supplies the URL (e.g. [contact.twitter]). May contain template variables.
Typeyescontact or deal — which 3-dots menu the button appears in, shown as a Contact/Deal radio pair. Add two buttons to cover both.
IconnoOne of default, call, mail, money, profile, tool.
EnabledToggle a button off without deleting it.

If the URL field has content, changing the type asks for confirmation, then clears it.

You can create up to 25 buttons per type (25 for contacts, 25 for deals). The limit is also enforced when switching an existing button’s type — the move is rejected if the target type already has 25 buttons. The disabled buttons also count towards the limit.

Template variables

Variables use the form [entity.field]. When a user clicks the button, each variable is replaced with the value from the current record.

Contact variables

VariableValue
[contact.firstname]First name
[contact.lastname]Last name
[contact.fullname]Full name
[contact.title]Title (Mr, Mrs, Ms)
[contact.jobtitle]Job title
[contact.email]First email address
[contact.phone]First phone number
[contact.twitter]X (Twitter) profile URL
[contact.id]OnePageCRM contact ID
[contact.address]First address, formatted as one line

[contact.twitter] reads the contact’s saved URL of type twitter and expands bare handles: onepagecrm and @onepagecrm both resolve to https://x.com/onepagecrm. An already-absolute URL passes through unchanged.

Organization variables

VariableValue
[organization.name]Company name
[organization.id]OnePageCRM company ID

Deal variables

VariableValue
[deal.name]Deal name
[deal.amount]Deal amount
[deal.totalamount]Total amount (amount × months)
[deal.id]OnePageCRM deal ID

Custom field variables

Every custom field is available as [contact.cf.<name>], [organization.cf.<name>], or [deal.cf.<name>], where <name> is the field’s name lowercased with spaces replaced by underscores. A field named Acme ID becomes:

[contact.cf.acme_id]

The Variable picker

The Variable picker sits below the URL field and inserts the placeholder at the cursor position, or replaces the selected text. Variables are grouped by button type: Contact buttons show Contact and Organization; Deal buttons show Deal, Contact and Organization. Account custom fields appear inside their group; section dividers are not offered.

Encoding

Values are percent-encoded, with one exception: a variable at the very start of the template whose value is an absolute http(s) URL is inserted raw, so the variable can supply the whole link.

[contact.twitter]

Text after it is kept, so you can append a path:

[contact.twitter, fallback=https://x.com]/with_replies

A leading variable that resolves to anything else is still encoded, which will produce a broken link.

Fallbacks

Provide a default with the fallback option:

[contact.cf.acme_id, fallback=unknown]

The fallback fires only when a variable resolves to no value at all — not an empty string. In practice it works for: custom field variables with no value, unset first/last name, title and job title fields, [contact.twitter] when no X URL is saved, organization.* variables when the contact has no company, an unset deal.name, and any variable whose linked record is missing. It does not fire for [contact.email], [contact.phone], or [contact.address] — those resolve to an empty string when absent. IDs and deal amounts always have a value, so a fallback on them never fires.

Example: open your app at the right customer

Say you sync customers with an External ID custom field named Acme ID. Add a contact button:

FieldValue
NameOpen in Acme
Typecontact
URL templatehttps://app.acme.com/customers/[contact.cf.acme_id]

A contact whose Acme ID is cus_8c1ab2 gets a menu item that opens:

https://app.acme.com/customers/cus_8c1ab2

No External ID yet? Key off email instead and resolve it on your side:

https://app.acme.com/lookup?email=[contact.email]&name=[contact.fullname]

Behavior notes

  • Buttons open in a new browser tab (target="_blank" with rel="noopener noreferrer").
  • Contact buttons resolve contact.* and organization.* variables. Deal buttons resolve deal.* plus the linked contact’s contact.* and organization.* variables.
  • If a button’s template resolves to a blank URL — for example a button pointing at [contact.twitter] for a contact with no X/Twitter URL recorded — the button is omitted from that record’s 3-dots menu rather than rendered as a dead link.
  • Variables are resolved when the record view loads. Your endpoint receives a plain GET from the user’s browser — there is no signature or auth handoff. Treat incoming parameters as hints and authenticate the user in your own app as usual.
  • Buttons are account-wide: every user sees enabled buttons, but only owners and admins can manage them.

See also

  • External ID — give every record a stable ID in your system, then link straight to it.