Skip to main content
Installing Vortex your application involves adding a snippet of code for each invitation flow wherever you want to render the widget. If you’re building a standalone implementation (i.e., not mounting the widget inside an existing modal), you’re responsible for providing the container markup into which the vortex component will render. In other words, create the HTML element where you want the widget to appear, then paste your widget code snippet. Although componentId and jwt are technically the only required parameters,scope is effectively required for most customers and there are other parameters detailed below that you will more than likely need to populate.
<VortexInvite
  componentId="ad968b65-f738-4b3b-957b-c3599773d09a"
  jwt=""
  scope=""
/>

widgetId

required An widget’s ID can be found on the Installation tab, in the code snippet in the Install Client step.
componentId="aa9ebe43-e565-4299-b2b9-5d01018506ac"

jwt

required Use the JWT generated per the instructions in the JSON Web Tokens section.

scope

required for most customers scope is the internal identifier of the grouping to which the invitation applies. Although some services have invitations that simply establish connections between users, like a social network, most other services, especially B2B services, have invitations that are specific to some type of grouping of users. For example, on Slack and Trello you get invited to a workspace. On Airbnb you get invited to a trip. And if you play fantasy sports, you get invited to a league. If Slack were using Vortex, scope would be the internal ID of the workspace.
scope="f1234567-89ab-cdef-0123-456789abcdef"
These groupings are also what defines the uniquess of an invitation. For example, [email protected] could be invited to three different Slack workspaces. If your service doesn’t have any groupings of users, you do not need to use the scope parameter.

scopeType

Your service may have multiple groupings. For example, Trello has workspaces, but also has the concept of boards that are owned by a workspace. People can be invited to a workspace, but they can also be invited directly to a board. If Trello were using Vortex, scope would represent a workspace ID for invitations to a workspace, or a board ID for invitations to a board. Unless Trello’s workspace and board IDs were of a format such that it was inherently obvious which type of entity they applied to, Trello would use the scopeType parameter, setting it to either “workspace” or “board” as appropriate.
scopeType="workspace"

userEmailsInGroup

If the number of members in a group (as defined by invitationScope) isn’t large, you can send them all via this parameter so that Vortex can validate that the person being invited isn’t already a member. If the number of members is too large to pass all of them in here, use the subsequent emailValidationFunction parameter instead.
userEmailsInGrouping={["[email protected]", "[email protected]", "[email protected]"]}

emailValidationFunction

For large groupings, where sending all members in userEmailsInGrouping isn’t practical, you can provide your own validation function. For example:
const emailValidationFunction = (email: string): boolean | null => {
  return email.includes('@');
};

or

const emailValidationFunction = async (emails: string[]): Promise<{ 
    isValid: boolean, 
    invalidEmails?: string[], 
    errorMessage?: string }> => {
  const result = await someAsyncCheck(email);
  return result;
};

and then

<VortexInvite
          componentId={widgetID}
          isLoading={jwtLoading}
          jwt={jwt}
          emailValidationFunction={emailValidationFunction}
/>
If you return the optional errorMessage parameter it will be displayed in the widget UI to the user.

templateVariables

Template variables allow you to pass in information to be displayed in your invitation emails. For example, you might want to refer to the name of the inviter, the name of a workspace, or even the current number of members already in the workspace. For every variable added to your templates, you’ll need to pass in the values on this parameter.
templateVariables={{ inviter_name:"John Doe", workspace_name: "Acme", member_count: "26" }}

metadata

The metadata field can be used to pass information, in JSON format, along with the invitation that will then be returned to you when you fetch the invitation details during the acceptance flow. The basic information about the inviter and invitee is automatically included, but you may want to capture additional information. For example, say you have an Invite button that is accessible from multiple pages on your site. You might want to include the name of the referring page in the metadata in support of your analytics. When sending data via this method, you are responsible for verifying the integrity of the data when it is returned to you. In deciding what information to send, also consider that the information is being sent in plain text.

googleAppClientId

If your invitation flow includes the Google contact import, then you’ll need to pass in the Client ID for your Google app. See instructions for creating your app.

