Objects
Orders, subscriptions, products and accounts explain the relationship behind an email. Store them as objects, then connect them to contacts through the fields and evaluated relationships your campaign needs.
For example, an order with a customer identifier, product and purchase date gives you the facts for a replenishment audience or a follow-up email. Define the relationship and request the relevant fields where you use them; storing a product alone does not connect it to a customer.
Create the object type
Go to Settings, then Schemas, and choose Create schema. Set the type to Object, then fill in the name ("Product"), the plural name ("Products"), a slug, and a description.
One type per kind of thing. Products and Orders are two types, not one. Every object belongs to exactly one type and is checked against it each time it is written, which is what your segments, emails and workflows rely on to find the fields there.
Write the description for a person to read. maxinja reads it too, every time it builds a segment, a computed field or workflow logic that touches this object.
Add your fields
Open the type, go to the Attributes tab, and use Create attribute for each field you need: price, SKU, colour, launch date. The available field types are covered in attributes.
Every object comes with these already, whatever else you add:
| Field | What it is for |
|---|---|
| ID | The identifier maxclicks gives it. |
| External ID | Your own identifier for the same thing, from your store or database. |
| Notes | Free text. |
| Tags | Labels you can filter and act on. |
| Created At, Updated At | Kept by maxclicks. |
Two of your own fields are worth naming deliberately, because the app reads them:
- A single-line Text field whose key contains
name,titleorlabelbecomes the heading on the object's page, soproductNamecounts. Without one, maxclicks falls back to your first single-line text field, and then to the External ID. - A URL field with its target set to Image becomes the thumbnail in the objects table.
Give every object an External ID
Supply the platform id to identify an existing object directly, or your source system's stable externalId to match within the object schema. Repeatedly upserting that external ID updates the same object. Names, prices and other custom fields do not establish identity.
Without either identifier, repeated writes can create repeated records. A Product and an Order can use the same external ID without colliding because matching stays within the selected schema. Sending a platform ID that is not found does not mean “create this exact ID”; inspect the operation's error or unmatched result.
No two objects of the same type can hold the same External ID. Over the upsert endpoint and from a workflow step, an update that would take one already belonging to another object keeps the old value, applies everything else you sent, and reports the change it skipped. Everywhere else the conflicting write is not applied at all: a clashing CSV row is counted as a failed row, with "Conflicting external ID." against it in the import's failure log, editing the field to a taken value in the app fails with a conflict error, and creating or patching a record over the API returns a conflict. Check those warnings and failed rows: a skipped or rejected External ID means your sync is pointing two things at one identifier.
Get your objects in
| Route | Use it for |
|---|---|
| The Import tab on the object type | A spreadsheet you already have. Download the sample CSV, fill it with your objects, upload it back. Up to 50 MB and 500,000 rows. The standard importer matches writable attribute keys and omits unknown columns; inspect imported records because the row summary does not show a per-column warning. Onboarding can plan a reviewed mapping with maxinja. See Import a contact list for shared CSV rules. |
| The button above the table, labelled New and then your type's name | One object, by hand. |
| The API | Your store, database or backend keeping maxclicks in sync. See Records. |
| A connected app | Integrations bring their own object types and keep them up to date for you. |
An object type created by a connected app is badged Managed by that app. Integration-owned definitions are locked and CSV import is switched off for the schema. Records remain editable, but a later sync can overwrite fields the integration owns. Keep your campaign-specific fields separate from the upstream system's fields.
Work with your objects
Objects live under Records in the top navigation, listed by the slug of each type. From there you can:
- Search the list, and use Select Columns to pick which fields the table shows. The choice is remembered per type.
- Click a row to open the object. Edits save as you type.
- Tick rows to select them, then tag or delete them all at once.
Deleting is permanent. The deletion operation can continue while related event and derived data are removed, and workspace processing can be gated during cleanup. Wait for completion. Schema deletion can also be blocked by dependencies; replace those references before retrying.
Keep record state and event history distinct
Update the object when its current state changes: a subscription becomes canceled or an order is refunded. Send a separate event when the occurrence itself matters to automation. For profile calculations, attach the event's explicit objectId; an externalId inside its custom payload does not establish that subject link.
Objects can receive computed attributes, such as the latest observed usage of an account, as well as evaluated relationships. Both require expansion when an email or workflow needs their values. A missing published calculation is not equivalent to a measured zero.
Put objects to work
An object sitting in a table does nothing on its own. It earns its place the moment something reads it.
- Add an evaluated attribute to your contacts so each contact points at the objects that belong to them: "the company this person works for", "the last three things they bought".
- Pull those objects into an email with Liquid, or describe the result you want and let Adaptyle write it per recipient. An email has to ask for related records before it can use them: see attribute expansion.
- In a workflow, start a run with a Record Created or Updated step on an object type, look objects up mid-run with Find Records, or write back with Create or Update Records.