When a new visitor first shares some of their contact information with your site, they're added to your Contact List. Once that happens, their details are available through the Contacts API.
Some examples of how a person can become a contact are:
Learn more about how you can manage your contact list.
With the Contacts APIs, you can:
To use the Contacts API,
import { contacts }
from wix-crm-backend:
import { contacts } from "wix-crm-backend";
It's important to note this point before coding:
If a contact is also a site member or site contributor, the contact cannot be deleted. The related site member or site contributor must first be deleted, and then the contact can also be deleted.
Extended fields: Additional properties that store additional contact information.
A contact's extended field data is available
in the contact object under info.extendedFields
.
Extended field definitions can be created and managed with
the extended field functions such as
findOrCreateExtendedField()
.
There are 2 types of extended fields:
Labels: Tags that help site contributors categorize and organize their contacts.
Labels can be system-defined or user-defined.
You can manage a site's labels with
the label functions such as
findOrCreateLabel()
.
A contact's assigned labels are available
in the contact object under info.labelKeys
.
Basic contact information is stored in the contact's default properties. This includes information such as contact name, company, phone numbers, addresses, and email addresses. Additional properties are stored in extended fields.
There are 2 types of extended fields:
When you create, update, or retrieve contacts,
you'll find extended field data in the contact object under info.extendedFields
.
Most system fields are read-only, while all custom fields can be written to.
Labels allow site collaborators to segment contacts in their Contact List. Contact labels are useful for targeting specific audiences for email campaigns or bulk actions.
For more information on how labels are used, see Creating Contact Labels.
When a contact interacts with your site,
the interaction is captured in lastActivity
in the contact object.
The table below shows the possible activityType
values
and describes the interactions each activity type represents:
Activity Type | Description |
---|---|
GENERAL | Visited the site. |
CONTACT_CREATED | Became a new contact. |
MEMBER_LOGIN | Logged in. |
MEMBER_REGISTER | Requested site membership. |
MEMBER_STATUS_CHANGED | Was approved, blocked, or unblocked. |
FORM_SUBMITTED | Submitted a form. |
INBOX_FORM_SUBMITTED | Started a chat. |
INBOX_PAYMENT_REQUEST_PAID | Paid a payment request. |
INBOX_MESSAGE_TO_CUSTOMER | Received a message from a site contributor. |
INBOX_MESSAGE_FROM_CUSTOMER | Sent a new message to the site. |
NEWSLETTER_SUBSCRIPTION_FORM_SUBMITTED | Subscribed to a site newsletter. |
NEWSLETTER_SUBSCRIPTION_UNSUBSCRIBE | Unsubscribed from a site newsletter. |
ECOM_PURCHASE | Made a Wix Stores purchase. |
ECOM_CART_ABANDON | Abandoned their shopping cart. |
ECOM_CHECKOUT_BUYER | Checked out shopping cart and submitted buyer info (but didn’t complete purchase yet). |
BOOKINGS_APPOINTMENT | Booked an appointment. |
HOTELS_RESERVATION | Made a Wix Hotels reservation. |
HOTELS_PURCHASE | Paid for a Wix Hotels reservation. |
HOTELS_CONFIRMATION | Confirmed a Wix Hotels reservation. |
HOTELS_CANCEL | Canceled a Wix Hotels reservation. |
VIDEO_PURCHASE | Purchased a video. |
VIDEO_RENT | Rented a video. |
CASHIER_BUTTON_PURCHASE | Made a purchase with a pay button. |
ARENA_NEW_LEAD | Became a new Wix Marketplace lead. |
EVENTS_RSVP | Responded that they're attending an event. |
INVOICE_PAY | Paid an invoice. |
INVOICE_OVERDUE | Contact's invoice is now overdue. |
PRICE_QUOTE_ACCEPT | Accepted a price quote. |
PRICE_QUOTE_EXPIRE | Contact’s price quote has expired. |
RESTAURANTS_ORDER | Ordered food with Wix Restaurants. |
RESTAURANTS_RESERVATION | Made a Wix Restaurants reservation. |
SHOUTOUT_OPEN | Opened an email from the site. |
SHOUTOUT_CLICK | Clicked a link in an email from the site. |
CONTACT_MERGED | Merged with another contact. |
This article covers field support for filtering, sorting, and searching in the Contacts API, the Labels API, and the Extended Fields API.
The available options when calling
queryContacts()
have been divided into these 3 sections:
info.extendedFields
object.info.extendedFields
object.For information on the difference between system fields and custom fields, see Terminology.
The table below shows field support for filters, sorting, and free-text searching for the base set of contact properties. It doesn't include extended fields (those are covered in the sections below).
For a full description of the Contact
object, see
ContactsQueryResult
>
items
.
The table below shows field support for filters, sorting, and free-text searching for the Wix-defined extended fields (also known as system fields).
Note:
When working directly with the Contact
object in your code,
data in extended fields must be accessed
using bracket notation, like this:
info.extendedFields['{key}']
.
However, when querying or sorting,
extended field names are flattened with dot notation, like this:
ascending('info.extendedFields.{key}')
.
Extended Field | Supported Filters & Sorting | Supported Values |
---|---|---|
info.extendedFields.emailSubscriptions.deliverabilityStatus | eq() ,ne() ,hasSome() | "VALID" , "BOUNCED" , "SPAM_COMPLAINT" , "NOT_SET" , "INACTIVE" . |
info.extendedFields.emailSubscriptions.effectiveEmail | ascending() , descending() | |
info.extendedFields.emailSubscriptions.subscriptionStatus | eq() , ne() , hasSome() | "SUBSCRIBED" , "UNSUBSCRIBED" , "NOT_SET" , "PENDING" . |
info.extendedFields.members.membershipStatus | eq() , ne() , hasSome() | "APPROVED" , "DENIED" , "PENDING" , "INACTIVE" . |
Extended fields that are created by 3rd-party apps or site contributors are known as custom fields. You can add, remove, and change custom field names from the Contact List in the Dashboard.
The table below shows field support for filters, sorting, and free-text searching for custom fields.
Note:
When querying or sorting,
extended field names are flattened to a dot-separated string, like this:
'info.extendedFields.{key}'
.
For example, to query the custom.new-customer
extended field,
use this flattened field name:
'info.extendedFields.custom.new-customer'
.
Data Type/Format | Supported Filters & Sorting |
---|---|
String | eq() , ne() , hasSome() , startsWith() , ascending() , descending() |
Number | eq() , ne() , gt() , lt() , ge() , le() , between() , ascending() , descending() |
Date string in YYYY-MM-DD format | eq() , ne() , gt() , lt() , ge() , le() , between() , ascending() , descending() |
This section covers the available options when calling
queryLabels()
.
The table below shows field support for filters and sorting for the label object.
For a full description of the Label
object, see
LabelsQueryResult
>
items
.
Property | Supported Sorting |
---|---|
_createdDate | ascending() , descending() |
_updatedDate | ascending() , descending() |
displayName | ascending() , descending() |
This section covers the available options when calling
queryExtendedFields()
.
The table below shows field support for filters and sorting for the extended field object.
For a full description of the ExtendedField
object, see
ExtendedFieldsQueryResult
>
items
.
Property | Supported Sorting |
---|---|
_createdDate | ascending() , descending() |
_updatedDate | ascending() , descending() |
displayName | ascending() , descending() |
Appends contactInfo
to an existing contact or creates a new contact if it doesn't already exist.
The appendOrCreateContact()
function returns a Promise
that resolves to a contact ID and identity type when a contact is found or created.
When called, appendOrCreateContact()
accepts an object with contact information and follows the steps below.
When one of the conditions is met, this process ends and the specified
data is handled:
appendOrCreateContact()
reconciles with the member's associated contact.appendOrCreateContact()
tries to reconcile any specified email addresses and/or phone numbers with an existing contact.appendOrCreateContact()
reconciles with the new contact.appendOrCreateContact()
tries to reconcile the visitor's session identity with an existing contact.appendOrCreateContact()
does not require member authentication,
so it does not return the entire contact object.
The contact's data can be retrieved with
getContact()
.
If an existing contact is found:
emails
, addresses
, phones
, and labelKeys
.Note:
If the reconciled contact belongs to a member
who isn't currently logged in to the site,
identityType
is returned as "NOT_AUTHENTICATED_MEMBER"
.
In that case, no contact properties are modified.
If a new contact is created:
function appendOrCreateContact(
contactInfo: ContactInfo,
): Promise<ContactIdentification>;
Contact's information. To reconcile with an existing contact, a phone or email must be provided, or the current session identity must be attached to a contact or member.
If no existing contact can be found, a new contact is created with the specified information.
import { Permissions, webMethod } from "wix-web-module";
import { contacts } from "wix-crm-backend";
export const myAppendOrCreateContactFunction = webMethod(
Permissions.Anyone,
() => {
const contactInfo = {
name: {
first: "Ari",
last: "Thereyet",
},
};
return contacts
.appendOrCreateContact(contactInfo)
.then((resolvedContact) => {
return resolvedContact;
})
.catch((error) => {
console.error(error);
});
},
);
/* Promise resolves to:
* {
* "contactId": "a52852d7-e0d6-484b-93fe-bffdb670f08f",
* "identityType": "CONTACT"
* }
*/
Creates a new contact.
The createContact()
function returns a Promise
that resolves to the new contact when it is created.
Note:
This function replaces the deprecated
wixCrmBackend.createContact()
.
The deprecated function will continue to work, but it will not receive updates.
To keep any existing code compatible with future changes, see the
migration instructions.
The contactInfo
parameter object must include a name, phone number, or email address.
If all 3 of these parameters are missing,
the contact won't be created.
By default,
if the call contains an email already in use by another contact,
the new contact won't be created.
To override this behavior,
set allowDuplicates
in the options
object to true
.
Note:
Only visitors with
Manage Contacts permissions
can create contacts.
You can override the permissions by setting the suppressAuth
option to true
.
function createContact(
contactInfo: ContactInfo,
options: Options,
): Promise<Contact>;
Contact info.
Contact creation options.
import { Permissions, webMethod } from "wix-web-module";
import { contacts } from "wix-crm-backend";
export const myCreateContactFunction = webMethod(Permissions.Anyone, () => {
const contactInfo = {
name: {
first: "Ari",
last: "Thereyet",
},
};
const options = {
allowDuplicates: false,
suppressAuth: false,
};
return contacts
.createContact(contactInfo, options)
.then((contact) => {
return contact;
})
.catch((error) => {
console.error(error);
});
});
/* Promise resolves to:
* {
* "_id": "bbc44e99-4439-4a51-ac8c-77d6a9bb6243",
* "_createdDate": "2021-07-26T06:32:46.466Z",
* "_updatedDate": "2021-07-26T06:32:46.467Z",
* "revision": 0,
* "info": {
* "name": {
* "first": "Ari",
* "last": "Thereyet"
* },
* "extendedFields": {
* "contacts.displayByFirstName": "Ari Thereyet",
* "contacts.displayByLastName": "Thereyet Ari"
* }
* },
* "lastActivity": {
* "activityDate": "2021-07-26T06:32:46.466Z",
* "activityType": "CONTACT_CREATED"
* },
* "source": {
* "appId": "v4.createContact",
* "sourceType": "OTHER"
* }
* }
*/
Deletes a contact who is not a site member or contributor.
The deleteContact()
function returns a Promise
that resolves when the specified contact is deleted.
Note:
This function replaces the deprecated
wixCrmBackend.deleteContact()
.
The deprecated function will continue to work, but it will not receive updates.
To keep any existing code compatible with future changes, see the
migration instructions.
Deleting a contact permanently removes them from your Contact List.
If the contact is also a site member, the member must be deleted first, and then the contact can be deleted.
Note:
Only visitors with
Manage Contacts permissions
can delete contacts.
You can override the permissions by setting the suppressAuth
option to true
.
function deleteContact(contactId: string, options: AuthOptions): Promise<void>;
ID of the contact to delete.
Authorization options.
import { Permissions, webMethod } from "wix-web-module";
import { contacts } from "wix-crm-backend";
export const myDeleteContactFunction = webMethod(Permissions.Anyone, () => {
const contactId = "43fd5f9e-d7d4-4a31-8bfc-3bdc180cc40a";
const options = {
suppressAuth: false,
};
return contacts
.deleteContact(contactId, options)
.then(() => {
console.log("Contact deleted");
})
.catch((error) => {
console.error(error);
});
});
Deletes an extended field.
The deleteExtendedField()
function returns a Promise that resolves
when the specified extended field is deleted.
When an extended field is deleted, any contact data stored in the field is permanently deleted as well.
Note:
Only visitors with
Manage Contacts permissions
can delete extended fields.
You can override the permissions by setting the suppressAuth
option to true
.
function deleteExtendedField(key: string, options: AuthOptions): Promise<void>;
Extended field ID.
Authorization options.
import { Permissions, webMethod } from "wix-web-module";
import { contacts } from "wix-crm-backend";
export const myDeleteExtendedFieldFunction = webMethod(
Permissions.Anyone,
() => {
const fieldKey = "custom.event-name";
const options = {
suppressAuth: false,
};
return contacts
.deleteExtendedField(fieldKey, options)
.then(() => {
console.log("Extended field deleted");
})
.catch((error) => {
console.error(error);
});
},
);
Deletes a label from the site and removes it from contacts it applies to.
The deleteLabel()
function returns a Promise
that resolves when the specified label is deleted.
Note:
Only visitors with
Manage Contacts permissions
can delete labels.
You can override the permissions by setting the suppressAuth
option to true
.
function deleteLabel(key: string, options: AuthOptions): Promise<void>;
Label key to delete.
Authorization options.
import { Permissions, webMethod } from "wix-web-module";
import { contacts } from "wix-crm-backend";
export const myDeleteLabelFunction = webMethod(Permissions.Anyone, () => {
const labelKey = "custom.new-lead";
const options = {
suppressAuth: false,
};
return contacts
.deleteLabel(labelKey, options)
.then(() => {
console.log("Label deleted");
})
.catch((error) => {
console.error(error);
});
});
Retrieves a custom field with a given name, or creates one if it doesn't exist.
The findOrCreateExtendedField()
function returns a Promise
that resolves when the specified custom field is found or created.
Successful calls to findOrCreateExtendedField()
always return an
extended field,
which can be passed to subsequent function calls.
To find an existing extended field without potentially creating a new one, use
getExtendedField()
or
queryExtendedFields()
.
Note:
Only visitors with
Manage Contacts permissions
can find or create extended fields.
You can override the permissions by setting the suppressAuth
option to true
.
function findOrCreateExtendedField(
extendedFieldInfo: ExtendedFieldInfo,
options: AuthOptions,
): Promise<FoundOrCreatedExtendedField>;
Custom field to find or create.
Authorization options.
import { Permissions, webMethod } from "wix-web-module";
import { contacts } from "wix-crm-backend";
export const myFindOrCreateExtendedFieldFunction = webMethod(
Permissions.Anyone,
() => {
const extendedFieldInfo = {
displayName: "Last Contacted",
dataType: "DATE",
};
const options = {
suppressAuth: false,
};
return contacts
.findOrCreateExtendedField(extendedFieldInfo, options)
.then((extendedField) => {
return extendedField;
})
.catch((error) => {
console.error(error);
});
},
);
/*
* Promise that resolves to:
*
* {
* "extendedField": {
* "_createdDate": "2021-01-19T23:18:16.550Z",
* "_updatedDate": "2021-01-19T23:18:16.550Z"
* "namespace": "custom",
* "key": "custom.last-contacted",
* "displayName": "Last Contacted",
* "dataType": "DATE",
* "fieldType": "USER_DEFINED",
* },
* "newExtendedField": true
* }
*/
Retrieves a label with a given name, or creates one if it doesn't exist.
The findOrCreateLabel()
function returns a Promise
that resolves when the specified label is found or created.
Successful calls to findOrCreateLabel()
always return a label,
which can be passed to subsequent function calls.
To find an existing label without potentially creating a new one, use
getLabel()
or
queryLabels()
.
Note:
Only visitors with
Manage Contacts permissions
can find or create labels.
You can override the permissions by setting the suppressAuth
option to true
.
function findOrCreateLabel(
displayName: string,
options: AuthOptions,
): Promise<FoundOrCreatedLabel>;
Label display name to retrieve or create.
If an existing label is an exact match for the specified display name, the existing label is returned. If not, a new label is created and returned.
Authorization options.
import { Permissions, webMethod } from "wix-web-module";
import { contacts } from "wix-crm-backend";
export const myFindOrCreateLabelFunction = webMethod(Permissions.Anyone, () => {
const displayName = "Active Customer";
const options = {
suppressAuth: false,
};
return contacts
.findOrCreateLabel(displayName, options)
.then((label) => {
return label;
})
.catch((error) => {
console.error(error);
});
});
/*
* Promise resolves to:
*
* {
* "label": {
* "_createdDate": "2021-01-20T00:31:41.452Z",
* "_updatedDate": "2021-01-20T00:31:41.452Z"
* "namespace": "custom",
* "key": "custom.active-customer",
* "displayName": "Active Customer",
* "labelType": "USER_DEFINED"
* },
* "newLabel": true
* }
*/
Retrieves a contact.
The getContact()
function returns a Promise
that resolves when the contact is found.
When a source contact is merged
with a target contact, the source contact is deleted.
When calling getContact()
for a merged contact,
you can use the source or target contact ID.
In both cases, the target contact is returned.
This is supported only when calling getContact()
,
and only for merged contacts.
Deleted source contact IDs are not supported on any other function.
Notes:
wixCrmBackend.getContactById()
.
The deprecated function will continue to work, but it will not receive updates.
To keep any existing code compatible with future changes, see the
migration instructions.suppressAuth
option to true
.function getContact(contactId: string, options: AuthOptions): Promise<Contact>;
ID of the contact to retrieve.
Authorization options.
import { Permissions, webMethod } from "wix-web-module";
import { contacts } from "wix-crm-backend";
export const myGetContactFunction = webMethod(Permissions.Anyone, () => {
const contactId = "bc0ae72b-3285-485b-b0ad-c32c769a4daf";
const options = {
suppressAuth: false,
};
return contacts
.getContact(contactId, options)
.then((contact) => {
return contact;
})
.catch((error) => {
console.error(error);
});
});
/* Promise resolves to:
* {
* "_id": "bc0ae72b-3285-485b-b0ad-c32c769a4daf",
* "_createdDate": "2021-03-30T13:12:39.650Z",
* "_updatedDate": "2021-03-30T13:12:39.650Z",
* "revision": 0,
* "info": {
* "name": {
* "first": "Gene",
* "last": "Lopez"
* },
* "birthdate": "1981-11-02",
* "company": "Borer and Sons, Attorneys at Law",
* "jobTitle": "Senior Staff Attorney",
* "labelKeys": [
* "custom.white-glove-treatment",
* "contacts.contacted-me",
* "custom.new-lead"
* ],
* "locale": "en-us",
* "emails": [
* {
* "_id": "5bdcce4a-37c2-46ed-b49c-d562c6e3c4ce",
* "tag": "HOME",
* "email": "gene.lopez.at.home@example.com",
* "primary": true
* },
* {
* "_id": "78e5f398-e148-448d-b490-7c0b7d2ab336",
* "tag": "WORK",
* "email": "gene.lopez@example.com",
* "primary": false
* }
* ],
* "phones": [
* {
* "_id": "820e4640-ffe0-4980-a097-62a715e73135",
* "tag": "MOBILE",
* "countryCode": "US",
* "phone": "(722)-138-3099",
* "primary": true
* },
* {
* "_id": "8506549e-e4f8-42f6-b6fc-9db155b582ef",
* "tag": "HOME",
* "countryCode": "US",
* "phone": "(704)-454-1233",
* "e164Phone": "+17044541233",
* "primary": false
* }
* ],
* "addresses": [
* {
* "address": {
* "formatted": "9834 Bollinger Rd\nEl Cajon, WY 97766\nUS",
* "location": {
* "latitude": 84.1048,
* "longitude": -116.8836
* },
* "city": "El Cajon",
* "subdivision": "US-WY",
* "country": "US",
* "postalCode": "97766",
* "streetAddress": {
* "name": "Bollinger Rd",
* "number": "9834",
* "apt": ""
* }
* },
* "_id": "8532051f-91f2-42d9-9a97-9f2c39e64f7a",
* "tag": "HOME"
* }
* ],
* "profilePicture": "https://randomuser.me/api/portraits/men/0.jpg",
* "extendedFields": {
* "contacts.displayByLastName": "Lopez Gene",
* "emailSubscriptions.deliverabilityStatus": "NOT_SET",
* "emailSubscriptions.subscriptionStatus": "NOT_SET",
* "custom.event-we-met-at": "LegalBigData",
* "emailSubscriptions.effectiveEmail": "gene.lopez.at.home@example.com",
* "contacts.displayByFirstName": "Gene Lopez"
* }
* },
* "lastActivity": {
* "activityDate": "2021-03-30T13:12:39.649Z",
* "activityType": "CONTACT_CREATED"
* },
* "primaryInfo": {
* "email": "gene.lopez.at.home@example.com",
* "phone": "(722)-138-3099"
* },
* "source": {
* "sourceType": "OTHER"
* }
* }
*/
Retrieves an extended field.
The getExtendedField()
function returns a Promise
that resolves when the extended field is retrieved.
Note:
Only visitors with
Manage Contacts permissions
can retrieve extended fields.
You can override the permissions by setting the suppressAuth
option to true
.
function getExtendedField(
key: string,
options: AuthOptions,
): Promise<ExtendedField>;
Extended field ID .
When accessing contact data,
extended field values are available at extendedFields[key]
.
For example, if the key is "custom.notes",
the value can be accessed at extendedfields["custom.notes"]
.
Once set, key
cannot be modified, even if displayName
changes.
Authorization options.
import { Permissions, webMethod } from "wix-web-module";
import { contacts } from "wix-crm-backend";
export const myGetExtendedFieldFunction = webMethod(Permissions.Anyone, () => {
const fieldKey = "custom.event-name";
const options = {
suppressAuth: false,
};
return contacts
.getExtendedField(fieldKey, options)
.then((extendedField) => {
return extendedField;
})
.catch((error) => {
console.error(error);
});
});
/*
* Promise resolves to:
*
* {
* "_createdDate": "2021-01-19T21:41:39Z",
* "_updatedDate": "2021-01-19T21:41:39Z"
* "namespace": "custom",
* "key": "custom.event-name",
* "displayName": "Event Name",
* "dataType": "TEXT",
* "fieldType": "USER_DEFINED",
* }
*/
Retrieves a label.
The getLabel()
function returns a Promise
that resolves when the specified label is retrieved.
Note:
Only visitors with
Manage Contacts permissions
can retrieve labels.
You can override the permissions by setting the suppressAuth
option to true
.
function getLabel(key: string, options: AuthOptions): Promise<Label>;
Label key.
key
is generated when the label is created
and cannot be modified, even if displayName
changes.
Authorization options.
import { Permissions, webMethod } from "wix-web-module";
import { contacts } from "wix-crm-backend";
export const myGetLabelFunction = webMethod(Permissions.Anyone, () => {
const labelKey = "custom.active-customer";
const options = {
suppressAuth: false,
};
return contacts
.getLabel(labelKey, options)
.then((label) => {
return label;
})
.catch((error) => {
console.error(error);
});
});
/*
* Promise resolves to:
*
* {
* "_createdDate": "2021-01-20T00:31:41Z",
* "_updatedDate": "2021-01-20T00:31:41Z"
* "namespace": "custom",
* "key": "custom.active-customer",
* "displayName": "Active Customer",
* "labelType": "USER_DEFINED"
* }
*/