googleAppApiKey

If your invitation flow includes the Google contact import, then you’ll need to pass in the API key for your Google app. See instructions for creating your app.

onInvite

When passing an onInvite function, you are able to capture the invitations created by your users. For example, if your service treats invitees as pending members for the purposes of email notifications and other functionality, you would want to know the email addresses and custom-field values for the invitees so that you could add them to your users table. If your service doesn’t care at all about invitees until they’ve accepted an invitation, then you don’t need to worry about this. This data format varies based on your widget configuration.
import type { OnInviteData } from '@teamvortexsoftware/vortex-react';

const onInvite = (invitations: Invitation[]) => {
	console.log("Invitations:", data);
	processData(data);
}

<VortexInvite
          componentId={widgetID}
          isLoading={jwtLoading}
          jwt={jwt}
          onInvite={onInvite}
/>
Here is an example of the data passed to your registered onInvite function:
[{
acceptedAt: null,
​​	accountId: "43310069-8b56-4294-a0a6-79d910404d39",
​​	attributes: null,
​​	clickThroughs: 0,
​​	configurationAttributes: {
​​​		emails: {
​​​​			role: "email",
​​​​			type: "email",
​​​​			value: "[email protected]"
		}
	},
​​	createdAt: "2025-08-25T18:55:50.551Z",
​​	deactivated: false,
​​	deliveryCount: 0,
​​	deliveryTypes: [
​​​		"email"
	],
	deploymentId: "8a95daf5-76ec-438c-ae34-b91b61d98f21",
​​	environmentId: "df3d007d-2716-41fc-ad32-5477230847b1",
​​	firstClickThrough: null,
​​	foreignCreatorId: "e6453ae2-6ca8-44f4-b0b5-b72f1f642e5e",
​​	id: "65b3c403-c03a-4baa-8eaa-20a40af31dd4",
​​	invitationType: "single_use",
​​	lastClickThrough: null,
​​	modifiedAt: null,
​​	passThrough: null,
​​	projectId: "35957e27-fdcd-482f-8462-2cbe9ab6ca77",
​​	senderIdentifier: "[email protected]",
​​	senderIdentifierType: "email",
​​	source: "email",
​​	status: "queued",
​​	templateVariables: {
​​​	    companyName: "AcmeTasks",
​​​		groupMemberCount: "1",
​	​​	groupName: "xxcbn",
​​​		inviterName: "yngwie User"
	},
​​	views: 0,
​​	widgetConfigurationId: "baf28550-8dcc-451e-9ec2-d17888a79fb6"
}, ...]

onEvent

When passing an onEvent function, you are able to capture events generated by your users via the invitation widget. For example, you might want to know when the user clicks on the “Invite” button in the invitation form you have during your onboarding process, so that you can advance the user to the next step in the onboarding flow as a result of that action. See the Vortex Events section for a complete list of events.
// see Vortex Events section for event type definitions
const AppEvent = widgetRender | widgetSubmit | widgetSubmitEmailFocus | widgetSubmitEmailBlur | widgetEmailValidation | widgetShareLinkClick | widgetSubmitValidationError | widgetSubmitError | widgetError;

const onEvent = (event: AppEvent) => {
	console.log("Event:", event);
	processEvent(event);
};

<VortexInvite
          componentId={widgetID}
          isLoading={jwtLoading}
          jwt={jwt}
          onEvent={onEvent}
/>

isLoading

This prop is used to indicate that the invitation widget should not attempt to render yet, and instead render a loading placeholder. This can be used when all of the other props aren’t quite ready. For example:
export const vortexHarness = ({ parentIsLoading: boolean }) => {
const (jwt, jwtIsLoading) = useJwtHook();
const (isLoading, setIsLoading) = useState(parentIsLoading || jwtIsLoading);

useEffect(() => {
	setIsLoading(parentIsLoading || jwtIsLoading);
}, [parentIsLoading, jwtIsLoading]);

return (
<VortexInvite
          componentId={widgetID}
          isLoading={isLoading}
          jwt={jwt}
          onSubmit={onSubmit}
/>
);
}