# Quotient
Quotient is an AI-native marketing platform and intelligent agent in one — built to plan and execute campaigns across email, social, blog, and events, without the fragmented tools you've outgrown.
It combines a full-featured SaaS marketing platform (content authoring, distribution, lead storage, performance analytics) with a powerful AI agent that can operate the platform, access external tools, and manage brand knowledge and memories. Quotient gives small-to-mid-sized B2B companies — from seed to Series C — the output of a top-notch marketing agency at a fraction of the cost.
Key capabilities:
- AI agent that plans and executes full marketing campaigns end-to-end
- Email marketing with custom domains, audience targeting, and CRM sync
- Social media publishing across major platforms
- Blog content creation and WordPress publishing
- HubSpot integration for contact and list management
- Brand memory so the agent learns your voice, audience, and past campaigns
- SDK and MCP server for developers building on top of Quotient
---
# Docs
## File Tree
docs/
analytics/
custom-events/
server-side-conversions
identifying-users
on-site-tracking/
custom-website
framer
google-tag-manager
webflow
wix
wordpress
reports/
catalog
tagging-and-attribution
audience/
import-audience
location
people
segments
blog
campaign
email/
dns/
cloudflare-guide
godaddy-guide
namecheap-guide
shopify-guide
squarespace-guide
email-status
suppression
unsubscribe
variables/
conditional-components
flow
integrations/
attio/
field-mappings
setup
hubspot/
email-sync
field-mappings
lists
objects
setup
troubleshooting
slack
wordpress/
setup
syncing
troubleshooting
zoom
mcp/
connecting-tools/
github-private-repos
from-other-apps/
setup-instructions
tools-reference
navigating
plans-and-billing
sdk/
analytics
api-keys
audience
blog
flow
memory
react
social
trust-security/
privacy
subprocessors
working-with-ai/
jobs
memory
## Documentation
-- Start of: /blog
---
title: Blog
description: Write and publish blog posts with Quotient
order: 6
---
Writing a blog is one of the best ways to attract interest in your brand and establish your business as a trusted leader in its space. More specifically, a blog serves several purposes within your marketing strategy:
- **Organic SEO:** Thoughtful, SEO-optimized blogs can help your brand rank for high-intent keywords in search engines like Google. Note that this can also help your brand get noticed by AI assistants like ChatGPT.
- **Thought Leadership:** An informative, high-quality blog establishes your brand as a thought leader in your industry. This helps establish your brand’s reputation and credibility, which is critical for selling your product.
- **Content that Sells without Selling:** A blog can help educate customers and prospects about the importance of your solution. The goal of a blog is not necessarily to sell your product directly, but rather to educate and promote understanding of the problem your business is trying to solve.
With Quotient, you can write and publish a blog from the same integrated platform you use to send email, plan events, and manage your brand.
## Core Concepts
**Posts**
A blog post is an individual article with a dedicated URL. Blog posts are written as **rich text**, which means you can apply basic formatting like bold/italics, headers, and lists, but more advanced formatting like fonts and text size are controlled in your publishing environment.
**Authors and Tags**
Each blog has one or more **authors** and can also optionally have **tags**. Authors are linked to Quotient users, so if you want someone to be listed as a blog author they must be a user in Quotient.
Tags are simply for organizational purposes to help users navigate your blog. For example you might have separate tags for…
- Company Updates
- Product Updates
- Industry Trends
**SEO Metadata**
Blogs also have additional metadata for SEO, such as…
- **Meta Description:** A short summary that appears in search results and helps improve click-through rates
- **Keywords:** Target keywords that help search engines understand your content's focus
- **Thumbnail Image:** The featured image that appears when your blog is shared on social media
- **Publish Date:** Helps search engines understand when content was published
This information is not necessarily visible on the page, but it helps search engines better understand the content and signals that it's fresh and relevant.
## Writing with Quotient
You can ask Quotient to write entire blogs for you, conduct research, or edit and proofread blogs you've written.
Quotient draws on its memory of your business, which is crucial for creating on-brand, on-message content. It also reads campaign briefs, ensuring that blogs fit into larger marketing campaigns.
Here are a few tips for getting the most out of Quotient when writing blogs:
- Share samples of your writing and ask Quotient to save them to memory. This will help Quotient get a sense of your unique writing voice and preferences. Similarly, it can be helpful to put together an Author Profile for common blog authors.
- Give Quotient your rough notes or stream-of-consciousness voice messages and ask it to polish them up into a nicely formatted, professional blog post.
- Writing with Quotient is an iterative, back-and-forth process. You can ask it to draft the first version of the post, and then you can select portions of the text that you want to tweak using the “Ask for Changes” feature.
## Publishing Your Blog
Once you've written your blog, you have two options for publishing it to your website:
1. If you have a custom-built website using a framework like NextJS or Remix, you can use the Quotient Javascript SDK to fetch data from the blog and render it.
2. If you use Webflow, you can use our Webflow integration to sync blog posts from Quotient to Webflow’s CMS.
In the near future, we will be adding additional integrations to other web platforms like Framer and WordPress as well.
You can schedule your blog to publish at a specific date and time, or publish it immediately. You can also unpublish a blog after it has been published.
### Publishing Changes
Once your blog moves to the __Published__ status, it will be visible on your site.
However, you may often want to publish changes to an already-published blog. Changes you make to a published blog will **_not_** automatically sync to your website. To publish them, click the “Publish Changes” button in the upper right hand corner of the blog page.
-- End of: /blog
-- Start of: /campaign
---
title: Campaigns
description: Plan and organize your marketing into campaigns
order: 3
---
Campaigns help you organize your marketing efforts around a central theme or goal. A **[campaign](/s/most-recent-business/campaigns)** in Quotient is a coordinated collection of tasks and deliverables that work together toward a common objective. Think of campaigns as the strategic umbrella that organizes your marketing work across different channels and timeframes.
Grouping deliverables into campaigns is not a requirement in Quotient; you can still publish one-off blog posts or email broadcasts. But grouping things into campaigns helps ensure that your marketing has a consistent message, making it more effective.
Here are some examples of campaigns:
1. **New Feature Announcement:** When announcing an important new feature or launching a new product, it's common to write blogs, send email broadcasts, or host webinars promoting the new feature.
2. **Events:** Campaigns are often built around marketing events. For example, if you are hosting a webinar, or if your company is attending an industry conference, you might want to do a lot of marketing around that event, e.g. sending emails to customers before and after the event.
3. **Thought Leadership:** A specific topic, such as a new regulation or technological breakthrough, might be trending in your industry. To capitalize on interest, you might want to publish a series of blogs explaining your company's perspective on it.
## Core Concepts
### Tasks
Campaigns are organized as a series of tasks. Each task represents a specific piece of work that needs to be completed as part of the campaign. Tasks move through a workflow with four statuses:
- **To-do** - Task has been created but work hasn't started yet
- **In progress** - Task is actively being worked on
- **In review** - Task is complete and awaiting review or approval
- **Done** - Task is complete and approved
Tasks can represent many different types of work:
**Deliverable-Linked Tasks** - Work that's connected to creating specific marketing assets in Quotient:
- Writing a blog post
- Designing an email broadcast
- Setting up a marketing event
- Building an automated flow
- Creating a social media post
**Standalone Tasks** - Work that doesn't happen directly in Quotient:
- Shooting a video
- Taking screenshots of a new feature
- Getting legal approval
- Running paid ads
- Coordinating with external vendors
### Deliverables
When a task involves creating a marketing asset that will be distributed to your audience, it can be linked to a **deliverable**. Deliverables are the actual marketing assets created in Quotient:
- **Blog Posts** - Articles published on your website
- **Email Broadcasts** - Emails sent to your audience
- **Marketing Events** - Webinars, conferences, or in-person events
- **Flows** - Automated email sequences
- **Social Posts** - Content for X, LinkedIn, Instagram, Facebook, and TikTok
When you link a task to a deliverable (like "Write Q4 product announcement blog"), the task provides project management structure while the deliverable contains the actual content and publishing details.
### Briefs
Briefs are strategic memos that explain the purpose, message, and audience for a campaign. This information is critical for aligning both humans and Quotient on the strategy of a campaign. Quotient reads the brief for a campaign when creating content to ensure that the content is consistent with the theme and message of the campaign.
### Task Owners
Each task can have an **owner** - the human who's responsible for completing it. When you're the owner of a task, you'll get notifications about its progress as Quotient works on it, and you can track it on your personal task list.
## Planning Campaigns with Quotient
Ask Quotient to help you develop campaigns from inception to execution. It can create the campaign, write the initial brief, break down the work into tasks, and pick the right timeframe. Once you've agreed on the concept, Quotient will work through each task, creating the deliverables (like blogs, emails, or social posts) in new threads.
Here are some tips for getting the most out of Quotient when planning campaigns:
- You can ask Quotient to help you come up with ideas for campaigns, or if you already have a clear idea for a campaign you can ask it to break it down into actionable tasks.
- Ask Quotient to search the web and perform research, which is helpful for campaigns that have to do with current events or trending topics.
- Every company runs campaigns differently. Some prefer many small campaigns with just a few tasks and deliverables, while others prefer large campaigns with dozens of tasks and deliverables over several months. Tell Quotient about your preferred workflow and ask it to "remember" it in the future.
- If you're not happy with a campaign, tell Quotient what you'd like to change. It will update briefs and add or remove tasks until it looks right. Building campaigns is an iterative process and requires some back and forth.
-- End of: /campaign
-- Start of: /flow
---
title: Flows
description: Automate your marketing with flows that run on triggers and schedules
order: 8
---
Quotient allows you to automate common internal and external workflows throughout your marketing stack. You can easily put together automations such as…
- Sending automated sequences of marketing emails based, like a welcome series or account activation
- Sending highly personalized, AI generated emails tailored to each customer's recent activity and firmographics
- Updating a prospect's lead score when they signal high intent to purchase, e.g. by performing specific actions on your site
- Sending automated notifications to your team when a new customer signs up for your product or achieves a certain lead score
Automations like these help you engage with customers with personalized content at the right time, and they can also help automate repetitive work for your team.
## Core Concepts
**Flows**
[Flows](/s/most-recent-business/flows) are automated sequences of actions orchestrated by the Quotient platform. You can create flows using the flow editor or by chatting with Quotient. Every flow starts with a **trigger** and then proceeds through a series of **steps** until it's finished.
Flows can also optionally be scoped to a specific **segment** of people, which you can define dynamically in each flow.
**Trigger**
Triggers are events or schedules that initiate a flow. There are six different trigger types:
1. **Event Trigger:** Activates when a specific user action occurs (email subscribe, page view, add to cart, checkout complete). Responds to customer behavior.
2. **Schedule Trigger:** Runs at defined times and frequencies (daily, weekly, monthly). Used for recurring communications.
3. **Person Update Trigger:** Activates when a specific field in a customer profile changes. Can trigger on any change or only when matching a specific value.
4. **Person Created Trigger:** Activates when a new person record is added to Quotient. Used for initial contact sequences.
5. **Programmatic Trigger:** Activates via the Quotient API or SDK. Provides programmatic control over flow initiation.
6. **Marketing Event Trigger:** Activates when someone's participation status changes in a marketing event (webinar, conference). Tracks status changes like registered, attended, or no-show.
**Steps**
Once the trigger has been activated, the flow proceeds through a series of steps. There are eight different step types:
1. **Send Email:** Sends an email to the customer using a specified template. Can include dynamic variables for personalization.
2. **AI Email:** Uses artificial intelligence to dynamically decide whether to send an email and which template to use based on customer data and behavior.
3. **Delay:** Pauses the flow for a specified duration (minutes, hours, days, weeks, months). Controls timing between actions.
4. **Update Person:** Updates a field in the person's profile. Works with both standard fields and custom properties.
5. **Notify User:** Sends an internal notification to a team member. References users by USER-type fields on the person or company record.
6. **Update Lead Score:** Modifies the person's lead score using increment,
decrement, or set operations.
7. **Send to CRM:** Sends person data to connected CRM systems (Attio, Salesforce, HubSpot). Configurable for different CRM object types.
8. **HTTP Request:** Sends a custom request to any external URL, like a webhook, Zapier, or another tool in your stack. You can personalize the path, query parameters, and request body with customer data, though the destination domain itself must stay fixed.
**Conditionals**
Conditional steps create branching paths in your flow based on either profile data or random sampling. They evaluate a statement about a person and route them down one of two paths: the "if true" branch or the "if false" branch.
Conditions can be based on:
- Profile properties (location, preferences)
- Behavioral history (pages viewed, purchases made)
- Email engagement metrics
- Random sampling (for A/B testing)
Conditionals transform flows from linear sequences into adaptive journeys that respond to each person's unique attributes and behaviors, allowing for targeted messaging without creating separate flows for each scenario.
## Building Flows with Quotient
Tell Quotient the business objective of your flow and it will help fill in the details, including creating any email templates or segments needed along the way.
Here are some tips for getting the most out of Quotient when building flows:
1. If there are specific email templates you want to use in your flow, @ mention them so that Quotient knows to use them.
2. If you are using Quotient to automate workflows with your CRM, make sure to explain how your CRM is set up, e.g. any custom fields you use for lead qualification.
## Common Use Cases
Flows are a versatile tool that can support a wide range of marketing automation needs. While most commonly used for customer communication, flows can also streamline internal processes and automate data management across your marketing stack.
Let's walk through a few of the most common use cases for flows.
### Sending Email to Users
The most common use case for flows is sending automated marketing emails to users. Whereas email broadcasts send a single blast email to many people all at once, flows allow for more personalized, timely messaging that reaches customers at specific moments in their buying journey.
These flows typically leverage the **Send Email** step to deliver targeted messages, often combined with **Delay** steps to control timing and **Conditional** steps to create personalized paths based on customer behavior.
Here are some examples:
- **Welcome Series** - Automatically send a sequence of emails to new subscribers introducing your product or service, typically spaced over several days or weeks. Uses **Send Email** and **Delay** steps with an **Event** trigger for new subscribers.
- **Customer Activation** - Guide new users through key features with timely, targeted emails based on their activity (or lack thereof) in your product. Combines **Send Email** steps with **Conditional** logic to check user activity.
- **Customer Winback** - Re-engage inactive customers with personalized offers or content based on their previous purchase history and browsing behavior. Uses **Schedule** triggers with **Conditional** steps to identify inactive users.
### AI Personalized Email
AI Personalized Email steps are an especially powerful feature of flows in Quotient. These steps allow you to use AI to predict the best email to send a user based on their recent behavior - plus the instructions you provide.
This helps improve conversion rates and improve outreach to customers who may not have been addressed by more deterministic, logic-based flows.
An AI Personalized Email step accepts two main parameters:
**Instructions** - A single block of instructions you wish to provide the AI. You can give the AI whatever instructions you like here. For example:
- "Send promotional emails only to users who have opened emails in the last 30 days"
- "Prioritize product recommendations from categories the user has previously purchased"
- "Avoid sending more than 2 emails per week to any user"
**Available Templates** - A list of templates that the AI can choose from. The AI will only choose from a list of pre-approved templates for this particular flow.
Based on these, the AI will choose whether to send a template at all and, if so, which template to send.
It is common to use AI Personalized Email steps in conjunction with schedule triggers. For example you might have a flow that is triggered at 9:00 am every Monday for any users that have not opened an email in the past two weeks. In this flow you could instruct the AI to choose from a set of templates in an effort to re-engage the customer.
### Sending Data to the CRM
CRM integration flows automate the synchronization of customer data between Quotient and your CRM system, ensuring your sales and customer success teams always have access to the most current and relevant information.
These flows typically use the **Send to CRM** step to sync data with systems like Attio, Salesforce, and HubSpot, often combined with **Update Lead Score** and **Update Person** steps to track customer progression.
Here are some examples:
- **Lead Score Updates** - Automatically increment a prospect's lead score when they perform specific high-value actions like downloading resources or visiting pricing pages. Uses **Update Lead Score** steps with **Event** triggers for high-value actions.
- **Deal Stage Progression** \- Move leads through your sales pipeline based on their behavior and engagement with your marketing materials. Uses **Conditional** steps to check engagement levels before **Send to CRM** steps.
### Notifying Your Team
Quotient can also send notifications via email or Slack to your team when certain events happen. This is helpful for getting your team's attention when someone performs an action that your team should know about - e.g. a new signup or a cancellation.
These flows use the **Notify User** step to send internal notifications to team members, often triggered by **Event** or **Person Update** triggers that signal important customer actions.
- **New Account Alerts** - Notify relevant team members when a new customer signs up, including essential information about the customer's profile and initial activity. Uses **Notify User** steps with **Person Created** triggers.
- **Lead Qualification Notifications** - Alert sales representatives when a prospect reaches a specified lead score threshold or performs high-intent actions. Combines **Notify User** steps with **Person Update** triggers monitoring lead score changes.
- **Customer Milestone Notifications** - Keep customer success teams informed when accounts reach important usage milestones or when accounts show signs of churn risk. Uses **Conditional** steps to check milestone criteria before **Notify User** steps.
-- End of: /flow
-- Start of: /index
---
title: Introduction
description: Getting started with Quotient
order: 0
---
## What is Quotient?
Quotient is an **AI demand marketing platform.** "Demand marketing refers to all the activities that attract customers to your business, such as…
- Writing online content like blogs or social media posts
- Sending emails to customers or prospects
- Hosting in-person or online events like webinars and trade shows
- Building an authoritative brand that customers recognize and trust
With Quotient, you can do all of this from a single integrated platform \- write blogs and emails, plan campaigns and events, and manage your brand information, all powered by AI.
## Working with Quotient
You can chat with Quotient to get things done, just like you would with a coworker. If you've used products like ChatGPT or Claude, the experience will feel familiar. Simply tell Quotient what you want, and it takes care of the rest.
Quotient understands your brand and learns your business's preferences and workflows over time through [memory](/docs/working-with-ai/memory). You can ask it to do virtually any marketing task on the platform, from writing blog posts and composing emails to planning campaigns, building customer segments, and creating automated workflows.
## Quotient's Interface
Quotient's interface has two main parts:
1. The **app panel** \- a traditional graphical user interface where you can manage campaigns, write blogs, compose emails, etc.
2. The **chat panel** \- a conversational interface on the right side of the app panel where you can chat with Quotient.
As a general rule, everything that you can do in the app panel you can _also_ do by asking Quotient in the chat panel, and vice versa.
When you chat with Quotient, it understands what page you're on in the app panel and can "see" what you're looking at. This makes it easy to collaborate side by side, much like you would with a human coworker.
## Next Up
## For AI Agents
Every page in these docs is available as raw Markdown — just append `.md` to any URL (for example, `/docs/working-with-ai.md`).
-- End of: /index
-- Start of: /plans-and-billing
---
title: Plans and Billing
description: How Quotient's plans, usage, billing, and trials work
order: 1050
---
Quotient offers four plans — **Free**, **Starter**, **Pro**, and **Scale** — each designed for a different stage of your marketing operation. For a side-by-side comparison of what's included in each plan, visit the [pricing page](https://www.getquotient.ai/pricing).
This document covers the details of how billing, usage, and plan changes actually work once you're up and running.
## AI Credits
AI credits are the unit of measurement for work that Quotient's AI does on your behalf. Every time Quotient writes a blog draft, composes an email, researches a competitor, or answers a question in chat, it consumes AI credits.
Not all tasks consume credits equally. A few factors affect how many credits a given interaction uses:
- **Conversation length.** Longer threads with more back-and-forth consume more credits than short, focused requests, because Quotient re-reads the full conversation each time it responds.
- **AI model.** Premium AI models (available on Starter and above) are more capable but consume more credits per interaction than the standard models available on the Free plan.
- **Task complexity.** Tasks that require Quotient to use tools — like searching the web, looking up audience data, or reading multiple documents — consume more credits than simple conversational responses, because each tool use involves additional processing.
- **Content length.** Generating a 2,000-word blog post consumes more credits than writing a short social media caption.
You can monitor your credit usage at any time in [Settings > Usage](/s/most-recent-business/settings/usage), which shows a breakdown of consumption within your current billing cycle.
## Usage and Overages
Each plan includes a monthly allotment of AI credits, emails sent, social posts published, and blog posts published. How overages are handled depends on your plan:
**Free plan.** When you reach your included allotment, usage is cut off until the next billing cycle. There are no overage charges — but you won't be able to use the feature until your usage resets.
**Paid plans (Starter, Pro, Scale).** You're never cut off. If you exceed your included allotment, you can keep using the platform and the overage is added to your next invoice. This means your monthly bill may vary slightly depending on usage, though most users stay within their included allotments.
Your usage resets at the start of each billing cycle, which is anchored to the date you first subscribed — not the first of the month.
## Resources and Feature Access
In addition to usage-based metrics, each plan includes a set number of **resources** (users and connected social accounts) and access to certain **features** (email sending, social publishing, CRM integrations, Slack, custom email domains, and premium AI models).
Resource limits are hard caps — if your plan includes 15 users, you'll need to upgrade before inviting a sixteenth. Feature access is binary: either your plan includes it or it doesn't. You can see exactly what's included on each plan on the [pricing page](https://www.getquotient.ai/pricing).
## Free Trial
Every new Quotient business starts with a **14-day free trial of the Pro plan**. During the trial, you have full access to all Pro features — CRM integrations, Slack, custom email domains, premium AI models, and the full Pro usage allotment — without entering a credit card.
When the trial ends, your business reverts to the Free plan. Any content you created during the trial (published blogs, sent emails, etc.) remains intact, but you'll lose access to Pro-only features until you subscribe.
If you subscribe to any paid plan during or after the trial, the trial ends and your new plan takes effect immediately.
## Upgrading and Downgrading
You can change your plan at any time from [Settings > Plan](/s/most-recent-business/settings/plan).
**Upgrading.** When you upgrade to a higher plan, the change takes effect immediately. You're charged a prorated amount for the remainder of the current billing cycle — so if you upgrade halfway through the month, you only pay half the price difference.
**Downgrading.** When you downgrade, you keep access to your current plan's features through the end of your billing cycle. The lower plan takes effect when the next cycle begins. If the lower plan doesn't include features you were using (like Slack or CRM integrations), those integrations will be deactivated at that point.
## Cancellation
You can cancel your subscription at any time from [Settings > Plan](/s/most-recent-business/settings/plan). When you cancel:
- Your subscription remains active through the end of the current billing cycle. You won't be charged again.
- After the billing period ends, your business reverts to the Free plan.
- All of your data, content, and settings are preserved — nothing is deleted. You just lose access to paid features.
If you change your mind before the billing period ends, you can undo the cancellation and stay on your current plan.
## Payment Issues
If a payment fails (for example, due to an expired credit card), Quotient will continue to retry the charge for a short period. During this time, your access is unaffected — you'll see a banner prompting you to update your payment method, but nothing is locked.
If the payment remains unresolved after the retry period, your account's paid features will be restricted until the balance is settled. You can update your payment method at any time through [Settings > Plan](/s/most-recent-business/settings/plan) by clicking "Manage billing."
## Deleting a Business
If you delete a business from Quotient, any active subscription is cancelled immediately — not at the end of the billing cycle. This is permanent. If you think you might come back, consider cancelling your subscription instead, which preserves your data on the Free plan.
## Overage Rates
For reference, here are the current overage rates for paid plans. These apply only to usage beyond what's included in your plan:
Metric
Overage Rate
AI Credits
$26 per 1,000 credits
Emails Sent
$1.50 per 1,000 emails
Social Posts Published
$0.10 per post
Blog Posts Published
$0.10 per post
Overages are calculated automatically and added to your next invoice. You can estimate your monthly cost using the [pricing calculator](https://www.getquotient.ai/pricing).
-- End of: /plans-and-billing
-- Start of: /navigating
---
title: Navigating Quotient
description: How to get around the platform
order: 2
---
Quotient keeps two things side by side: your work, and a conversation about it.
There's a fair amount on screen, so here are the shortcuts and small tricks that
make moving between them feel quick instead of busy.
## The Command Menu (⌘ + K)
The fastest way to get anywhere in Quotient is the command menu. Press `⌘ + K`
(or `Ctrl + K` on Windows and Linux) from anywhere, then start typing.
The command menu does two jobs. First, it's a universal search: type the name of
an email broadcast, flow, asset, or any other object and jump straight to it.
Second, it's a launcher for actions, so instead of hunting through menus you can
run a command right from the keyboard.
What makes it powerful is that it's **contextual** — the actions it offers
depend on where you are. If you're looking at an email broadcast, you'll see
broadcast actions like "Send a Test" or "Schedule" right at the top. Open it
somewhere else and you'll get that page's actions instead.
Once it's in your muscle memory, you'll rarely take your hands off the keyboard.
When in doubt, reach for `⌘ + K`.
## @ Mentioning
When you're chatting with Quotient, you can quickly reference existing objects
by @ mentioning them — a campaign, an email broadcast, a memory, another user,
and most other things you've created.
This automatically shares all the relevant context with Quotient — like sending
a hyperlink to a human colleague instead of describing the thing from memory. So
rather than explaining which campaign you mean, just @ mention it and Quotient
has everything it needs.
## Collapsible Sidebar
Press `⌘ + .` to collapse and expand the navigation sidebar, giving your work
more room when you need it.
## Keyboard Shortcuts
If you like to move fast, Quotient has shortcuts for the things you do most
often. Here are the handiest ones:
| Action | Shortcut |
| ------------------------------- | ----------- |
| Open the command menu | `⌘ + K` |
| Start a new chat | `⌘ + /` |
| Start a new chat in full screen | `⌘ + ⇧ + /` |
| Go to the previous chat | `⌘ + ⇧ + ,` |
| Go to the next chat | `⌘ + ⇧ + .` |
| Attach a file to a message | `⌘ + U` |
And for arranging your workspace:
| Action | Shortcut |
| ------------------------- | -------------- |
| Show the chat sidebar | `Ctrl + \` |
| Make the chat full screen | `Ctrl + M` |
| Hide the chat panel | `Ctrl + ⇧ + \` |
| Move the chat left | `Ctrl + [` |
| Move the chat right | `Ctrl + ]` |
| Collapse the sidebar | `⌘ + .` |
For the complete list, press `⌘ + ;` in the app to open the keyboard shortcuts
cheat sheet. We keep it up to date as shortcuts change.
-- End of: /navigating
-- Start of: /social
---
title: Social
description: Create and publish social media posts with Quotient
order: 4
---
Social media is a powerful channel for building your brand, engaging with your audience, and driving traffic to your website. Quotient helps you create compelling social media content tailored to each platform.
## Supported Platforms
Quotient currently supports creating and publishing posts to:
- **X (Twitter)** - Including support for threads
- **LinkedIn** - Professional networking and B2B content
- **Instagram** - Visual content and engagement
- **Facebook** - Pages and community engagement
- **TikTok** - Short-form video and photo carousels
## Creating Social Posts
Ask Quotient to help you [create social media posts](/s/most-recent-business/social) tailored to each platform. It understands the unique characteristics and best practices for each platform, including character limits, image requirements, and optimal posting strategies.
When you create a social post, you can:
- Write or edit the post content directly
- Add images and media
- Create multi-post threads (for X)
- Add a first comment (LinkedIn, Instagram, Facebook)
- Schedule posts for a specific date and time
- Track the status of your posts
## Publishing Your Posts
Once you've connected your social accounts in **Settings > Social Accounts**, Quotient can publish directly to each platform. Posts can be:
- **Published immediately** — click "Publish" to post right away
- **Scheduled** — set a date and time for automatic publishing
- **Unpublished** — remove a published post from the platform (X, LinkedIn, Facebook)
## Creating Posts with Quotient
Ask Quotient to help you create engaging social media content. It draws on its memory of your business, so everything it creates will be consistent with your brand's voice and messaging.
Here are some tips for getting the most out of Quotient when creating social posts:
- Provide context about your target audience and goals for each post
- Ask Quotient to create variations for different platforms
- Upload reference images or examples of posts you like
- Request specific hashtags or mentions to include
- Have Quotient create thread series for more in-depth topics
-- End of: /social
-- Start of: /audience/import-audience
---
title: Import Audience
description: Import contacts into Audience with a CSV file.
order: 1
---
If you already have contacts in another system, you can import them into
Audience with a CSV instead of adding people one by one. Start from the
[Upload CSV page](/s/most-recent-business/people/import-people/upload-csv), map
your columns to Quotient fields, and then run the import.
Quotient requires two fields for each contact:
1. `EMAIL` — a valid email address.
2. `EMAIL SUBSCRIPTION STATUS` — the contact's current marketing permission status.
Most other columns (like first name, company, job title, phone, city, and
country) are optional, but including them usually makes segmentation and
personalization more useful later.
## Email Subscription Status Values
Use one of the following values in the `EMAIL SUBSCRIPTION STATUS` column:
- `SUBSCRIBED` — The person is opted in and can receive marketing emails.
- `NOT_SUBSCRIBED` — The person has not opted in and should not receive
marketing emails.
- `UNSUBSCRIBED` — The person explicitly opted out and should not receive
marketing emails.
- `PENDING` — The person's subscription is waiting for confirmation.
These meanings match how unsubscribe and consent handling works in Quotient, so
it is important to use the exact values in your CSV.
## Validation Before Import
Before import starts, Quotient checks the first 100 records in your file. If it
finds invalid values for `EMAIL SUBSCRIPTION STATUS`, the upload is blocked so you
can fix the data first.
-- End of: /audience/import-audience
-- Start of: /audience/index
---
title: Audience
description: Build, organize, and understand your audience in Quotient
order: 7
---
Quotient's Audience section helps you understand and engage with your customers effectively. The platform enables you to:
- Track customer interactions and behaviors across channels
- Build detailed customer segments based on engagement patterns
- Personalize marketing campaigns using customer data
- Measure and analyze customer engagement over time
## Key Features
### Import Audience
Upload a CSV to quickly add or update contacts in bulk. [Start an
import](/s/most-recent-business/people/import-people/upload-csv), and review the
[import guide](/docs/audience/import-audience) for required fields and validation.
### People
View detailed information about individual customers, including their purchase history, email engagement, and preferences. [Explore your people](/s/most-recent-business/people) or learn more in our [people guide](/docs/audience/people).
### Segments
Create dynamic groups of customers based on shared characteristics or behaviors. [View your segments](/s/most-recent-business/segments) to target your marketing campaigns and analyze customer patterns.
### Working with Quotient
Ask Quotient to help you understand your customers better and suggest targeted marketing strategies based on your audience data.
-- End of: /audience/index
-- Start of: /audience/location
---
title: Location
description: How Quotient determines where your customers are located
order: 4
---
Understanding where your customers are located is crucial for personalized marketing. Quotient uses multiple data sources to build an accurate picture of each customer's location.
## How We Determine Location
Quotient uses several sources to determine customer location, in order of priority:
### 1. Profile Location
When a customer makes a purchase on your Shopify store, we get their billing address. This is our most reliable source of location data since customers typically enter their real address for billing purposes. We also use saved default addresses from Shopify customer accounts.
For example, if Jane places an order and enters a billing address in Toronto, Ontario, Canada, we'll use this as her primary location. This helps ensure marketing emails she receives are relevant to her region.
### 2. Company Location
If a person is associated with a company in your CRM and we don't have their direct location, we'll infer their location from the company's address. This is useful for B2B scenarios where individual contact addresses may not be available.
For instance, if Bob works at TechStart Inc which is headquartered in Austin, Texas, and we don't have Bob's personal address, we'll use Austin as his location.
### 3. Analytics Events
As a last resort, we use location data from analytics events (like page views or clicks) captured during website visits or interactions with your marketing campaigns. While less precise than profile or company addresses, this helps us understand where visitors are browsing from before they provide any address information.
## How We Choose Between Sources
We follow a strict priority order to always use the most reliable location data available:
1. Profile location from orders or saved addresses (highest priority)
2. Company location inferred from associated company
3. Analytics event location (lowest priority)
This means that:
- If a customer has a known address, we'll always use that
- If they're associated with a company, we'll use the company's location
- Only if we have neither will we fall back to their analytics event location
As customers interact more with your store - from browsing to creating an account to making purchases - our understanding of their location becomes increasingly accurate.
## Viewing Location Source
On the person detail page, you'll see a small label next to the location indicating where the data came from: **Profile**, **Company**, or **Analytics**. Hover over the label to see more details about the source.
## Why Location Matters
Knowing where your customers are helps you:
- Send emails at the right time for their timezone
- Create location-specific campaigns (like "Free Shipping to California")
- Personalize content based on regional preferences
- Comply with regional marketing regulations
For example, you might want to:
- Send a special promotion just to customers in New York
- Ensure customers in Australia receive emails during their daytime
- Notify West Coast customers about a pop-up shop in Los Angeles
-- End of: /audience/location
-- Start of: /audience/people
---
title: People
description: A deep dive into customer profiles in Quotient
order: 2
---
A customer profile in Quotient is a comprehensive record of an individual customer's interactions with your business. Each profile helps you understand who your customers are and how they engage with your brand.
## What's in a Profile?
Every customer profile includes:
### 1. Basic Information
- Email address
- Name (if provided)
- Location and timezone
- Sign-up date
### 2. Shopping Activity
- Purchase history
- Total spend
- Average order value
- Cart activity
- Product browsing history
### 3. Email Engagement
- Email subscription status
- Open and click rates
- Email preferences
- Campaign responses
### 4. Custom Properties
- Tags
- Custom attributes
- Segment memberships
- Notes and annotations
### 5. Lead Score
- `leadScore` — an integer you assign to indicate how qualified or engaged a
person is. Higher values typically represent more qualified leads. Defaults to
`0` and can be set or updated via the API.
## Viewing People
To access customer profiles:
1. Navigate to the **[People](/s/most-recent-business/people)** page in your dashboard
2. Use the search bar to find specific customers
3. Click on any profile to view detailed information
## Working with Profiles
You can:
- Add notes to profiles
- Update custom properties
- View detailed engagement timelines
- Export profile data
- Create segments based on profile attributes
Ask Quotient to analyze profiles and identify patterns in customer behavior. Try asking it questions about specific profiles or customer groups.
## Setting Lead Score via the API
You can set or update a person's `leadScore` when creating or updating them via
`POST /api/v0/audience/people`:
```typescript
await client.audience.people.upsert({
emailAddress: "jane@example.com",
leadScore: 85,
});
```
`leadScore` is an integer (default `0`). Pass any non-negative integer to
reflect how qualified or engaged the person is. You can update it at any time
by upserting the person with a new value.
-- End of: /audience/people
-- Start of: /audience/segments
---
title: Segments
description: Creating and managing customer segments in Quotient
order: 3
---
Segments in Quotient let you group customers based on shared characteristics or behaviors. They provide a powerful foundation for targeted marketing, personalization, and customer flow management.
## Understanding Segments
A segment is a group of customers who match specific criteria you define. Segments update dynamically - as customers' data changes, they'll automatically move in and out of segments based on whether they meet the criteria.
Segments are particularly valuable for:
- Sending targeted emails
- Creating personalized customer flows
- Analyzing customer behavior patterns
- Prioritizing sales and support resources
## Creating Segments
Quotient offers two different approaches to create segments, letting you choose the method that works best for your needs:
1. **Visual Editor** - A drag-and-drop interface for creating segments with precise control
2. **Chat** - Ask Quotient to build segments from natural language descriptions
You can freely choose between these methods depending on your preferences, the complexity of your segment, and your comfort level with technical details. Both approaches create the same type of segments with identical capabilities.
### 1. Segment Editor
Navigate to **[Segments](/s/most-recent-business/segments)** to use our visual editor. The editor lets you combine multiple filters with logical operators to define your target audience.
#### Available Filter Types
##### Person Filters
- **Properties**: Filter based on custom properties you've defined (text fields, numbers, dates, etc.)
- **Email Subscription**: Target based on subscription status (subscribed, pending, unsubscribed)
- **Location**: Filter by country, region, city using standard codes
- **Timezone**: Filter by IANA timezone identifiers
##### Analytics Filters
- **Events**: Filter based on actions like page views, add to cart, email opens
- **Event Frequency**: Target based on number of occurrences (exactly, greater than, less than, between)
- **Time Periods**: Filter events within specific timeframes (hours, days, weeks)
##### Company Filters
- **Company Name**: Target customers from specific companies
- **Company Location**: Filter by company's geographical location
- **Company Industry**: Segment by industry categories
- **Company Revenue**: Filter by company revenue ranges with currency options
- **Company Size**: Segment by employee count (enterprise, SMB, startup)
##### Deal Filters
- **Deal Amount**: Filter based on deal values (high, mid, low value deals)
- **Deal Status**: Target based on deal stages (in progress, won, lost, early stage)
#### Logical Operators
Combine filters with:
- **AND**: Customers must match all conditions
- **OR**: Customers must match at least one condition
- **NOT**: Exclude customers who match specific conditions
### 2. Building Segments with Quotient
You can also ask Quotient to build segments through natural conversation. Simply describe the customers you want to target, and it will create the appropriate segment.
#### Example Prompts
**Basic Segments:**
- "Create a segment of customers with a lead score over 100"
- "Show me customers who haven't opened emails in 30 days"
- "Find customers in the Pacific timezone who bought recently"
**Company-Based Segments:**
- "Create a segment of customers from tech companies in California"
- "Find people from healthcare companies with more than 100 employees"
- "Segment customers from companies with over $10M in revenue"
**Deal-Based Segments:**
- "Create a segment of people with deals in the proposal stage"
- "Find customers with high-value deals over $50,000"
- "Segment people with won or lost deals in the last quarter"
**Complex Segments:**
- "Create a segment of customers from financial companies who opened our last email and have active deals"
- "Find customers in Canada with a lead score over 500 who viewed our product page at least 3 times"
- "Create a segment of enterprise customers who haven't engaged in 90 days and have active deals"
## Advanced Segmentation Strategies
### Behavioral Segmentation
Target customers based on how they interact with your business:
- **Engagement Level**: Highly engaged vs. at risk of churn
- **Purchase Frequency**: Frequent buyers vs. one-time customers
- **Product Interest**: Based on page views, searches, or cart additions
- **Email Response**: Regular openers vs. non-responders
### Lifecycle Segmentation
Target based on customer flow stage:
- **New Subscribers**: Recent signups who haven't purchased
- **First-Time Buyers**: Converted from prospects to customers
- **Repeat Customers**: Made multiple purchases
- **VIP Customers**: High lifetime value, frequent purchasers
- **At-Risk**: Declining engagement or purchase frequency
- **Lapsed**: Haven't engaged in a defined timeframe
### B2B Segmentation
For business customers, leverage company and deal data:
- **Industry Vertical**: Target specific industries with relevant messaging
- **Company Size**: Different approaches for enterprise vs. SMB
- **Deal Stage**: Tailor content based on sales funnel position
- **Deal Value**: Prioritize high-value prospects
- **Decision Maker Role**: Target based on position in company
## Using Segments
Once created, you can use segments in multiple ways:
### Email Broadcast Targeting
- Select specific segments as the audience for your email broadcast
- Exclude segments from receiving certain campaigns
- Create more personalized messaging for different customer groups
- A/B test campaign effectiveness across different segments
### Customer Flow Personalization
- Start flows for specific segments
- Create conditional branches in flows based on segment membership
- Customize flow actions based on which segments a customer belongs to
## Best Practices
### Segment Design
1. **Start with clear objectives**: Define what you want to achieve before creating segments
2. **Keep segments focused**: Create specific segments for clear use cases rather than trying to cover too many criteria in one segment
3. **Use descriptive names**: Name segments clearly to communicate their purpose (e.g., "High-Value Tech Companies" is better than "Segment A")
4. **Add detailed descriptions**: Document segment criteria and intended use cases
### Segment Management
1. **Update regularly**: Review and update your segments periodically to ensure they remain relevant
2. **Archive unused segments**: Keep your workspace clean by archiving segments you no longer need
3. **Test before sending**: Always preview your segment size and composition before using it in campaigns
4. **Start small**: When using a new segment, test with a small campaign before scaling
5. **Track segment performance**: Monitor how different segments respond to your marketing
### Optimization Strategies
1. **Refine based on performance**: Adjust segment criteria based on campaign results
2. **Progressive profiling**: Build more detailed segments over time as you gather more customer data
3. **Segment hierarchies**: Create broader segments for general campaigns and more specific sub-segments for targeted messaging
4. **Combine behavioral and demographic data**: The most effective segments often use both types of information
## Troubleshooting
### Common Issues
- **Empty segments**: If a segment contains no users, check for overly restrictive criteria or data issues
- **Oversized segments**: Very large segments may need more specific criteria for effective targeting
- **Slow-updating segments**: Some segment criteria may take time to evaluate for large customer bases
- **Conflicting criteria**: Using contradictory conditions may create unexpected results
### Getting Help
Ask Quotient to help you:
- Diagnose issues with existing segments
- Optimize segment criteria for better targeting
- Suggest new segmentation strategies based on your business goals
- Convert natural language descriptions into technical segment definitions
-- End of: /audience/segments
-- Start of: /email/email-status
---
title: Email Status
description: What Email Status means inside of Quotient
---
When you send email with Quotient, each email will have a status that tracks
it's delivery and engagement. Please see the table below for
an overview of each status and its description:
Status
Description
`QUEUED`
Quotient has queued the email to be sent
`SENT`
Quotient is attempting to deliver the email to the recipient
`ERROR`
An error prevented Quotient from sending the email
`DELIVERED`
Quotient delivered the email to the recipient
`DELIVERY_DELAYED`
Quotient could not deliver the email due to a temporary issue; Quotient
will continue attempting delivery
`BOUNCED`
The recipient's mailbox permanently rejected the email
`OPENED`
Quotient delivered the email and the recipient has opened it
`CLICKED`
Quotient delivered the email, the recipient has opened it, and clicked
on a link inside of it
`COMPLAINED`
Quotient delivered the email and the recipient marked it as spam
Please note that the status of an email reflects the most recent event to occur
to it, so if a recipient opens an email, clicks a link inside of it, and then
marks the email as spam, Quotient will mark this email as `COMPLAINED`.
-- End of: /email/email-status
-- Start of: /email/index
---
title: Email
description: Send email broadcasts and automated emails with Quotient
order: 5
---
Email is one of the most important tools in your marketing toolkit. Email marketing remains one of the most effective ways to nurture leads, build relationships with customers, and drive sales for your business.
Quotient lets you craft, send, and measure emails — and you can ask Quotient to handle any part of the process for you.
## Core Concepts
**Broadcasts**
[Broadcasts](/s/most-recent-business/email-broadcasts) are a one-time blast email to a portion of your audience. A broadcast is made up of...
- **Content:** HTML content that recipients will see in their inbox. You can edit the content of the email directly in the email editor, or you can ask Quotient to make updates on your behalf.
- **Metadata**: Additional data about the email including the subject line, preview text, and from address. Setting metadata correctly helps improve the performance and deliverability of emails.
- **Send Time:** The time at which the email will begin sending to recipients. We say "begin sending" because not all of the emails will be sent immediately at the send time. To improve deliverability, we send the emails in batches over the course of several minutes.
Email broadcasts follow a three-stage lifecycle: **Draft** → **Scheduled** → **Launched**. You can either schedule a broadcast for a specific time in the future or launch it immediately. Once the broadcast is launched and emails start sending, it moves to the "Launched" status. Once launched, broadcasts can no longer be modified - this is different from blogs, which can be re-published after going live. Once an email has been sent, you can't change it.
**Audience**
“Audience” refers to the people you've designated to receive an email broadcast. The audience can be made up of both **lists** and **segments**. You can learn more about the difference in the article on Building Your Audience.
You can include multiple lists and/or segments in the audience for your broadcast. If a person appears in multiple, Quotient will deduplicate and ensure that they only receive the email once.
**Analytics**
If you're using Quotient to send email, we will automatically track the performance of your broadcasts, including:
1. **Delivery Rate:** Of the emails sent, how many were successfully delivered.
2. **Open Rate:** Of the emails delivered, how many were opened by the recipient.
3. **Click Rate:** Of the emails opened, how many people clicked on a link leading to your website.
**Templates**
[Templates](/s/most-recent-business/email-template) are reusable blueprints of email content. It's important to understand that templates are not directly sent out - they must either be cloned into a broadcast or used as part of a flow. There are two different ways you can use templates:
1. **Starting Point for Broadcasts:** It's common to clone templates as a starting point for email broadcasts. This ensures that all email broadcasts maintain a consistent structure and look. For example, you might have a template for your weekly newsletter, and each week you would clone it and replace the content for that week.
2. **In Automated Flows:** Templates can also be used inside of **flows**. In Quotient, flows are automated processes that can send email to customers based on pre-defined schedules or triggers. A common example would be sending new users an automated welcome series after they sign up for your product. To learn more about flows, check out the [Flows](/docs/flow) article.
**Components**
[Components](/s/most-recent-business/email-components) are reusable blocks of email content that can be used in both broadcasts and templates and stay automatically up-to-date. The most common examples of components are **headers and footers**.
Typically you want your headers and footers to stay consistent across all your emails, and if you change them, you want them to update automatically in all the templates/broadcasts where they're used.
**Email Domains**
[Email domains](/s/most-recent-business/email-settings) are the domains that your emails are sent from (e.g., `updates@yourcompany.com`). Using a custom email domain is crucial for deliverability and brand consistency. It helps ensure your emails reach the inbox rather than being marked as spam.
Quotient helps you set up and verify custom email domains with proper DNS configuration. You can learn more about setting up custom DNS in our [Custom DNS guide](/docs/email/dns).
## Creating Emails with Quotient
Ask Quotient to help you create any of the above — broadcasts, templates, components, and finding the right audience for each email.
Quotient draws on its memory of your business, so the content it creates will be consistent with your brand's voice and messaging strategy.
Here are some tips for getting the most out of Quotient when working with email:
- When setting up your Quotient account, ask Quotient to create a standard header, footer, and "base template", and ask it to remember to always use those as a starting point. This helps keep your emails consistent and on-brand, and ensures that Quotient doesn't have to reinvent the wheel with each new broadcast.
- Formatting emails is notoriously difficult due to the esoteric requirements of legacy email clients. We recommend asking Quotient to take the first stab at creating the content. From there you can use the editor to tweak copy and styles. This is often easier than creating the formatting yourself.
- You can upload screenshots of emails from other brands to the chat panel and ask Quotient to copy them or use them as inspiration.
- Emails should always have CTAs that lead to pages on your website where readers can learn more and hopefully enter your conversion funnel. To set CTAs up properly, Quotient needs to understand your website structure. Ask Quotient to crawl your website and save a memory describing it, which it can then use to construct links.
## Inbound vs. Outbound Email
It's important to note that Quotient is used for **inbound email marketing**, not **outbound email marketing.** Inbound marketing targets people who have _already_ shown interest in your product - like signing up for a demo or newsletter - whereas outbound marketing, also known as "cold email", proactively reaches out to people regardless of their expressed interest.
There are a few key differences between inbound and outbound email marketing:
Inbound
Outbound
Typically comes from a company email address, e.g.
updates@mail.company.com
Usually comes from an individual salesperson, e.g. max@getquotient.ai
Emails are not meant to be replied to and may come from a "noreply"
address
Emails are meant to be replied to - the goal is to start a conversation
with the salesperson
Emails may be somewhat personalized, but typically are sent as
"broadcasts", i.e. sending the same email to many people
Emails are often highly personalized and tailored to each individual
prospect
Emails typically contain rich formatting, images, and CTAs
Emails are usually written in plain text
If you’re looking for an outbound email marketing platform, here are a few we recommend:
- [SalesLoft](https://www.salesloft.com/)
- [Apollo](https://www.apollo.io/)
- [Outreach](https://www.outreach.io/)
- [Unify](https://www.unifygtm.com/)
## Next Up
-- End of: /email/index
-- Start of: /email/suppression
---
title: Suppression & Bounce
description: Understanding email suppression and bounce handling.
---
Quotient uses a combination of user-submitted manual suppression and bounce detection to manage email suppression lists.
When an email address is added to a business's suppression list, Quotient will
automatically suppress the email address.
## Manual Suppression
A Quotient user can manually suppress an email address via the `manuallySuppressed` field when uploading an email list. Please see
the [building-email-list](/docs/email/building-email-list#3.-manual-upload-and-quick-add) guide for more information.
## Automatic Suppression
Quotient allows users to upload all syntatically valid email addresses, but
will suppress email to email addreses with invalid top-level domains (TLDs)
as well as to email addresses that end in IANA special-use domains.
**For more information, see the resources below:**
- [IANA List of Top-Level Domains](https://data.iana.org/TLD/tlds-alpha-by-domain.txt)
- [IANA Special-Use Domain Names](https://www.iana.org/assignments/special-use-domain-names/special-use-domain-names.xhtml)
## Bounces
An email "bounces" when it is not delivered to the inbox of the recipient, or
if the email is rejected by the recipient's email provider. If your Quotient
account has a large number of bounces, this can negatively impact deliverability.
In order improve deliverability, Quotient monitors and detects email bounces for all emails sent via Quotient.
### Bounce Types and Detection
Quotient monitors and detects email bounces for all emails sent via Quotient.
There are two types of bounces and a number of subtypes:
- **Hard Bounce:** A hard bounce is a permanent failure to deliver an email.
- **General**: The email provider sent a hard bounce message
- **Domain Does Not Exist**: The email address domain does not exist
- **User Does Not Exist**: The email address user does not exist
- **Blocked**: Your domain is blocked by the recipient's email provider
- **Soft Bounce:** A soft bounce is a temporary failure to deliver an email.
- **General**: The email provider sent a general bounce message, in which case the email
address may not bounce again in the future
- **Mailbox Full**: The recipient's mailbox is full
- **Message Length & Size**: The message is too long or to large
- **Rate Limited**: The provider is receiving too many emails within a given time period and is temporarily rejecting new ones
- **Content**: The content of the message is rejected by the recipient's email provider for spam reasons
- **Sender Reputation**: The provider determines your domain has poor sender reputation
- **DNS Issues**: Temporary DNS failures or routing problems
Email addresses that receive **Hard Bounces** are automatically suppressed and will not receive any emails. These email addresses are added to Quotient's global suppression list, which is used for all emails across all businesses. This ensures that emails are not sent to email addresses that are known to bounce.
Email addresses that receive **Soft Bounces** are not suppressed until they
exceed our soft bounce occurence threshold of 7 for a given business. At that point, they are added to the business's suppression list.
### Suppression Lists
Quotient maintains a global suppression list for hard bounces. This means that once an email address is suppressed due to bouncing, it will remain suppressed for all emails across all businesses, ensuring that emails are not sent to email addresses that are known to bounce.
Quotient also maintains a business-specific suppression list for soft bounces
and manually suppressed emails. This means that once an email address is suppressed due to bouncing or manual suppression, it will remain suppressed for the duration of the business's Quotient account.
-- End of: /email/suppression
-- Start of: /email/unsubscribe
---
title: Unsubscribe
description: How email unsubscribes work and how to customize the unsubscribe page.
---
It is crucial to provide email recipients with the ability to unsubscribe from
your email broadcasts in order to maintain a good sender reputation.
Giving recipients the ability to unsubscribe from your email broadcasts:
- reduces the likelihood that your emails are marked as spam
- improves deliverability for your email broadcasts
In Quotient, use the **Unsubscribe Link** component in your email footer to give
recipients the option to unsubscribe from your emails. Quotient also includes a
`List-Unsubscribe` header on outgoing emails, so many inbox providers can show a
native one-click unsubscribe button.
- **One-click unsubscribe (inbox provider button):** The inbox provider calls
Quotient's unsubscribe endpoint. The person is unsubscribed without needing to
load a confirmation page.
- **Footer link unsubscribe:** The person lands on your branded unsubscribe page
and confirms by clicking the unsubscribe button.
## What Happens When Someone Unsubscribes
Quotient immediately updates that person's email subscription status to `UNSUBSCRIBED`.
From that point forward, they are excluded from marketing sends, even if they
still appear in a list or segment.
## Subscription Statuses
State
Description
`SUBSCRIBED`
Opted in. Will receive marketing emails.
`NOT_SUBSCRIBED`
Has not opted in. Will not receive marketing emails.
`UNSUBSCRIBED`
Explicitly opted out. Will not receive marketing emails.
`PENDING`
Subscription pending confirmation.
## Customizing the Unsubscribe Page
You can customize the copy on your unsubscribe page in [Email
Settings](/s/most-recent-business/settings/email-settings):
- **Dark mode** — enables a dark unsubscribe page treatment
- **Show logo** — controls whether your brand logo appears on the page
- **Accent color** — sets the unsubscribe button color
- **Heading** — defaults to "Unsubscribe from [Brand Name]"
- **Subheading** — defaults to "You're currently subscribed to emails from
[Brand Name]."
- **Button text** — defaults to "Unsubscribe"
Quotient also provides a preview so you can check how the page looks before
saving changes.
-- End of: /email/unsubscribe
-- Start of: /integrations/index
---
title: Integrations
description: Connect Quotient to the other tools you use to run your marketing
order: 700
---
Quotient works best when it can see the rest of your marketing stack. Connect
your CRM and Quotient keeps your audience in sync with it. Connect your website
and your blog posts publish straight from Quotient. Connect Zoom and your
webinar registrations and attendance flow into your campaigns.
You can connect any of these tools from
[Settings → Integrations](/s/most-recent-business/settings/integrations). Each
guide below walks through setup and explains what gets synced.
Looking to connect Quotient to an AI app, or give Quotient access to another
tool through MCP? See [MCP](/docs/mcp).
-- End of: /integrations/index
-- Start of: /integrations/slack
---
title: Slack
description:
Connect Slack to receive notifications and interact with Quotient
directly from your workspace
order: 5
---
Quotient's Slack integration lets you receive notifications and interact with
Quotient directly from your Slack workspace. There are two main capabilities:
1. **Notifications** — Receive updates about your marketing activities directly
in Slack
2. **Talking to Quotient** — Chat with Quotient without leaving
Slack
## Getting Started
To enable the Slack integration, navigate to **[Integrations > Slack](/s/most-recent-business/integrations)** in
Quotient and click **Connect to Slack**. You'll be prompted to authorize
Quotient to access your Slack workspace. Once connected, you can start receiving
notifications and chatting with Quotient immediately.
## Notifications
Quotient can send you notifications about important events—like when it
completes a task or needs your input—directly to Slack. These notifications
arrive as direct messages from the Quotient bot, keeping your channels
clutter-free while ensuring you never miss an important update.
### Configuring Notification Preferences
You can customize which notifications you receive in Slack from your
notification preferences. Navigate to **[Settings > Notifications](/s/most-recent-business/preferences?tab=notifications)** to control
exactly what types of updates Quotient sends you.
For each notification type, you can choose:
- **Immediate** — Receive the notification in Slack right away
- **None** — Don't send this notification type to Slack (you may still receive
it via email)
## Talking to Quotient in Slack
You can interact with Quotient directly from any Slack channel or
direct message—just mention **@Quotient** and start chatting.
### How It Works
When you mention @Quotient in Slack, here's what happens:
1. **Quotient processes your request** — Your message is sent to Quotient, which
works on your request
2. **A thread is created in Quotient** — The conversation becomes a thread in
Quotient that you can view anytime
3. **You get a response in Slack** — Once processing is complete, Quotient
replies in the same Slack thread with a summary of what was accomplished
The entire conversation—including all the work Quotient did—is visible in
the Quotient app. Just click the "View in Quotient" link in the response to see the full
thread.

### Using Conversation Context
When you mention @Quotient mid-thread, it can see the full conversation history
leading up to your message. This means you can discuss ideas with colleagues
first, then bring Quotient in to execute.
For example:
Marc
I have an idea for a new campaign. We should target our enterprise
customers with content about our new analytics features.
Alex
Love it. Let's do a blog post and some LinkedIn posts from our company
page.
Marc
Perfect.{" "}
@Quotient{" "}
make it happen!
Quotient{" "}
APP
Done! I've created a campaign called "Enterprise Analytics Launch" with:
Blog post: "5 Ways Advanced Analytics Transforms Enterprise Marketing"
Because Quotient can see the entire conversation, it understands exactly what
you're asking for without you having to repeat the context.
### Continuing the Conversation
If you need to make changes or ask follow-up questions, just reply in the same
Slack thread and mention @Quotient again. Your follow-up will be added to the
same Quotient thread, preserving the full context of your conversation.
### File Attachments
You can attach files to your messages when chatting with Quotient in Slack. Any
file type that Quotient supports—such as images, PDFs, and documents—will be
processed. Unsupported file types are simply ignored.
### Tips for Getting the Most Out of Slack
Here are a few tips to help you work effectively with Quotient in Slack:
- **Be specific in your requests.** The more context you provide, the better
Quotient can help. Instead of "create a campaign," try "create a campaign for
our product launch next month targeting enterprise customers."
- **Use threads for context.** When you mention @Quotient in an existing thread,
it can see the full conversation history. Use this to your advantage by
discussing ideas with your team first, then bringing Quotient in to execute.
- **One request at a time.** Like most AI applications, Quotient processes one
message at a time. If you send a follow-up while Quotient is still working on
your previous request, it may ask you to wait until it's finished.
- **Check the full thread in Quotient.** The response you see in Slack is a
summary. For the full details of what Quotient did—including any drafts it
created—click through to view the thread in Quotient.
## Troubleshooting
### Quotient isn't responding to my @mention
Make sure Quotient has been added to the channel where you're trying to mention
it. In private channels, you may need to invite Quotient first using
`/invite @Quotient`.
### I'm not receiving notifications in Slack
Check your notification preferences in **[Settings > Notifications](/s/most-recent-business/preferences)** to ensure
Slack notifications are enabled for the notification types you want to receive.
Also verify that your Slack integration is still connected in **[Integrations >
Slack](/s/most-recent-business/integrations)**.
### My file attachment wasn't processed
Quotient only processes supported file types. If your file wasn't processed, it
may be an unsupported format. Try converting it to a common format like PDF or
PNG.
-- End of: /integrations/slack
-- Start of: /integrations/zoom
---
title: Zoom
description:
Connect Zoom to create meetings and webinars from Quotient, sync
registration and attendance, and run follow-up campaigns
order: 4
---
Quotient's Zoom integration lets you plan webinars and meetings as marketing
events, keep registration in sync with Zoom, pull attendance after the session
ends, and use that data in segments and Flows.
This page covers how to add the app, use it, and remove it.
## Prerequisites
- A Quotient workspace
- A Zoom account that can authorize apps (admin or owner is typical)
- For **Zoom Webinars** (registration pages, panelists, one-to-many broadcast): a
Zoom plan with the Webinar add-on. Without it, use **Meetings** instead
(workshops, roundtables, smaller interactive sessions)
## Adding the app
Install from Quotient. Marketplace users land on the [Zoom integration
page](/integrations/zoom) and continue into the product to connect.
### Step 1: Open Zoom in Integrations
1. Sign in to Quotient
2. Go to **[Settings → Integrations](/s/most-recent-business/settings/integrations)**
3. Find the **Zoom** card and click **Connect**
You can also open **[Zoom integration settings](/s/most-recent-business/settings/integrations/zoom)**
directly.
### Step 2: Authorize in Zoom
Quotient redirects you to Zoom's authorization page. Sign in if prompted, review
the permissions Quotient is requesting, and approve.
Quotient asks Zoom for permission to:
- Create and read meetings and webinars
- List existing meetings and webinars so you can link them
- Add and read webinar registrants
- Read past meeting and webinar participants
- Read the connected Zoom user (connection health and host exclusion)
OAuth access and refresh tokens are stored encrypted at rest (AES-256-CBC). They
are not stored in plaintext.
### Step 3: Confirm the connection
After you approve, Zoom sends you back to Quotient. On the Zoom integration
card you should see **Connected**.
If authorization fails, see [Troubleshooting](#troubleshooting).
## Using the app
All Zoom work in Quotient lives under **[Marketing
Events](/s/most-recent-business/marketing-events)**.
### Create a Zoom session
When you create a marketing event, you can:
- **Create a Meeting** — a standard Zoom meeting tied to the event. Use this for
workshops, roundtables, or smaller interactive sessions.
- **Create a Webinar** — Zoom's webinar format with registration, panelists, and
broadcast. Requires the Zoom Webinar add-on.
- **Connect an existing meeting** — link a meeting you already created in Zoom
to a Quotient event. Quotient lists meetings and webinars from the connected
account so you can pick one.
After you create or link a session, Quotient stores the Zoom event ID, schedule,
and join / registration URLs on the marketing event.
### Registration sync
- **Push to Zoom** — when someone registers for the event in Quotient, Quotient
can add them as a Zoom registrant.
- **Pull from Zoom** — registrations that came in through Zoom's registration
page are imported into Quotient (email, name, status).
- **Bidirectional sync** — keep both lists aligned. Zoom webhooks also notify
Quotient when a registration is created or cancelled.
Registrants are stored as People and event participants in Quotient so you can
email them and include them in Flows.
### Attendance tracking
After the session ends, Quotient pulls attendance from Zoom (join time, leave
time, duration) and updates participant status to **Attended** or **No Show**.
The host is excluded from lead / participant sync when Quotient can resolve the
host user.
You can then:
- Segment attendees vs no-shows for follow-up email
- Build audience filters from event participation (for example, “attended this
webinar”)
- Trigger [Flows](/docs/flow) on marketing-event status changes (registered,
attended, no-show)
- Report on attendance rate, no-show rate, and duration
## Removing the app
Remove the connection in **both** places if you want Zoom and Quotient fully
disconnected.
### In Quotient
1. Go to **[Zoom integration settings](/s/most-recent-business/settings/integrations/zoom)**
2. Open the options menu (⋯) on the Zoom card
3. Click **Delete Integration** and confirm
This deletes the Zoom connection for that workspace, including encrypted OAuth
tokens. Quotient can no longer create Zoom sessions, sync registrants, or pull
attendance for that account.
Marketing events, people, and historical attendance records already in Quotient
are not automatically deleted. Disconnecting stops new Zoom API access; it does
not wipe your event history. Remove those records separately in Quotient if you
need them gone.
To reconnect later, click **Connect** again and complete Zoom authorization.
### In Zoom
If you installed or authorized the app from Zoom as well:
1. Sign in to the [Zoom App Marketplace](https://marketplace.zoom.us/)
2. Click **Manage** → **Added Apps**, or search for **Quotient**
3. Open the app and click **Remove**
4. Confirm
After removal, Quotient cannot call Zoom APIs for that Zoom account until
someone reconnects. Existing Quotient event and contact data is unchanged unless
you delete it in Quotient.
## Troubleshooting
**Connect never finishes / you don't return to Quotient**
- Allow pop-ups for getquotient.ai and zoom.us
- Try a private browser window
- Confirm you approved the correct Zoom account
**Connected, then it drops**
Zoom invalidates tokens if the same Zoom account is connected from another
device, browser, or environment (for example production and staging). Disconnect
and reconnect, or use separate Zoom accounts per environment.
**Can't create a webinar**
The connected Zoom account needs the Webinar add-on. Create a **Meeting**
instead, or upgrade the Zoom plan.
**Registrants or attendance don't show up**
- Confirm the marketing event is linked to the right Zoom meeting or webinar ID
- Wait until the session has ended for attendance (past participants)
- Reconnect Zoom if the integration health check fails
**Need help?** Email [support@getquotient.ai](mailto:support@getquotient.ai) or
use [Support](/support).
-- End of: /integrations/zoom
-- Start of: /mcp/index
---
title: MCP
description: How Quotient works with the Model Context Protocol (MCP) — both connecting tools to Quotient and using Quotient from other AI apps.
order: 750
---
[MCP (Model Context Protocol)](https://modelcontextprotocol.io/) is an open standard that lets AI apps securely connect to other software. Think of it as a universal adapter: once a tool supports MCP, any AI app can plug into it.
Quotient works with MCP in **two directions**, and it's worth knowing which one you want before you dig in:
* **Connect tools _to_ Quotient.** Give Quotient access to outside tools — like GitHub, Notion, or Ahrefs — so it can use them while you chat. For example, Quotient can read your latest pull requests and draft a changelog. (In technical terms, Quotient acts as an MCP *client*.)
* **Use Quotient _from_ other AI apps and agents.** Connect Quotient to AI apps — like ChatGPT, Claude, Cursor, or Codex — so they can do work in your Quotient account on your behalf. For example, Claude Code can create a campaign or publish a social post for you. (In technical terms, Quotient acts as an MCP *server*.)
The simplest way to keep them straight: in the first case, **Quotient reaches out** to other tools; in the second, **other apps reach in** to Quotient.
## Pick Your Path
-- End of: /mcp/index
-- Start of: /sdk/analytics
---
title: Analytics
description: Track page views and custom events with the Quotient analytics API
order: 4
---
## Overview
Use the analytics API to connect activity on your site, such as viewing a page
or custom event that you define, to the marketing that brought each visitor
there.
The client SDK (`@quotientjs/client` or `@quotientjs/react`) runs in the
browser. It adds the visitor's session, attribution, and identity to each event.
The server SDK (`@quotientjs/server`) tracks backend events about a person you
already know.
| Endpoint | API Key | SDK | Method |
| --------------------- | ------- | ---------- | --------------------------------- |
| Track a browser event | public | Client SDK | `client.analytics.event(event)` |
| Track a server event | private | Server SDK | `quotient.analytics.event(event)` |
## Track a Client Event with @quotientjs/client
#### `client.analytics.event(event)`
> `POST /api/v0/analytics/web`
>
> **Auth:** public key · scope: `ANALYTICS_WRITE`
Every client event includes the current session ID, device ID, browser
fingerprint, page URL, and attribution. Attribution comes from the `utm_*` and
`qt_*` parameters on the visitor's incoming URL and lasts for the current
session. If a tagged link or `client.audience.people.upsert()` identifies the
visitor, the SDK includes their `personId` too. You only provide the event.
| `eventType` | Extra fields | Description |
| ------------ | ----------------------- | ---------------------------------------------------------------------------- |
| `"pageView"` | none | A page view. The SDK tracks these automatically by default |
| `"custom"` | `customEventId: string` | The ID of an event defined by your business, such as `"completedOnboarding"` |
```typescript
// Page view (usually automatic; see Auto-Tracking below)
await client.analytics.event({
eventType: "pageView",
});
// Custom event
await client.analytics.event({
eventType: "custom",
customEventId: "completedOnboarding",
});
```
**Returns:** `void`
Register each custom event in Quotient before sending it. Pass its immutable
event ID as `customEventId`; the API rejects IDs that have not been registered
for your business.
Pass `idempotencyKey` on any event to avoid recording it twice, such as when a
retry resends the same request. Quotient checks for a matching key from your
business for 24 hours; a duplicate within that window is dropped instead of
recorded again. This check depends on our caching layer being reachable; a
rare outage there can still let a duplicate through.
## Track a Server Event
#### `quotient.analytics.event(event)`
> `POST /api/v0/analytics/server`
>
> **Auth:** private key · scope: `ANALYTICS_WRITE`
Use a server event when an activity that matters to your marketing analytics
does not take place in a browser. These activities often happen in webhooks,
OAuth callbacks, scheduled jobs, or other backend code. For example, you might
track when a free trial expires, a customer upgrades their plan, or a user
completes onboarding.
The server API currently accepts custom events only. Each event must be about a
known person, so include their `personId`, the person's identifier in Quotient.
It must belong to an existing person in your business. Because the event does
not come from a browser, the SDK cannot add a browser session or its attribution
automatically. Pass the visitor's browser context yourself as `browserContext`
(see
[Server-Side Conversions](/docs/analytics/custom-events/server-side-conversions)),
or attribute the event to a campaign directly with `campaignId`.
| Field | Type | Required | Description |
| ---------------- | ---------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `eventType` | `"custom"` | Yes | Server events are always custom events today |
| `personId` | `string` | Yes | The Quotient identifier of the person this event is about |
| `customEventId` | `string` | Yes | A custom event ID already registered for your business |
| `campaignId` | `string` | No | Attributes the event to a specific campaign |
| `browserContext` | `BrowserContext` | No | What the browser SDK knew about the visitor when the conversion happened, read from the `qt_browser_context` cookie or `client.getBrowserContext()` |
| `idempotencyKey` | `string` | No | Prevents recording the same event twice, such as when a retry resends the same request. Quotient checks for a matching key from your business for 24 hours (a rare caching-layer outage can still let a duplicate through) |
```typescript
await quotient.analytics.event({
eventType: "custom",
personId: "person_abc123",
customEventId: "upgradedPlan",
});
```
**Returns:** `void`
## Read the Browser Context
#### `client.getBrowserContext()`
Returns what the browser SDK currently knows about the visitor: device, session,
person, referrer, and attribution. The SDK also writes the same object to the
`qt_browser_context` cookie on every tracked event, so a server on your own
domain can read it without any call from the page.
```typescript
const browserContext = client.getBrowserContext();
```
**Returns:** `BrowserContext`
Use it when a conversion completes on a server that the cookie cannot reach,
such as an API on another domain, and pass the object along in your request
body.
[Server-Side Conversions](/docs/analytics/custom-events/server-side-conversions)
walks through both paths and the shape of the object.
## Auto-Tracking with React
`QuotientProvider` tracks a page view when your app loads and after each
navigation. Auto-tracking is on by default, so no additional setup is needed.
```tsx
```
If another tool on the page already sends Quotient page views, pass
`autoTrackPageViews={false}` to avoid counting each navigation twice.
See the [React SDK](/docs/sdk/react) article for full provider setup. For manual
tracking, use `client.analytics.event()` via the `useQuotient()` hook.
## Common Patterns
### Custom Event Tracking
```javascript
import { useQuotient } from "@quotientjs/react";
function CompleteOnboardingButton() {
const { client } = useQuotient();
const handleClick = async () => {
await completeOnboarding();
void client?.analytics.event({
eventType: "custom",
customEventId: "completedOnboarding",
});
};
return ;
}
```
### Page View Tracking in a SPA
If you're not using the React SDK's `autoTrackPageViews`, you can track route
changes manually:
```javascript
import { useEffect } from "react";
import { useLocation } from "react-router-dom";
import { useQuotient } from "@quotientjs/react";
function PageTracker() {
const location = useLocation();
const { client } = useQuotient();
useEffect(() => {
void client?.analytics.event({ eventType: "pageView" });
}, [location, client]);
return null;
}
```
## Next Steps
-- End of: /sdk/analytics
-- Start of: /sdk/api-keys
---
title: API Keys
description: Understanding and managing API keys for Quotient
order: 1
---
API keys are the primary authentication mechanism for accessing the Quotient API. This guide covers the different key types, their use cases, and how to set them up correctly.
## Key Types
Quotient uses a two-tier API key system designed for different security contexts:
### Public Keys (`pk_*`)
Public keys are designed for **client-side applications** where the key is exposed in browser code or mobile apps.
**Characteristics:**
- Prefix: `pk_`
- Length: 20-40 characters after prefix
- Safe to expose in client-side code
- Limited set of scopes supported
- Origin-restricted for security
- Cannot access sensitive operations
**Allowed Endpoints:**
- `POST /api/v0/analytics` - Track events
- `POST /api/v0/audience/people` - Upsert people
- `POST /api/v0/audience/companies` - Upsert companies
- `POST /api/v0/audience/lists/:slug/people` - Add people to a list
- `DELETE /api/v0/audience/lists/:slug/people` - Remove people from a list
- `GET /api/v0/blog/*` - Retrieve blogs, authors, and tags
- `POST /api/v0/flow/:id/trigger` - Trigger a programmatic flow
- `GET /api/v0/whoami` - Verify key configuration and get client context
**Use Cases:**
- Integrating signup forms with Quotient
- Centralizing client-side analytics
- Publishing blogs and content managed by Quotient on your website
- Triggering flows from your frontend
### Private Keys (`sk_*`)
Private keys are for **server-side applications** where the key can be kept secret.
**Characteristics:**
- Prefix: `sk_`
- Length: 20-40 characters after prefix
- Must be kept secret
- Full support for all scopes
- IP address restrictions (coming soon)
**Use Cases:**
- Server-to-server integrations
- Backend services
- Data imports/exports
- Administrative operations
> **Security Warning**: Never expose private keys in client-side code, version control, or public repositories.
## Key Security Features
### Origin Restrictions (Public Keys)
Public keys can be restricted to specific origins to prevent unauthorized use if the key is stolen.
**How it works:**
1. The API checks the `Origin` header of incoming requests
2. Compares against the allowed origins list
3. Rejects requests from unauthorized origins
**Origin formats supported:**
- **Wildcard**: `*` - Allow any origin (not recommended for production)
- **Domain**: `example.com` - Matches example.com and all subdomains
- **Subdomain**: `app.example.com` - Matches only this specific subdomain
- **With protocol**: `https://app.example.com` - Matches exact protocol and domain
- **With port**: `localhost:3000` - Matches localhost on specific port
**Examples:**
```
✅ Valid origins:
- example.com
- app.example.com
- subdomain.example.com
- localhost:3000
- https://app.example.com:8080
❌ Invalid origins:
- http:// (protocol only)
- :3000 (port only)
- .com (TLD only)
```
**Matching rules:**
- `example.com` matches:
- `https://example.com`
- `https://www.example.com`
- `https://app.example.com`
- `app.example.com` matches only:
- `https://app.example.com`
- `http://app.example.com`
### Scopes
API keys support granular permission scopes. When creating a key, you assign
one or more scopes to limit what it can access. Scopes are required — there
is no implicit "full access" default; choose the smallest set your
integration needs.
| Scope | Description |
|---|---|
| `ANALYTICS_READ` | Read analytics data |
| `ANALYTICS_WRITE` | Track events |
| `AUDIENCE_PERSON_READ` | Read people |
| `AUDIENCE_PERSON_WRITE` | Create and update people |
| `AUDIENCE_COMPANY_READ` | Read companies |
| `AUDIENCE_COMPANY_WRITE` | Create and update companies |
| `AUDIENCE_LIST_READ` | Read lists and list members |
| `AUDIENCE_LIST_WRITE` | Create and update lists, add and remove members |
| `BLOG_READ` | Read blogs, authors, and tags |
| `BLOG_WRITE` | Create and update blog content |
| `FLOW_TRIGGER` | Trigger programmatic flows |
| `MEMORY_READ` | Read memory documents |
| `MEMORY_WRITE` | Create and update memory documents |
### Key Expiration
Keys can have optional expiration dates for temporary access:
- Useful for trials or time-limited integrations
- Automatically rejected after expiration
- No impact on existing data
### Usage Tracking
Each key tracks:
- **Last used**: Timestamp of most recent API call
- **Created at**: When the key was generated
- **Created by**: User who created the key
## Creating API Keys
### Via Dashboard
For now, you can only create public keys via the dashboard.
1. Navigate to **[Settings → Developers](/s/most-recent-business/settings/developers)** in your business dashboard
2. Click **"Create API Key"**
3. Configure the key:
- **Name**: Descriptive identifier (e.g., "Production Web App")
- **Description**: Optional details about usage
- **Allowed Origins**: Domains that can use this key
### Best Practices for Key Creation
#### Security Recommendations
1. **Principle of Least Privilege**
- Create separate keys for different environments
- Use the most restrictive origin settings possible
2. **Origin Restrictions**
- Never use `*` (wildcard) in production
- Be specific with subdomains
- Include ports when necessary
## Using API Keys
### In Requests
Include the API key in the `Authorization` header:
```bash
curl -X POST https://www.getquotient.ai/api/v0/analytics/web \
-H "Authorization: Bearer pk_test_1234567890abcdef" \
-H "Content-Type: application/json" \
-d '{"eventType": "pageView"}'
```
### With SDKs
```javascript
// JavaScript SDK
const quotient = await QuotientClient.init({
apiKey: 'pk_test_1234567890abcdef'
});
// React SDK
```
## Next Steps
-- End of: /sdk/api-keys
-- Start of: /sdk/audience
---
title: Audience
description: Manage people, companies, and lists using the Quotient SDK
order: 5
---
## Overview
The audience API lets you manage people, companies, lists, and custom
properties.
Both the client and server SDKs expose the audience API under `audience.*`.
The client SDK includes `audience.people` only. The server SDK adds
`audience.companies`, `audience.lists`, and `audience.properties`.
| Endpoint | API Key | Server SDK | Client SDK |
|---|---|---|---|
| Upsert person | public or private | `audience.people.upsert()` | `audience.people.upsert()` |
| Identify a person | public or private | `audience.people.identify()` | `audience.people.identify()` |
| Register for an event | public or private | `audience.people.registerForEvent()` | `audience.people.registerForEvent()` |
| Subscribe to email | public or private | `audience.people.subscribeToEmail()` | `audience.people.subscribeToEmail()` |
| Upsert company | public or private | `audience.companies.upsert()` | — |
| Upsert list | private only | `audience.lists.upsert()` | — |
| List all lists | private only | `audience.lists.list()` | — |
| Get a list | private only | `audience.lists.get()` | — |
| List people in a list | private only | `audience.lists.listPeople()` | — |
| Add people to a list | private only | `audience.lists.addPeople()` | — |
| Remove people from a list | private only | `audience.lists.removePeople()` | — |
| List custom properties | private only | `audience.properties.list()` | — |
| Create custom property | private only | `audience.properties.create()` | — |
| Update custom property | private only | `audience.properties.update()` | — |
To manage list membership from the browser, use `audience.people.upsert()`
with the `lists` parameter.
## People
### Upsert a Person
#### `audience.people.upsert(params)`
> `POST /api/v0/audience/people`
>
> **Auth:** public or private key · scope: `AUDIENCE_PERSON_WRITE`
Creates or updates a person record based on email address.
| Param | Type | Required | Description |
|---|---|---|---|
| `emailAddress` | `string` | Yes | Primary identifier |
| `emailSubscriptionStatus` | `"SUBSCRIBED" \| "UNSUBSCRIBED"` | No | Marketing email opt-in state |
| `firstName` | `string` | No | First name |
| `lastName` | `string` | No | Last name |
| `jobTitle` | `string` | No | Job title |
| `leadScore` | `number` | No | Integer lead score (default 0) |
| `lists` | `string[]` | No | List slugs to add the person to |
| `properties` | `Record` | No | Custom properties (must be pre-defined) |
```typescript
const { personId } = await client.audience.people.upsert({
emailAddress: "user@example.com",
firstName: "Jane",
lastName: "Doe",
emailSubscriptionStatus: "SUBSCRIBED",
leadScore: 50,
lists: ["newsletter", "customers"],
properties: {
plan: "pro",
signupSource: "landing-page",
},
});
```
**Email Subscription Statuses:**
- `SUBSCRIBED` - Opted in to marketing emails
- `UNSUBSCRIBED` - Opted out of marketing emails
- If not specified:
- Existing people keep their current state
- New people default based on double opt-in settings
**Returns:**
```typescript
{
personId: string; // Unique identifier (CUID format)
}
```
### Identify a Person
#### `audience.people.identify(params)`
> `POST /api/v0/audience/people/identify`
>
> **Auth:** public or private key · scope: `AUDIENCE_PERSON_WRITE`
Identifies a person by email, creating them if they don't already exist —
the same job `upsert()` does, but the intended path forward for new
integrations, since it carries lead attribution. Creating a new person fires
a `personCreated` analytics event with whatever attribution context is
available.
The client SDK attaches the visitor's current browser context (device,
session, referrer, and attribution) automatically. On the server, forward it
yourself, typically from `client.getBrowserContext()` on your frontend.
| Param | Type | Required | Description |
|---|---|---|---|
| `emailAddress` | `string` | Yes | Primary identifier |
| `firstName` | `string` | No | First name |
| `lastName` | `string` | No | Last name |
| `jobTitle` | `string` | No | Job title |
| `leadScore` | `number` | No | Integer lead score |
| `lists` | `string[]` | No | List slugs to add the person to |
| `properties` | `Record` | No | Custom properties (must be pre-defined) |
| `browserContext` | `BrowserContext` | Server SDK only | Attribution to attach if this creates a new person |
```typescript
// Browser
const { personId } = await client.audience.people.identify({
emailAddress: "user@example.com",
firstName: "Jane",
});
// Server
const { personId } = await client.audience.people.identify({
emailAddress: "user@example.com",
firstName: "Jane",
browserContext: clientBrowserContext, // forwarded from the browser client
});
```
**Returns:**
```typescript
{
personId: string;
}
```
### Register for an Event
#### `audience.people.registerForEvent(options)`
> `POST /api/v0/audience/people/register-for-event`
>
> **Auth:** public or private key · scope: `AUDIENCE_PERSON_WRITE`
Identifies a person, then registers them for a marketing event. Registration
dispatches the `marketingEventRegistration` analytics event and triggers the
event's flow automatically — no separate `analytics.event()` call is needed.
| Param | Type | Required | Description |
|---|---|---|---|
| `emailAddress` | `string` | Yes | Primary identifier |
| `eventSlug` | `string` | Yes | Slug of the marketing event to register for |
| `firstName` | `string` | No | First name |
| `lastName` | `string` | No | Last name |
| `jobTitle` | `string` | No | Job title |
| `leadScore` | `number` | No | Integer lead score |
| `lists` | `string[]` | No | List slugs to add the person to |
| `properties` | `Record` | No | Custom properties (must be pre-defined) |
| `browserContext` | `BrowserContext` | No | Attribution to attach if this creates a new person |
```typescript
const { personId, eventId, participantStatus } =
await client.audience.people.registerForEvent({
emailAddress: "user@example.com",
eventSlug: "spring-webinar",
});
```
**Returns:**
```typescript
{
personId: string;
eventId: string;
participantStatus: "INVITED" | "REGISTERED" | "ATTENDED" | "NO_SHOW" | "CANCELLED";
}
```
Fails with `404` when `eventSlug` doesn't match an event for the business, and
`400` when registration isn't allowed in the event's current state (e.g. an
ended event that doesn't accept the requested status).
### Subscribe to Email
#### `audience.people.subscribeToEmail(options)`
> `POST /api/v0/audience/people/subscribe-to-email`
>
> **Auth:** public or private key · scope: `AUDIENCE_PERSON_WRITE`
Identifies a person, then subscribes them to email, honoring the business's
double opt-in setting. If double opt-in is enabled, a new subscriber (or one
who was never subscribed) lands on `PENDING` rather than `SUBSCRIBED`. Any
other existing status is left exactly as it is; this call never overrides an
explicit unsubscribe or a compliance-managed status.
| Param | Type | Required | Description |
|---|---|---|---|
| `emailAddress` | `string` | Yes | Primary identifier |
| `firstName` | `string` | No | First name |
| `lastName` | `string` | No | Last name |
| `jobTitle` | `string` | No | Job title |
| `leadScore` | `number` | No | Integer lead score |
| `lists` | `string[]` | No | List slugs to add the person to |
| `properties` | `Record` | No | Custom properties (must be pre-defined) |
| `browserContext` | `BrowserContext` | No | Attribution to attach if this creates a new person |
```typescript
const { personId, emailSubscriptionStatus } =
await client.audience.people.subscribeToEmail({
emailAddress: "user@example.com",
});
```
**Returns:**
```typescript
{
personId: string;
emailSubscriptionStatus:
| "SUBSCRIBED"
| "UNSUBSCRIBED"
| "PENDING"
| "NOT_SUBSCRIBED"
| "REDACTED"
| "INVALID";
}
```
## Companies
### Upsert a Company
#### `audience.companies.upsert(params)`
> `POST /api/v0/audience/companies`
>
> **Auth:** public or private key · scope: `AUDIENCE_COMPANY_WRITE`
Creates or updates a company record keyed on `domain`.
| Param | Type | Required | Description |
|---|---|---|---|
| `domain` | `string` | Yes | Company domain (upsert key) |
| `name` | `string` | No | Company name |
| `description` | `string` | No | Description |
| `industries` | `string[]` | No | Industry tags |
| `totalEmployees` | `number` | No | Employee count |
| `address1` | `string` | No | Street address |
| `city` | `string` | No | City |
| `regionCode` | `string` | No | State/region code |
| `country` | `string` | No | Country code |
| `zip` | `string` | No | Postal code |
| `socialLinkLinkedIn` | `string` | No | LinkedIn URL |
| `properties` | `Record` | No | Custom properties (must be pre-defined) |
```typescript
const { companyId } = await client.audience.companies.upsert({
domain: "acme.com",
name: "Acme Corp",
description: "Makes everything",
industries: ["manufacturing"],
totalEmployees: 500,
properties: {
arr: 1200000,
fundingStage: "Series B",
},
});
```
**Returns:**
```typescript
{
companyId: string; // Unique identifier (CUID format)
}
```
Domain is not required to be unique. If exactly one company matches `domain`,
it's updated; if none match, one is created. If more than one company shares
the same domain, the upsert fails with a `409`:
```typescript
{
domain: string; // The domain that matched more than one company
matchCount: number; // How many companies matched
matchingCompanyIds: string[]; // Ids of the matching companies
}
```
## Lists
The Lists API lets you create and manage audience lists programmatically.
Lists are identified by a unique slug and can contain people identified by
either their person ID or email address.
All list operations require a private API key. List membership
changes (`addPeople`, `removePeople`) are not safe to expose on a
public key, so they're server-side only.
```typescript
import { QuotientServer } from "@quotientjs/server";
const client = new QuotientServer({
privateKey: "sk_your_private_api_key",
});
```
### Create or Update a List
#### `audience.lists.upsert(options)`
> `POST /api/v0/audience/lists`
>
> **Auth:** private key only · scope: `AUDIENCE_LIST_WRITE`
The **slug** is always the upsert key — you either provide it directly, or
it gets derived from the name.
| Param | Type | Required | Description |
|---|---|---|---|
| `name` | `string` | One of `name` or `slug` | List name (slug auto-derived if slug omitted) |
| `slug` | `string` | One of `name` or `slug` | Explicit slug to target |
| `description` | `string` | No | List description |
```typescript
// By name — slug is auto-generated ("newsletter-subscribers")
await client.audience.lists.upsert({
name: "Newsletter Subscribers",
description: "People who opted into our weekly newsletter",
});
// By slug — target an existing list directly
await client.audience.lists.upsert({
slug: "newsletter-subscribers",
description: "Updated description",
});
// By slug + name — target by slug, rename the list
await client.audience.lists.upsert({
slug: "newsletter-subscribers",
name: "Weekly Newsletter",
});
```
**Upsert behavior:**
| Input | Lookup key | Not found | Found |
|---|---|---|---|
| `{ name }` | `generateSlug(name)` | Create with name + generated slug | Update name |
| `{ name, description }` | `generateSlug(name)` | Create with both | Update name + description |
| `{ slug }` | slug | Create (name defaults to slug) | No-op |
| `{ slug, name }` | slug | Create with name + slug | Update name |
| `{ slug, description }` | slug | Create (name defaults to slug) | Update description |
| `{ slug, name, description }` | slug | Create with all fields | Update name + description |
**Returns:**
```typescript
{
listId: string;
name: string;
slug: string;
}
```
### List All Lists
#### `audience.lists.list(options?)`
> `GET /api/v0/audience/lists`
>
> **Auth:** private key only · scope: `AUDIENCE_LIST_READ`
| Param | Type | Required | Description |
|---|---|---|---|
| `search` | `string` | No | Filter by name |
| `page` | `number` | No | Page number (default 1) |
| `limit` | `number` | No | Results per page (default 20) |
```typescript
const { lists, pageData } = await client.audience.lists.list({
search: "newsletter",
page: 1,
limit: 20,
});
```
**Returns:**
```typescript
{
lists: {
id: string;
name: string;
slug: string;
description: string | null;
peopleCount: number;
createdAt: string;
updatedAt: string;
}[];
pageData: {
page: number;
limit: number;
total: number;
isNextPageAvailable: boolean;
};
}
```
### Get a Single List
#### `audience.lists.get(options)`
> `GET /api/v0/audience/lists/{slug}`
>
> **Auth:** private key only · scope: `AUDIENCE_LIST_READ`
| Param | Type | Required | Description |
|---|---|---|---|
| `slug` | `string` | Yes | List slug |
```typescript
const { list } = await client.audience.lists.get({
slug: "newsletter-subscribers",
});
```
**Returns:**
```typescript
{
list: {
id: string;
name: string;
slug: string;
description: string | null;
peopleCount: number;
createdAt: string;
updatedAt: string;
};
}
```
### List People in a List
#### `audience.lists.listPeople(options)`
> `GET /api/v0/audience/lists/{slug}/people`
>
> **Auth:** private key only · scope: `AUDIENCE_LIST_READ`
| Param | Type | Required | Description |
|---|---|---|---|
| `listSlug` | `string` | Yes | List slug |
| `search` | `string` | No | Filter by email |
| `page` | `number` | No | Page number (default 1) |
| `limit` | `number` | No | Results per page (default 20) |
```typescript
const { people, pageData } = await client.audience.lists.listPeople({
listSlug: "newsletter-subscribers",
search: "jane",
page: 1,
limit: 20,
});
```
**Returns:**
```typescript
{
people: {
personId: string;
emailAddress: string;
firstName: string | null;
lastName: string | null;
}[];
pageData: {
page: number;
limit: number;
total: number;
isNextPageAvailable: boolean;
};
}
```
### Add People to a List
#### `audience.lists.addPeople(options)`
> `POST /api/v0/audience/lists/{slug}/people`
>
> **Auth:** private key only · scope: `AUDIENCE_LIST_WRITE`
Add up to 100 people per request. Each entry can reference an existing person
by ID, or provide an email address to upsert a person and add them in one call.
| Param | Type | Required | Description |
|---|---|---|---|
| `listSlug` | `string` | Yes | List slug |
| `people` | `AddPersonEntry[]` | Yes | Array of people to add (max 100) |
Each entry in `people` is one of:
| Param | Type | Required | Description |
|---|---|---|---|
| `personId` | `string` | Yes (if no email) | Existing person ID |
| `emailAddress` | `string` | Yes (if no ID) | Email to upsert |
| `firstName` | `string` | No | First name (with email only) |
| `lastName` | `string` | No | Last name (with email only) |
| `jobTitle` | `string` | No | Job title (with email only) |
| `leadScore` | `number` | No | Lead score (with email only) |
| `properties` | `Record` | No | Custom properties (with email only) |
```typescript
await client.audience.lists.addPeople({
listSlug: "newsletter-subscribers",
people: [
{ personId: "clx..." },
{
emailAddress: "jane@example.com",
firstName: "Jane",
lastName: "Doe",
properties: { plan: "pro" },
},
],
});
```
**Returns:**
```typescript
{
added: number;
listSlug: string;
listId: string;
}
```
### Remove People from a List
#### `audience.lists.removePeople(options)`
> `DELETE /api/v0/audience/lists/{slug}/people`
>
> **Auth:** private key only · scope: `AUDIENCE_LIST_WRITE`
Remove up to 100 people per request. Each entry can reference a person by ID
or by email address. This operation is idempotent — removing a person who is
not in the list (or referencing an email that doesn't exist) is a no-op.
| Param | Type | Required | Description |
|---|---|---|---|
| `listSlug` | `string` | Yes | List slug |
| `people` | `RemovePersonEntry[]` | Yes | Array of people to remove (max 100) |
Each entry in `people` is one of:
| Param | Type | Description |
|---|---|---|
| `personId` | `string` | Existing person ID |
| `emailAddress` | `string` | Person's email address |
```typescript
await client.audience.lists.removePeople({
listSlug: "newsletter-subscribers",
people: [
{ personId: "clx..." },
{ emailAddress: "jane@example.com" },
],
});
```
**Returns:**
```typescript
{
removed: number;
listSlug: string;
listId: string;
}
```
## Custom Properties
Custom properties are the fields you define on people, companies, and deals
beyond the built-in ones. These endpoints manage the property *definitions* —
the values themselves are written through `audience.people.upsert()` /
`audience.companies.upsert()` `properties` payloads, which validate against
the definitions.
Every definition has an `entityType` (`"person"`, `"company"`, or `"deal"`),
an immutable alphanumeric `id` (the key used in `properties` payloads), an
immutable `datatype`, and a `readOnly` flag. `SINGLE_SELECT` and
`MULTI_SELECT` datatypes carry `allowedValues` — the closed set of allowed
options, always at least 2.
### List Custom Properties
#### `audience.properties.list(options)`
> `GET /api/v0/audience/properties`
>
> **Auth:** private key only · scope: `AUDIENCE_PROPERTY_READ`
| Param | Type | Required | Description |
|---|---|---|---|
| `entityType` | `"person" \| "company" \| "deal"` | Yes | Which entity's definitions to list |
```typescript
const { properties } = await client.audience.properties.list({
entityType: "person",
});
```
**Returns:**
```typescript
{
properties: Array<{
id: string;
businessId: string;
entityType: "person" | "company" | "deal";
displayName: string;
description: string | null;
datatype: string; // e.g. "STRING", "NUMBER", "SINGLE_SELECT", ...
allowedValues?: string[]; // present only on select datatypes
readOnly: boolean;
}>;
}
```
### Create a Custom Property
#### `audience.properties.create(options)`
> `POST /api/v0/audience/properties`
>
> **Auth:** private key only · scope: `AUDIENCE_PROPERTY_WRITE`
| Param | Type | Required | Description |
|---|---|---|---|
| `entityType` | `"person" \| "company" \| "deal"` | Yes | Which entity the property is defined for |
| `id` | `string` | Yes | API name — alphanumeric, unique per entity type, immutable |
| `displayName` | `string` | Yes | Human-readable name shown in the UI |
| `datatype` | `string` | Yes | Value type (`STRING`, `NUMBER`, `BOOLEAN`, `DATE`, `SINGLE_SELECT`, ...) — immutable |
| `allowedValues` | `string[]` | Yes (select datatypes) | Allowed options — at least 2; forbidden for other datatypes |
| `readOnly` | `boolean` | No | Read-only properties reject value writes (default false) |
```typescript
const { property } = await client.audience.properties.create({
entityType: "person",
id: "plan",
displayName: "Plan",
datatype: "SINGLE_SELECT",
allowedValues: ["free", "pro", "enterprise"],
});
```
**Returns:**
```typescript
{
property: CustomPropertyDefinition; // same shape as the list items
}
```
Fails with `409` when the id already exists for the entity type or collides
with a built-in field, and `422` when the id isn't alphanumeric or a select
datatype has fewer than 2 options.
### Update a Custom Property
#### `audience.properties.update(options)`
> `PATCH /api/v0/audience/properties/:propertyId`
>
> **Auth:** private key only · scope: `AUDIENCE_PROPERTY_WRITE`
Only `displayName`, `readOnly`, and (for select datatypes) appending new
options are supported — `id` and `datatype` are immutable, and existing
options can't be renamed or removed.
| Param | Type | Required | Description |
|---|---|---|---|
| `propertyId` | `string` | Yes | The property's id (API name) |
| `entityType` | `"person" \| "company" \| "deal"` | Yes | Which entity the property is defined for |
| `displayName` | `string` | No | New display name |
| `readOnly` | `boolean` | No | New read-only flag |
| `addAllowedValues` | `string[]` | No | NEW options to append (select datatypes only; an exact re-add is a no-op, a case-variant of an existing option is rejected) |
```typescript
const { property } = await client.audience.properties.update({
propertyId: "plan",
entityType: "person",
addAllowedValues: ["enterprise-plus"],
});
```
**Returns:**
```typescript
{
property: CustomPropertyDefinition; // same shape as the list items
}
```
Fails with `404` when the property doesn't exist for the entity type, and
`422` when `addAllowedValues` targets a non-select datatype.
## Common Patterns
### User Identification on Signup
```javascript
async function identifyUser(user) {
const { personId } = await client.audience.people.upsert({
emailAddress: user.email,
firstName: user.firstName,
lastName: user.lastName,
emailSubscriptionStatus: "SUBSCRIBED",
leadScore: user.leadScore ?? 0,
lists: ["customers", "newsletter"],
properties: {
plan: user.subscription,
signupDate: new Date(),
lastLogin: new Date(),
totalPurchases: user.purchaseCount,
},
});
console.log(`User identified: ${personId}`);
}
```
### Contact Form Capture
```javascript
async function handleContactForm(formData) {
try {
await client.audience.people.upsert({
emailAddress: formData.email,
firstName: formData.firstName,
lastName: formData.lastName,
lists: ["leads"],
properties: {
message: formData.message,
source: "contact-form",
submittedAt: new Date(),
},
});
void client.analytics.event({
eventType: "custom",
customEventId: "contact_form_submitted",
});
} catch (error) {
console.error("Failed to save lead:", error);
}
}
```
Create `contact_form_submitted` in Quotient before sending it. See
[Custom Events](/docs/analytics/custom-events) for the complete browser
workflow.
### Syncing a List from an External Source
```typescript
const client = new QuotientServer({ privateKey: "sk_..." });
// Ensure the list exists
await client.audience.lists.upsert({
name: "Active Customers",
description: "Synced from billing system",
});
// Add people in batches of 100
const customers = getActiveCustomers(); // your data source
for (let i = 0; i < customers.length; i += 100) {
const batch = customers.slice(i, i + 100);
await client.audience.lists.addPeople({
listSlug: "active-customers",
people: batch.map((c) => ({
emailAddress: c.email,
firstName: c.firstName,
lastName: c.lastName,
properties: {
plan: c.plan,
mrr: c.mrr,
},
})),
});
}
```
## Next Steps
-- End of: /sdk/audience
-- Start of: /sdk/blog
---
title: Blog
description: Retrieve and render blog content using the Quotient SDK
order: 7
---
## Overview
The blog API lets you retrieve published blog posts, authors, and tags from
your Quotient blog. All endpoints are read-only and work with both public and
private API keys.
| Endpoint | API Key | Server SDK | Client SDK |
|---|---|---|---|
| Get blog post | public or private | `blog.get()` | `blog.get()` |
| List blog posts | public or private | `blog.list()` | `blog.list()` |
| List authors | public or private | `blog.listAuthors()` | `blog.listAuthors()` |
## Get a Blog Post
#### `blog.get(options)`
> `GET /api/v0/blog/{slug}`
>
> **Auth:** public or private key · scope: `BLOG_READ`
| Param | Type | Required | Description |
|---|---|---|---|
| `slug` | `string` | Yes | Blog post slug |
| `rawHtml` | `boolean` | No | Return pre-rendered HTML |
```typescript
const { blog } = await client.blog.get({
slug: "my-first-post",
rawHtml: true,
});
```
**Returns:**
```typescript
{
blog: {
id: string;
title: string;
slug: string;
content: JSON;
dominantImageUrl?: string | null;
publishDate: Date | null;
rawHtml?: string | null;
authors: {
id: string;
name: string;
emailAddress?: string | null;
avatarUrl?: string | null;
}[];
metaDescription: string | null;
tags: {
id: string;
name: string;
description?: string | null;
}[];
};
}
```
## List Blog Posts
#### `blog.list(options?)`
> `GET /api/v0/blog/list`
>
> **Auth:** public or private key · scope: `BLOG_READ`
| Param | Type | Required | Description |
|---|---|---|---|
| `authorIds` | `string[]` | No | Filter by author IDs |
| `tagIds` | `string[]` | No | Filter by tag IDs |
| `statuses` | `("DRAFT" \| "SCHEDULED" \| "PUBLISHED")[]` | No | Filter by status |
| `search` | `string` | No | Search by title |
| `page` | `number` | No | Page number (default 1) |
| `limit` | `number` | No | Results per page (default 50) |
```typescript
const { blogs, pageData } = await client.blog.list({
statuses: ["PUBLISHED"],
search: "marketing",
page: 1,
limit: 20,
});
```
**Returns:**
```typescript
{
blogs: {
id: string;
title: string;
slug: string;
content: JSON;
dominantImageUrl?: string | null;
publishDate: Date | null;
authors: {
id: string;
name: string;
emailAddress?: string | null;
avatarUrl?: string | null;
}[];
metaDescription: string | null;
tags: {
id: string;
name: string;
description?: string | null;
}[];
}[];
pageData: {
page: number;
limit: number;
total: number;
isNextPageAvailable: boolean;
};
}
```
## List Authors
#### `blog.listAuthors(options?)`
> `GET /api/v0/blog/authors`
>
> **Auth:** public or private key · scope: `BLOG_READ`
| Param | Type | Required | Description |
|---|---|---|---|
| `search` | `string` | No | Filter by name |
| `page` | `number` | No | Page number (default 1) |
| `limit` | `number` | No | Results per page (default 10) |
```typescript
const { authors, pageData } = await client.blog.listAuthors({
search: "jane",
page: 1,
limit: 10,
});
```
**Returns:**
```typescript
{
authors: {
id: string;
name: string;
emailAddress?: string | null;
avatarUrl?: string | null;
}[];
pageData: {
page: number;
limit: number;
total: number;
isNextPageAvailable: boolean;
};
}
```
## Caching in Next.js
Blog content is a natural fit for caching. Posts change infrequently, so
re-fetching them on every request is wasteful — especially on high-traffic
pages like a blog index or a sitemap. Each server blog method accepts an
optional second argument, `fetchOptions`, which is forwarded to `fetch`. In a
Next.js app you can use it to opt into Incremental Static Regeneration instead
of fetching fresh data every time.
For example, a sitemap that lists every published post only needs to refresh
every hour or so:
```typescript
const { blogs } = await client.blog.list(
{ statuses: ["PUBLISHED"], limit: 1000 },
{ cache: "force-cache", next: { revalidate: 3600 } },
);
```
See [Customizing fetch behavior](/docs/sdk) for the full list of options you can
pass and the fields the SDK reserves for itself.
## Rendering
The `@quotientjs/react` package provides a `` component that renders
blog content into HTML. It takes the `content` JSON from `blog.get()` and
produces unstyled semantic HTML elements.
### Basic Usage
```tsx
import { Blog } from "@quotientjs/react";
import { QuotientServer } from "@quotientjs/server";
// app/blog/[slug]/page.tsx
export default async function BlogPost({
params,
}: {
params: { slug: string };
}) {
const client = new QuotientServer({
privateKey: process.env.QUOTIENT_PRIVATE_KEY!,
});
const { blog } = await client.blog.get({ slug: params.slug });
return ;
}
```
### Styling
The `` component renders unstyled HTML with default class names on
each element (`quotient-p`, `quotient-h1`, `quotient-a`, etc.). There are
three ways to style blog content:
**1. Target default classes in CSS**
```css
.quotient-p { line-height: 1.75; }
.quotient-h2 { margin-top: 2rem; }
.quotient-a { color: blue; text-decoration: underline; }
```
**2. Override classes via `elementClassName`**
```tsx
```
**3. Tailwind Typography plugin**
```tsx
```
### Available Class Targets
| Element | Default Class |
|---|---|
| `` | `quotient-strong` |
| `` | `quotient-em` |
| `` | `quotient-u` |
| `` | `quotient-a` |
| `
Real-time collaboration infrastructure. Enables collaborative editing
features in WYSIWYG editors.
## Data Processing Compliance
All subprocessors are carefully vetted for security and compliance. Where required by applicable data protection laws, we maintain data processing agreements with our subprocessors that include:
- Appropriate technical and organizational security measures
- Confidentiality commitments
- Data protection compliance obligations
- Terms governing data transfers and subprocessing
## Updates to This List
This subprocessor list is current as of the date of this document. Quotient reserves the right to add, remove, or replace subprocessors as needed to improve our services. Material changes to this list will be communicated to merchants in accordance with our Terms of Service.
If you have questions about our subprocessors or data processing practices, please contact us at support@getquotient.ai.
-- End of: /trust-security/subprocessors
-- Start of: /working-with-ai/index
---
title: Working with AI
description: How to get the most out of chatting with Quotient
order: 1
---
You can chat with Quotient in plain English, just like you would with a coworker. Tell it what you want, and it will help you get it done. If you've used products like ChatGPT or Claude, the experience will feel familiar.
However, working with AI is different from working with a human in a few key ways. The most important concept to understand is **context.**
## Context and Tools
"Context" refers to the information that is available to Quotient. Unlike humans, Quotient starts each conversation fresh — it doesn't remember what you told it yesterday. It has to be explicitly provided with the information it needs to do its job.
This means you should be explicit about what you want and provide all necessary context in each conversation. Knowing what context Quotient has and doesn't have will help you interact with it more effectively.
When you talk to Quotient, its context will automatically include…
- Information about your brand saved in Quotient's **[memory](/docs/working-with-ai/memory)**
- The conversation history within that chat thread
- An understanding of the Quotient platform itself
- Specialized knowledge relevant to the task at hand (e.g. when writing a blog, Quotient draws on expertise in SEO-optimized content)
However, Quotient's context does _not_ include...
- Knowledge of current events, like today's front page news or what's currently trending in your industry
- Any information about your brand or business that isn't saved in memory
- Your past conversations (if you tell Quotient about a new product feature in one conversation, it won't know about it in future conversations unless you ask Quotient to save it to memory)
To get additional information, Quotient can use **tools** to look things up. Tools allow Quotient to interact with the outside world, including the Quotient platform, the open internet, and other integrated systems.
Quotient can use tools to find information to add to its existing context, such as…
- Searching the web and visiting web pages
- Looking up a person or company from your Quotient audience
- Looking up all currently active campaigns in Quotient
In addition to looking up information, tools can also perform actions, such as…
- Creating a new campaign
- Editing a blog
- Deleting an email broadcast
## @ Mentioning Objects
You can @ mention **objects** in Quotient, such as Campaigns, Email Broadcasts, Blogs, Segments, and Email Templates.
Mentioning objects will automatically include all of the data about that object into Quotient's context. You can think of this like sharing a URL with a coworker. Your coworker can click into the URL, give it a quick read, and understand what you're talking about. But without the URL, they might be confused and not understand the context.
Here are some examples of when you might @ mention an object:
- If you're asking Quotient to use a specific email template as part of a flow
- If you're asking Quotient to send an email to a specific segment
- If you want Quotient to use a specific asset as the thumbnail image for a blog
## Managing Threads
Each conversation in Quotient is called a "thread". Within a given thread, Quotient will recall the entire conversation history, but it won't recall conversations from _other_ threads.
When a thread gets too large or covers too many topics, it tends to confuse or overwhelm the AI. Long threads can be overwhelming for humans too. (No one likes looking at a Slack thread with 150 responses, or an email chain that's 80 replies long.)
To get the best performance out of Quotient, it's best to keep threads scoped to a single task or set of related tasks. A good rule of thumb is to create one thread per **deliverable** — i.e. a single thread for each blog, campaign, email broadcast, etc.
Sometimes it makes sense to group related deliverables into a single thread. For example, you might be working on a blog post as well as an email broadcast announcing the new post to your subscribers. In this case, it might make sense to create both deliverables in the same thread.
On the other hand, if you have a completely new, unrelated request, it's best to start a fresh thread to begin working on it.
## Memories
Although Quotient doesn't naturally remember past conversations the way people do, it can save **[memories](/s/most-recent-business/memory)** that it draws on in future ones. This is how Quotient learns your business's particular preferences and workflows. If you want Quotient to remember something, just tell it to "please remember this going forward."
Common examples of memories include…
- Which email templates should be used as a starting point when creating new broadcasts
- Which segments or lists should be used in flows and email broadcasts
- Preferences about campaign management (e.g. "campaigns should always contain one email broadcast per blog post")
Memory also holds core information about your brand, like your ideal customer profile and brand voice guidelines. See [Memory](/docs/working-with-ai/memory) for what to save and how to organize it.
## Choosing an AI Model
Quotient can run on models from several AI providers, including Anthropic's Claude, OpenAI's GPT, Google's Gemini, and xAI's Grok. You can pick one from the model picker in the chat box:
Each message in a thread can use a different model, and the conversation history carries over when you switch.
If you're not sure which to pick, leave it on **Auto**. We regularly test leading models on everyday marketing work like campaign planning, copywriting, and research, and Auto uses whichever one currently does best.
The picker remembers your choice. An existing thread stays on the last model it used, and a new thread starts with the last model you picked. That default is saved in your browser for each business, so it isn't shared with your teammates.
Models with a **Pro** badge, like Claude Opus and GPT-5.6 Sol, are premium models. They're available on the Starter plan and above and use more AI credits per message. If your plan changes and you lose access to them, the picker switches back to Auto. See [Plans and Billing](/docs/plans-and-billing) for how credits work, and check [Settings > Usage](/s/most-recent-business/settings/usage) to track your usage.
-- End of: /working-with-ai/index
-- Start of: /working-with-ai/jobs
---
title: Jobs
description: Put recurring work on a schedule so Quotient does it for you
order: 2
---
Quotient can run marketing tasks for you on a schedule. For example, you might
want a daily list of new signups worth a follow-up, a weekly summary of campaign
performance, or a monthly draft of your customer newsletter.
A **job** is one of these recurring tasks. You write the instructions once and
pick a schedule, and Quotient carries out the instructions each time the job is
due, without anyone having to open a chat.
## Creating a Job
The easiest way to create a job is to ask Quotient. Describe what you want done
and how often. Here are a few examples:
Quotient creates the job from your request, including the instructions it will
follow on every run. Since you won't be there to clarify when the job runs, it's
worth being specific. "Summarize campaign performance" works, but "compare each
active campaign's email clicks and website sessions to the previous week" gets
you a more useful summary. You can @ mention objects in your request, like a
particular campaign or segment, and the job will refer to them on every run.
You can also create a job yourself on the
[Jobs](/s/most-recent-business/agent-jobs) page with the **Create Job** button.
That opens a new job's page, where you write the instructions, attach files if
the job needs them, choose which AI model the job starts with, and set the
schedule. Click **Save** when you're done.
## Schedules
On the Jobs page, you can schedule a job to run daily, weekly on a given day, or
monthly on a given date, at a time of your choosing. Times are in your
business's time zone. When you ask Quotient instead, you can describe more
specific patterns in plain language, like "every weekday at 8am" or "every other
hour during business hours".
Jobs start within a few minutes of their scheduled time. When you ask Quotient
for a job, mention your time zone ("9am Eastern") so there is no ambiguity. Each
job on the Jobs page shows its schedule and when it will run next, which is a
quick way to confirm Quotient got it right.
## What Happens When a Job Runs
Each run starts a new chat thread, as if the job's owner had typed the
instructions into a fresh conversation. Quotient can do anything it does in a
regular chat, like run reports, search the web, or draft content. These threads
appear in your chat history, labeled with the job's name.
When a run finishes, Quotient notifies the job's owner with a short summary and
links to anything it created. Notifications appear in Quotient, and by email and
[Slack](/docs/integrations/slack) if you've turned those on in your
[notification settings](/s/most-recent-business/settings/notifications). If a
run fails, the owner gets a notification with a link to the thread.
The owner is whoever created the job, unless you choose someone else. Teammates
can choose **Notify me** from a job's menu on the Jobs page to get notified too.
Every job's page has a **Runs** tab listing its past runs, newest first. Click
one to open its thread. The Jobs page also shows when each job last ran and
whether that run succeeded.
Each run uses AI credits like a regular conversation. Jobs are included on every
paid plan. If your plan stops including them, your jobs are saved but don't run
until that's resolved. See [Plans and Billing](/docs/plans-and-billing).
## Changing, Pausing, or Deleting a Job
To change a job, ask Quotient to update it ("move my Monday report to 8am", or
"also include social post engagement in the weekly summary"), or click the job
on the Jobs page to open its page, where you can edit its name, instructions,
schedule, owner, and more. Changes take effect the next time the job runs.
A job's menu, on the Jobs page or on the job's own page, has a few more actions:
- **Run now** runs the job right away and opens the resulting thread, which is
handy for testing new instructions without waiting for the schedule.
- **Pause schedule** stops the job from running on its schedule while keeping
its instructions, settings, and past runs. You can still use **Run now** on a
paused job. When you choose **Resume schedule**, the job picks up at its next
scheduled time. Runs it missed while paused aren't made up. You can also ask
Quotient to pause or resume a job for you.
- **Delete** removes the job for good. If you only want a job to stop for a
while, pause it instead.
A few tips for getting the most out of jobs:
- Run a new job once with **Run now** before you rely on it, and adjust the
instructions until the output looks right.
- Say what you want delivered. "Tell me the three campaigns with the biggest
drop in clicks" gets a sharper result than "check on campaigns".
- Keep each job to one task. Two focused jobs are easier to read and to fix than
one job that does everything.
-- End of: /working-with-ai/jobs
-- Start of: /working-with-ai/memory
---
title: Memory
description: How Quotient learns about your brand, preferences, and workflows
order: 1
---
To do great marketing, Quotient needs context about your business — the same kind of context you'd give a new hire before they could do useful work. **[Memory](/s/most-recent-business/memory)** is where that context lives.
Memory is a collection of documents that Quotient draws on whenever it writes content, proposes campaigns, or gives strategic advice. The more you teach Quotient about your business, the more relevant and on-brand its output becomes.
This isn't so different from a human marketing agency. To do good work, an agency spends time learning your brand, your customers, and how you like to operate. The same goes for Quotient — except instead of onboarding calls and brand decks, the knowledge lives in memory, and Quotient can draw on all of it instantly.
## What Goes in Memory
Memory is broader than just brand information. It captures anything that helps Quotient do better marketing for your business. Most memories fall into three categories.
**Brand fundamentals.** Who you are, what you sell, who you sell to, and how you talk about it. Think product overviews, ideal customer profiles, competitive positioning, and brand voice guidelines. This is typically the first thing you'll build when you get started with Quotient.
**Workflows and playbooks.** How your team actually gets marketing done. If you have a specific process for running product launches, publishing a weekly changelog, or planning quarterly campaigns, you can capture that in a memory document. When you later ask Quotient to kick off a product launch, it already knows what deliverables to produce, what the campaign structure should look like, and which channels to use — because your playbook told it so.
**Preferences.** Individual or team-level preferences about how work should be done. For example, you might create a memory that describes how a specific team member likes to write social media posts — their preferred tone, length, and formatting. Quotient is often smart enough to create these on your behalf. If you say something like "going forward, I want my blog posts to always include a summary at the top," Quotient will save that as a memory automatically.
## Common Memory Documents
Here are examples of documents that most businesses should have:
- **Ideal Customer Profile (ICP):** Your target customers — demographics, pain points, decision-making process, and what drives them to your solution. Helps Quotient create more targeted content.
- **Competitors and Battle Cards:** Profiles of your main competitors — positioning, pricing, strengths, weaknesses, and key differentiators. Enables Quotient to highlight your unique advantages.
- **Product Overview:** Core functionality, key features, integrations, and what makes your product different. Ensures Quotient accurately represents your capabilities.
- **Value Proposition:** Your main benefits and supporting pillars — the core reasons customers choose you. Gives Quotient consistent messaging frameworks.
- **Brand Voice and Style Guide:** Your brand personality, tone, writing preferences, and communication style, with examples of on-brand vs. off-brand copy.
- **Customer Success Stories:** Case studies, testimonials, and key metrics. Gives Quotient concrete proof points to draw on.
- **Messaging Framework:** Tested headlines, taglines, content themes, and words or phrases to avoid.
- **Campaign Playbooks:** Step-by-step workflows for recurring campaigns — a product launch playbook, a webinar planning checklist, or a process for assembling weekly newsletters. These help Quotient follow your team's established process rather than improvising from scratch.
## Pinned Memories
Not all memories are surfaced to Quotient at all times.
When you ask Quotient to do something, the system identifies
which memories are most relevant to the task at hand and
pulls them in automatically. This keeps Quotient focused
and avoids overwhelming it with context that isn't useful for
the current job.
**Pinned memories** override this behavior.
When you pin a memory, it is always visible to Quotient — regardless of the task.
This is useful for foundational context that Quotient needs in every
interaction, not just specific ones.
Good candidates for pinning:
- **Brand Voice and Style Guide:** so every piece of content stays on-brand
- **Value Proposition:** so Quotient always knows how to position your product
- **Key Preferences:** company-wide rules like "never use the word 'synergy'"
or "always link to the pricing page in bottom-of-funnel content"
You can pin or unpin a memory at any time from the memory detail page.
Pinned memories are marked with a pin icon in the memory list so you can
see at a glance which ones are always active.
Pin sparingly — if everything is pinned, the benefit is lost.
Memories that are only relevant to specific channels or tasks
(like an email-specific style guide or a single campaign playbook)
are better left unpinned. Quotient's relevance system will still
surface them when they're needed. Reserve pinning for the handful
of documents that truly represent your business fundamentals.
## Tags
Tags help you organize memories by area or by author,
so that Quotient can more easily identify which memories are relevant to each task.
There are two types of tags: **platform tags** and **user tags**.
### Platform Tags
Platform tags correspond to a platform area or topic. They help Quotient understand which memories apply to which kind of work. When Quotient is working on a task tied to a specific area, it will prioritize memories with matching tags — so the right guidelines show up at the right time without you having to think about it.
The available platform tags are:
| Tag | Use it for |
|---|---|
| **email** | Email campaign preferences — subject line style, send cadence, CTA placement |
| **blog** | Blog writing guidelines — structure, length, formatting conventions |
| **social** | Social media preferences — tone, hashtags, platform-specific conventions |
| **tone** | General voice and tone guidelines that apply across channels |
| **audience** | Target audience definitions and segmentation context |
| **brand** | Core brand identity — positioning, messaging, visual guidelines |
| **competitors** | Competitive intelligence — battle cards, positioning against alternatives |
| **products** | Product details — features, use cases, pricing context |
**Example:** You create a memory called "Email Best Practices" that describes your
preferred subject line style, send cadence, and CTA placement.
You tag it with **email**. Now, whenever Quotient drafts an email
campaign, this memory is automatically prioritized — but it won't
clutter the context when Quotient is writing a blog post.
### User Tags
User tags correspond to a specific user or author in Quotient.
These are useful when different team members have different
preferences or responsibilities.
**Example:** Your teammate Sarah prefers a conversational,
first-person tone in her blog posts, while your teammate
James writes in a more formal, third-person style. You create
separate "Writing Preferences" memories for each and tag them
with **Sarah** and **James** respectively. When Sarah asks
Quotient to draft a post, her preferences are applied
automatically — and the same for James.
## Building Your Memory
Building memory is not a one-time activity. It evolves alongside your business,
and as your product, positioning, and strategy change, your memory should too.
Here are the most common ways to get started.
### Ask Quotient to Interview You
This is often the best starting point. Ask Quotient to conduct an interview
about your brand, and it will ask the right questions to help you articulate
your ICP, value proposition, competitive positioning, and more. It's a great way
to get knowledge that's locked in your head down on paper.
### Share Your Website
Tell Quotient which URLs to look at, and it will visit your site, read about
your product and company, and use what it finds to bootstrap your memory. Note
that Quotient can only access public URLs.
### Upload Documents
If you have PDFs, Word documents, or slide decks about your brand, upload them
to chat and ask Quotient to synthesize them into memory documents. Copy and
paste works too.
### Ask Quotient to Research
Tell Quotient to search the web on your behalf. A common use case is researching
competitors and building battle cards that assess your strengths and weaknesses
relative to each one.
### Connect External Tools
Useful context often lives in other systems, like product briefs in Notion,
feature specs in Linear, or messaging docs in Google Drive. You can use
[MCP connections](/docs/mcp/connecting-tools) to give Quotient access to these
tools, making it easy to pull relevant context into memory.
Think of memory as a living wiki for your business: the single source of truth
for everything Quotient needs to know to do great work.
-- End of: /working-with-ai/memory
-- Start of: /email/dns/godaddy-guide
---
title: GoDaddy
description: How to set up your DNS records in GoDaddy.
---

### Step 1: Access Your Domain Settings
Navigate to your GoDaddy domain management page and find your domain.

### Step 2: Open DNS Management
Click on the "DNS" or "Manage DNS" button to access your domain's DNS settings.

### Step 3: Click on the "Add Record" button
Click on the "Add New Record" button to add the email hosting records.

### Step 4: Add MX and TXT Records ( DKIM and SPF )
Enter the required MX and TXT records from Quotient.

### Step 5: Verify Settings
Review your DNS settings to ensure all records are properly configured.

-- End of: /email/dns/godaddy-guide
-- Start of: /email/dns/namecheap-guide
---
title: Namecheap
description: How to set up your DNS records in Namecheap.
---
### Step 1: Access Domain List
Log into your Namecheap account and navigate to your domain list.

### Step 2: Access Domain Settings
Click on the "Manage" button next to your domain to access its settings.

### Step 3: Access Advanced DNS
Click on "Advanced DNS" to add or modify your domain's DNS records.

### Step 4: Add MX and TX Records
Add the required MX and TX records for your email service.

### Step 4: Add MX Records
Add the required MX records for your email service.

### Step 5: Verify DNS Records
Double check your DNS records to ensure they are properly configured.

-- End of: /email/dns/namecheap-guide
-- Start of: /email/dns/shopify-guide
---
title: Shopify
description: How to set up your DNS records in Shopify.
---
### Step 1: Access Domain Settings
Log into your Shopify admin panel and navigate to the Domains section.

### Step 2: Select Domain
Click on the domain you want to configure from your domain list.

### Step 3: Access DNS Settings
In the domain details page, you'll find your current DNS configuration.


### Step 4: Add New DNS Record

Click the "Add Record" button to create a new DNS entry.

### Step 7: Add TXT and MX Records
Add any required TXT records for email authentication.

Do the same thing for the MX record and then verify the configuration.
-- End of: /email/dns/shopify-guide
-- Start of: /email/dns/cloudflare-guide
---
title: Cloudflare
description: How to set up your DNS records in Cloudflare.
---
### Step 1: Access DNS Settings
Log into your Cloudflare account and navigate to the DNS settings for your domain.

### Step 2: Navigate to the Records page under Domain
Click on "Add record" to begin adding the necessary email DNS records.

### Step 3: Configure MX Records
Add the TX and MX records that will direct email to the correct mail servers.

-- End of: /email/dns/cloudflare-guide
-- Start of: /email/dns/squarespace-guide
---
title: Squarespace
description: How to set up your DNS records in Squarespace.
---
### Step 1: Access Your Domain Settings
Navigate to your Squarespace domain management page and find your domain.

### Step 2: Add MX and TXT Records ( DKIM and SPF )
Click on the "Add New Record" button to add the email hosting records.

### Step 3: Verify Settings
Review your DNS settings to ensure all records are properly configured.

-- End of: /email/dns/squarespace-guide
-- Start of: /email/dns/index
---
title: Custom DNS
description: Learn how to set up your custom DNS in Quotient.
---
Email deliverability is critical to the success of your communications. Using a custom DNS for email not only reinforces your brand identity but also plays a vital role in ensuring that your messages reach inboxes reliably. This page provides an introduction to best practices for email deliverability through proper DNS configuration and outlines the process for setting up your DNS in Quotient.
## Best Practices for Email Deliverability
Setting up a custom DNS is a cornerstone for improving email deliverability. Here are some key best practices:
- **Authenticate Your Domain:**
Use SPF, DKIM, and DMARC records to verify that your emails are sent from trusted servers. This helps prevent spoofing and reduces the risk of your emails being marked as spam.
- **Ensure Proper DNS Configuration:**
Configure the necessary DNS records (MX, CNAME, TXT) correctly. Incorrect entries can lead to delays or failures in email delivery.
- **Monitor and Maintain Your DNS Records:**
Regularly review your DNS settings to ensure that all records are up-to-date. Changes in your infrastructure or email service may require DNS updates.
- **Leverage a Custom DNS for Brand Consistency:**
Custom DNS entries enhance your brand’s credibility and allow you greater control over email authentication, ultimately contributing to improved deliverability and user trust.
## Setting Up Custom DNS in Quotient
This section will guide you through the process of configuring your DNS settings specifically in Quotient. Detailed instructions, screenshots, and troubleshooting tips will be provided to ensure a smooth setup experience.
1. Navigate to the **[Email Settings](/s/most-recent-business/email-settings)** via the left hand navigation.

2. Scroll down to the Email Domains section.

3. Click the "Add Domain" button to add a new domain. Fill out the domain you want to use as your "From" address.

4. After you click "Add Domain", you will be redirected to the domain details page.

5. Copy the records shown on the domain details page to your DNS provider, including the DMARC TXT record (`_dmarc` / `v=DMARC1; p=none;`).
Here are the guides for the most popular DNS providers:
- [Shopify](/docs/email/dns/shopify-guide)
- [Namecheap](/docs/email/dns/namecheap-guide)
- [GoDaddy](/docs/email/dns/godaddy-guide)
- [Cloudflare](/docs/email/dns/cloudflare-guide)
- [Squarespace](/docs/email/dns/squarespace-guide)
Once you have added the MX, TXT, and DMARC records to your DNS provider, navigate back to the email domain details page and click the "Verify" button.
6. Hit refresh on the email domain list or details. This can take a few minutes and up to a few hours to verify.

7. Once verified, you will see the domain details a verified status and you are free to begin sending email from your domain.
-- End of: /email/dns/index
-- Start of: /email/variables/conditional-components
---
title: Conditional Components
description: How to create and use conditional components in emails
---
## Overview
Conditional components allow you to show or hide email components based on [email variable](/docs/email/variables/index) values.
### Building Conditional Components
Navigate into the **Email Template Editor** and select a component that you wish
to display conditionally. In the example below we are selecting the container
of our "Special VIP Offer" component. After selecting the component, we'll
navigate to the **Conditional Rendering** section in the **Style Editor** and click on the button in the **Style Editor** labeled "Add Conditions"

This will pull up our **Conditional Editor** where we can add, remove, and
edit the conditions that control whether "Special VIP Offer" will display.
Here, we've decided that we want this VIP section to display if the email
recipient has spent over $5000 or has more than 10 orders. Other recipients
will not see this section.

After creating the conditionals and saving our changes, we can navigate to the
**Preview Tab** to see how our email looks depending on our email variable values. In this case we are interested in `{{customer.total_spent}}` and
`{{customer.order_count}}`.
When we first navigate to the **Preview Tab**, we select a customer to test
the email against, in this case "Ayumu Hirano." Ayumu has not spent or ordered
with us, so the email that would be sent to her, does not contain our
VIP section.

We'd like to see what the email would look like if Ayumu had satisfied our
conditions, so we'll adjust her `{{customer.total_spent}}` to $7000 (this
will not affect Ayumu's underlying data and is only applied for the preview).
As we can see, if Ayumu had spent $7000 with us, the email that she receives
would contain our VIP section!

## Related Topics
-- End of: /email/variables/conditional-components
-- Start of: /email/variables/index
---
title: Email Variables
description: How to use variables in email templates.
---
Our email templating system allows you to insert dynamic variables into your email templates using the `{{topic.variable}}` format. These variables will be replaced with actual data when the email is sent. This ensures that your emails are personalized and relevant to each recipient.
## Available Variables
### Business Variables
You can reference the following variables to insert business-related details:
- `{{business.name}}` - The name of the business
- `{{business.brandName}}` - The brand name of the business
- `{{business.logoId}}` - The ID of the business logo
- `{{business.socialLinkFacebook}}` - Facebook link of the business
- `{{business.socialLinkInstagram}}` - Instagram link of the business
- `{{business.socialLinkPinterest}}` - Pinterest link of the business
- `{{business.socialLinkTwitter}}` - Twitter link of the business
- `{{business.socialLinkTikTok}}` - TikTok link of the business
- `{{business.socialLinkLinkedIn}}` - LinkedIn link of the business
- `{{business.domain}}` - The business domain name
- `{{business.websiteScreenshotUrl}}` - Screenshot URL of the business website
- `{{business.fullAddress}}` - The full address of the business
- `{{business.phoneNumber}}` - The phone number of the business
- `{{business.emailAddress}}` - The email address of the business
### Person Variables
These variables reference persons stored in our system:
- `{{person.id}}` - Unique identifier for the person
- `{{person.firstName}}` - First name from the person
- `{{person.lastName}}` - Last name from the person
- `{{person.emailAddress}}` - Email address from the person
- `{{person.countryCode}}` - Country code from the person
- `{{person.regionCode}}` - Region code from the person
- `{{person.city}}` - City from the person
- `{{person.timezones}}` - Timezones from the person
- `{{person.phone}}` - Phone from the person
- `{{person.totalSpent}}` - The total spending of the person
- `{{person.ordersCount}}` - The total number of orders of the person
If your business has custom person properties set up, you can reference them using:
- `{{person.properties.}}` - Custom person property
### Campaign Variables (Optional)
If enabled, you can reference campaign-related details:
- `{{campaign.id}}` - Unique campaign ID
- `{{campaign.name}}` - Campaign name
- `{{campaign.description}}` - Campaign description
- `{{campaign.start_date}}` - Campaign start date
- `{{campaign.end_date}}` - Campaign end date
### Event Variables (Only Available in Email Templates)
These variables reference events that triggered the email:
- `{{event.emailAddress}}` - Email address of the recipient
- `{{event.eventType}}` - Type of event that triggered the email
- `{{event.pathname}}` - Pathname of the event occurrence
- `{{event.referrerUrl}}` - URL of the referrer
- `{{event.timestamp}}` - Event timestamp
- `{{event.deviceId}}` - Device ID of the user
- `{{event.sessionId}}` - Session ID
- `{{event.userAgent}}` - User agent string
- `{{event.pageUrl}}` - URL of the page
- `{{event.clickUrl}}` - URL that was clicked
- `{{event.productHandle}}` - Product handle related to the event
- `{{event.productId}}` - Product ID
- `{{event.cartId}}` - Cart ID
- `{{event.emailId}}` - Email ID associated with the event
- `{{event.orderId}}` - Order ID
- `{{event.variantId}}` - Variant ID of the product
- `{{event.searchQuery}}` - Search query performed by the user
- `{{event.browserName}}` - Name of the browser
- `{{event.city}}` - City of the user
- `{{event.country}}` - Country of the user
- `{{event.zip}}` - ZIP code
- `{{event.timezone}}` - User's timezone
- `{{event.region}}` - User's region
- `{{event.regionName}}` - Name of the region
- `{{event.isp}}` - Internet Service Provider
- `{{event.operatingSystem}}` - Operating system used
- `{{event.hashedIp}}` - Hashed IP address
### Current Date Variables
The system provides access to current date information in various formats:
- `{{currentDate.date}}` - Full formatted date (e.g., "December 25, 2024")
- `{{currentDate.year}}` - Current year as a number (e.g., 2024)
- `{{currentDate.month}}` - Current month name (e.g., "December")
- `{{currentDate.day}}` - Current day of month as a number (e.g., 25)
### AI Variables
These variables are only available in email templates that are sent by an AI Email step in a flow execution:
- `{{ai.productId}}` - Product ID
- `{{ai.message}}` - Custom message
### Flow Variables
These variables are only available if the flow was triggered programmatically (via `flow.trigger()`) with caller-supplied metadata. Any key passed in `metadata` can be referenced as:
- `{{flow.metadata.}}` - A metadata value passed at trigger time (e.g. `{{flow.metadata.plan}}`)
## Best Practices
- Use only the variables listed above. Using unrecognized variables may cause emails to render incorrectly.
- Always use `{{business.id}}` instead of the literal business ID to avoid errors.
- Ensure that all necessary variables are present in your template before sending emails.
By following this guide, you can leverage dynamic templating to create personalized and data-driven campaigns.
## Related Topics
-- End of: /email/variables/index
-- Start of: /integrations/attio/field-mappings
---
title: Field Mappings
description: How Attio attributes map to Quotient fields and how to customize them
order: 2
---
Field mappings control how data moves between Attio and Quotient. When Attio sends a person record, Quotient needs to know which attribute becomes `firstName`, which becomes `jobTitle`, and where custom properties should land. Mappings make that explicit.
Quotient uses a two-phase approach: built-in logic handles critical fields (email addresses, record IDs, company associations, parsed address and revenue data), then configurable mappings, including defaults plus anything you add, fill in the rest.
Custom fields are commonly used in the CRM for business-specific attributes, for example which product SKUs a company uses, or what pricing plan a business is on. These fields are also highly relevant to marketing, and the Attio integration allows you to sync them bidirectionally to Quotient.
## Default Mappings
When you connect Attio, Quotient creates default mappings automatically. These defaults are **inbound** (Attio → Quotient). You can change direction or add mappings on the **[Attio integration settings](/s/most-recent-business/integrations/attio)** page under the **Person**, **Company**, and **Deal** tabs.
### People (Attio → Quotient)
Attio Attribute
Quotient Field
Notes
email_addresses
emailAddress
Built-in; primary email used for matching
name
firstName, lastName
Default mapping; parsed from Attio name components
job_title
jobTitle
Default mapping
avatar_url
avatarUrl
Default mapping
phone_numbers
mainPhoneNumber
Default mapping; primary number
linkedin, twitter, instagram
linkedinUrl, twitterUrl, instagramUrl
Default mappings
company
companyId (association)
Built-in; links person to synced company
Quotient also sets `source` to `ATTIO` and initializes email subscription status for new imports. Secondary email addresses and phone numbers from Attio are stored automatically without a separate mapping.
### Companies (Attio → Quotient)
Attio Attribute
Quotient Field
Notes
name
name
Default mapping
description
description
Default mapping
domains
domain
Default mapping
logo_url
logoUrl
Default mapping
facebook, instagram, twitter, linkedin, angellist
socialLink*
Default mappings
primary_location
address1, city, regionCode, zip, country
Built-in; parsed into address fields
categories, employee_range, estimated_arr_usd
industries, totalEmployees, revenue
Built-in; parsed from Attio structured values
### Deals (Attio → Quotient)
Attio Attribute
Quotient Field
Notes
name
name
Default mapping
stage
status
Default mapping; uses stage title
value
amount, currency
Built-in
associated_company, associated_people
companyId, person associations
Built-in
## Sync Direction
Each mapping has a direction that controls when it applies:
- **Inbound**: Attio updates Quotient (the default for pre-configured mappings).
- **Outbound**: Quotient updates Attio when person, company, or deal data changes in Quotient.
- **Bi-directional**: Changes in either system can update the other, subject to the sync engine and webhook processing.
Outbound and bi-directional mappings are useful when Quotient is the system of record for a field, such as a lead score or marketing qualification flag you want reflected on the Attio person record. Flows that include a **Send to CRM** step can also push person updates to Attio using your outbound person mappings.
## Adding Custom Mappings
To map an Attio custom attribute:
1. Open **[Attio integration settings](/s/most-recent-business/integrations/attio)**.
2. Select the **Person**, **Company**, or **Deal** tab.
3. Add a mapping between the Attio attribute and the Quotient field (standard or custom property).
4. Choose the sync direction that matches how you want data to flow.
Quotient loads available Attio attributes from your workspace when you edit mappings, so custom attributes you add in Attio appear in the picker after sync.
## Tips
- Start with defaults, then add mappings only for attributes you actually segment or personalize on. Unmapped Attio fields are ignored, which keeps Quotient uncluttered.
- Sync companies before relying on person-company links; the initial import already follows this order, but manual people-only syncs may temporarily show missing company associations until companies are present.
- If an Attio attribute type does not map cleanly to a Quotient field type, create a custom person or company property in Quotient first, then map the Attio attribute to it.
## Next Steps
- **[Setup guide](/docs/integrations/attio/setup)**: Connect Attio and run your first sync.
- **[Audience segments](/docs/audience/segments)**: Build segments from synced CRM fields.
- **[Flows](/docs/flow)**: Automate marketing and push updates back to Attio with **Send to CRM**.
-- End of: /integrations/attio/field-mappings
-- Start of: /integrations/attio/setup
---
title: Setup
description: Connect your Attio workspace to Quotient and run your first sync
order: 1
---
Connecting Attio to Quotient takes a few minutes. You need an Attio workspace
you can authorize apps for, and a Quotient plan that includes CRM integrations
(Pro and above).
## Prerequisites
Before you start, make sure you have:
- **An Attio workspace** with permission to install or authorize third-party
apps
- **A Quotient business** on a plan with CRM integrations enabled
- **Data in Attio** (people, companies, or deals) if you want to verify the sync
immediately after connecting
## Connect Your Attio Workspace
### Step 1: Open Integrations
In Quotient, go to **[Integrations](/s/most-recent-business/integrations)** and
find the **Attio** card. If CRM integrations are not included on your current
plan, Quotient will prompt you to upgrade before you can connect.
Click **Connect** to start the OAuth flow.
### Step 2: Authorize in Attio
Quotient redirects you to Attio's authorization page. Sign in if prompted,
select the workspace you want to connect, and review the permissions Quotient is
requesting. Click to grant access and return to Quotient.
Quotient requests read access to Attio records, object configuration, workspace
members, and related metadata needed to import and keep your CRM data in sync.
### Step 3: Confirm the connection
After authorization, you land on the
**[Attio integration settings](/s/most-recent-business/integrations/attio)**
page. You should see:
- **Status: Connected**
- **Last Updated** timestamp for the integration
- Tabs for **Person**, **Company**, and **Deal** field mappings
- **Sync Actions** and **Jobs** tabs for monitoring and manual syncs
Quotient automatically creates default field mappings and starts the initial
Attio import as soon as the connection succeeds. You do not need to toggle
individual object types on: people, companies, deals, and workspace members are
all included in the standard sync.
## What Happens During the First Sync
The initial import runs as a background job. Quotient:
1. Registers webhooks so future Attio changes stream into Quotient
2. Syncs workspace members (for ownership mapping)
3. Syncs companies
4. Syncs people and deals, linking them to the companies already in Quotient
Open the **Jobs** tab on the Attio integration page to watch progress. Large
workspaces can take a while depending on record volume; you can keep using
Quotient while the import runs.
Initial sync duration
The first import may take several hours for large workspaces. Check
the Jobs tab for completion status rather than waiting on the page.
## Ongoing Sync
Once connected, Quotient keeps Attio data current in two ways:
**Daily automatic sync**: Every night at midnight, Quotient re-runs a full Attio
import for your workspace.
**Webhooks**: When someone creates or updates a person, company, or deal in
Attio, Quotient processes that change without waiting for the nightly job.
### Manual sync
If you need a fresh import immediately (for example, after a bulk update in
Attio), use the **Sync Data** button on the
**[Attio integration settings](/s/most-recent-business/integrations/attio)**
page. This re-runs the full ETL and may overwrite Quotient records with the
latest Attio values.
For a lighter-touch refresh, open the **Sync Actions** tab and re-trigger only
the job you need (users, people, companies, or deals).
## Verify Your Setup
After the initial sync completes:
1. Open **[People](/s/most-recent-business/people)** and confirm Attio-sourced
records appear with the expected email addresses and company links.
2. Check **[Companies](/s/most-recent-business/companies)** and deals if you
sync pipeline data.
3. Review default **[field mappings](/docs/integrations/attio/field-mappings)** on the
Person, Company, and Deal tabs in integration settings.
Make a small edit to a test person in Attio and confirm the change appears in
Quotient (via webhook or after the next daily sync).
## Common Setup Issues
**Connection failed or redirect error**
- Confirm you selected the correct Attio workspace during authorization.
- Disable popup blockers for the OAuth window.
- Try connecting again from
**[Integrations](/s/most-recent-business/integrations)**.
**No data after connecting**
- Check the **Jobs** tab for failed or in-progress sync jobs.
- Confirm the connected Attio workspace actually contains people, companies, or
deals.
- Trigger **Sync Data** manually if the initial job did not start.
**Missing fields on imported records**
- Review **[field mappings](/docs/integrations/attio/field-mappings)**: only mapped Attio
attributes sync beyond the built-in fields (email, IDs, associations, and
similar core data).
- Add a custom mapping for any Attio attribute you need in segments or email
personalization.
## Next Steps
1. **[Configure Field Mappings](/docs/integrations/attio/field-mappings)**: Map Attio
attributes to Quotient fields and set sync direction.
2. **[Build segments](/docs/audience/segments)** from synced CRM data.
3. **[Create a Flow](/docs/flow)** with a **Send to CRM** step to push Quotient
updates back to Attio.
**Need help?** Ask Quotient for assistance with your Attio connection.
-- End of: /integrations/attio/setup
-- Start of: /integrations/attio/index
---
title: Attio
description: Connect your Attio workspace to Quotient for CRM-powered marketing
order: 2
---
The Attio integration syncs audience data between your CRM (Attio) and Quotient. People, Companies, and Deals sync from Attio into Quotient automatically; People also sync back from Quotient to Attio as new leads come in.
This allows you to:
- Build dynamic segments in Quotient using firmographic data from Attio (like company industry, company size, and deal stage) so you can tailor your marketing to each segment.
- Automatically send new leads collected by Quotient to Attio, or use a Flow with a Conditional step to send them to Attio only once they cross a lead score threshold or meet other criteria.
- Add conditional logic to Flows based on firmographic data from Attio. For example, build automated email sequences that behave differently for companies of different sizes or in different regions.
## Core Concepts
When you connect Attio to Quotient, here is how the pieces fit together:
**Attio workspace connection**
Quotient connects to Attio through OAuth. You authorize Quotient from Attio's login screen, and Quotient stores a secure access token for your workspace. No API keys to copy, and you can disconnect at any time from **[Integrations → Attio](/s/most-recent-business/integrations/attio)**.
**Synced objects**
The integration syncs Attio people, companies, deals, and workspace members. In Quotient, people become audience records you can email and segment on; companies and deals power account-level targeting and reporting; workspace members are imported so record ownership can be mapped correctly.
**Field mappings**
Field mappings control which Attio attributes sync to which Quotient fields. Quotient sets up sensible defaults when you connect, and you can add custom mappings for the attributes that matter to your business. See **[Field Mappings](/docs/integrations/attio/field-mappings)** for details.
**Sync**
Your Attio data stays up to date in Quotient automatically, and changes appear instantly.
## Working with Attio Data in Quotient
Most teams connect Attio to solve a simple problem: marketing should not live in a silo. Here is a typical workflow:
1. **Connect Attio** and wait for the initial import to finish. Monitor progress on the **Jobs** tab in integration settings.
2. **Review field mappings** so the Attio attributes you care about (ICP tier, lifecycle stage, ARR band) appear on Quotient people and companies.
3. **Build segments** from synced deal stage, company attributes, or custom properties.
4. **Use Flows** with a **Send to CRM** step when you want Quotient to push updated person fields back to Attio after a form submission or nurture sequence.
Tips for getting the most out of the integration:
- Map your most-used Attio custom attributes early, since segments and email personalization work best when the fields you filter on actually exist in Quotient.
- Ask Quotient to build segments from Attio-backed fields once sync completes; it can see the same properties you mapped.
- Use **Send to CRM** in Flows when a lead fills out a form in Quotient and you want that enrichment written back to the Attio person record.
## Getting Started
1. **[Connect Attio →](/docs/integrations/attio/setup)** Authorize your workspace and run the first sync.
2. **[Configure Field Mappings →](/docs/integrations/attio/field-mappings)** Customize how Attio attributes map to Quotient fields.
---
**Need help?** Ask Quotient for assistance with your Attio integration, or contact our support team.
-- End of: /integrations/attio/index
-- Start of: /integrations/hubspot/email-sync
---
title: Email Sync
description:
Sync Quotient email templates and broadcasts to HubSpot as marketing emails
order: 5
---
## Overview
Quotient's email synchronization feature allows you to seamlessly sync your
email templates and broadcasts to HubSpot as marketing emails. This integration
enables you to leverage HubSpot's email delivery infrastructure while
maintaining Quotient's AI-powered content creation and campaign management
capabilities.
The email sync system automatically creates a customizable base template in
HubSpot and handles the complex process of converting Quotient's email format to
HubSpot's marketing email structure.
## Prerequisites
### HubSpot Plan Requirements
Email synchronization requires specific HubSpot capabilities:
- **Marketing Hub Starter** or higher (for marketing email functionality)
- **Marketing Email API access** (included in paid Marketing Hub plans)
- **Design Manager access** (for template customization)
### Required Permissions
Your HubSpot integration needs these scopes:
- `content` - For creating and managing email templates
Plan Compatibility
Email sync is designed to work gracefully across HubSpot plan levels.
CRM-only users get core contact and list management, while Marketing
Hub users get full email broadcasting capabilities.
## Setting Up Email Sync
### Step 1: Enable Email Synchronization
1. **Navigate** to HubSpot integration settings and go to the **Email** tab
2. **View the Email Sync configuration** section
3. **Click "Enable Sync"** to activate email synchronization and confirm the
setup
### Step 2: Template Setup
When you enable email sync, Quotient automatically:
1. **Validates your HubSpot capabilities** to ensure email sync is supported
2. **Creates the base template** (`quotient-base.html`) in your HubSpot Design
Manager
3. **Configures the template** with the required modules for Quotient email
injection
4. **Tests the setup** to ensure emails can be created successfully
Automatic Template Creation
Quotient automatically creates and validates the{" "}
quotient-base.html template in your HubSpot Design
Manager. This template includes all necessary modules and structure
for seamless email injection.
## The quotient-base.html Template
### What It Is
The `quotient-base.html` template is a custom HubSpot email template that
Quotient creates in your Design Manager. This template serves as the foundation
for all emails synced from Quotient to HubSpot.
**Key Features:**
- **Email body injection point** - Where Quotient inserts your email content
- **Customizable footer** - Editable company information and unsubscribe links
- **HubSpot compliance** - Includes required unsubscribe and view-as-webpage
links
- **Responsive design** - Works across all email clients and devices
### Template Structure
The template includes these essential components:
```html
```
### Customizing the Footer
You can customize the footer of the `quotient-base.html` template through
HubSpot's Design Manager:
1. **In HubSpot**, go to Marketing → Files and Templates → Design Manager
2. **Navigate** to the Templates folder
3. **Find and click** `quotient-base.html`
4. **Edit the footer section** (the `
` element)
5. **Customize** company information, styling, and additional links
6. **Save** your changes
The screenshot above shows HubSpot's Design Manager where you can customize the
`quotient-base.html` template. You can also view the template structure:
**What You Can Customize:**
- Company name and address formatting
- Footer styling (colors, fonts, layout)
- Additional links (privacy policy, social media)
- Custom branding elements
- Legal disclaimers or compliance text
Don't Modify Core Structure
While you can customize the footer and styling, avoid modifying the
core template structure or the{" "}
email_template_main_email_body module, as this could
break email injection from Quotient.
## Email Template Sync
### How Template Sync Works
When you sync a Quotient email template to HubSpot:
1. **Template Creation**: Creates a new marketing email in HubSpot using
`quotient-base.html`
2. **Content Injection**: Injects your Quotient email content into the template
body
3. **Style Mapping**: Converts Quotient styling to HubSpot-compatible CSS
4. **Metadata Transfer**: Copies template name, subject line, and other metadata
### Syncing Email Templates & Broadcasts
**To sync an email template or broadcast:**
1. **In Quotient**, navigate to your email template or broadcast
2. **Click "Sync to HubSpot"** in the actions menu
3. **Success confirmation** - A toast notification will confirm the sync was
successful
That's it! Your email template or broadcast is now available in HubSpot as a
marketing email.
**Template Updates:**
- Changes to Quotient templates can be re-synced to update the HubSpot version
- HubSpot maintains a link to the original Quotient template
- Simply click "Sync to HubSpot" again to update the HubSpot version
### What Gets Synced
**Template Properties:**
- Template name and description
- Email subject line
- HTML content and styling
- Preview text
- Template categorization
**Content Handling:**
- **HTML Structure**: Preserved with HubSpot-compatible formatting
- **Images**: Uploaded to HubSpot's file manager and linked
- **Styling**: Converted to inline CSS for email client compatibility
- **Dynamic Content**: Quotient variables mapped to HubSpot personalization
tokens
### Audience Targeting
**List Mapping:**
- Quotient lists are automatically synced to HubSpot static lists
- Quotient segments map to HubSpot dynamic lists (where possible)
- Multiple lists can be combined for complex targeting
### Scheduling and Delivery
**Scheduling Options:**
- **Immediate send**: Send the email right away through HubSpot
- **Scheduled send**: Set a specific date and time for delivery
- **Draft mode**: Create the email in HubSpot without scheduling
**Delivery Tracking:**
- Email status syncs back from HubSpot to Quotient
Status Synchronization
Email broadcast status syncs from HubSpot back to Quotient: DRAFT,
SCHEDULED, and LAUNCHED states are automatically updated to keep both
systems in sync.
## Email Status Tracking
### Status Mapping
Email status is synchronized between systems to provide accurate campaign
tracking:
HubSpot Status
Quotient Status
Description
DRAFT
DRAFT
Email created but not scheduled
SCHEDULED
SCHEDULED
Email scheduled for future delivery
PROCESSING
LAUNCHED
Email currently being sent
SENT
LAUNCHED
Email delivery completed
PUBLISHED
LAUNCHED
Email published and available
## Troubleshooting Email Sync
### Common Issues
**Template Creation Failed**
- Verify HubSpot plan includes marketing email functionality
- Check Design Manager permissions in HubSpot
- Ensure the `quotient-base.html` template was created successfully
**Email Content Not Displaying**
- Verify the email template uses the correct base template
- Check that the `email_template_main_email_body` module exists
- Review HTML formatting for HubSpot compatibility
**Audience Targeting Issues**
- Ensure target lists are synced to HubSpot
- Verify list members have valid email addresses
- Check HubSpot list permissions and access
**Status Not Updating**
- Check that email broadcast has a valid HubSpot ID
- Review sync logs for status update errors
- Trigger manual sync to refresh status information
### Best Practices
**Template Management:**
- Use descriptive names for synced templates
- Regularly review and clean up unused templates in HubSpot
- Test template rendering across different email clients
**Content Optimization:**
- Optimize images for email delivery before syncing
- Use HubSpot-compatible HTML and CSS
- Test personalization tokens with sample data
**Audience Management:**
- Keep lists synchronized and up-to-date
- Use suppression lists to manage unsubscribes
- Segment audiences appropriately for targeted campaigns
## Next Steps
Once you've set up email synchronization:
1. **[Troubleshooting](/docs/integrations/hubspot/troubleshooting)** - Track email sync
operations and performance
2. **[Advanced Workflows](/docs/flow)** - Integrate email campaigns with
Quotient automation
3. **[Campaign Attribution](/docs/campaign)** - Track email performance in
multi-channel campaigns
---
**HubSpot Help Resources:**
- [HubSpot Email Marketing](https://knowledge.hubspot.com/email) - Complete
email marketing guide
- [Using Design Manager](https://knowledge.hubspot.com/cos-general/use-the-design-manager) -
Template customization help
- [Creating Email Templates](https://knowledge.hubspot.com/email/create-and-edit-email-templates) -
Template creation guide
- [Email Personalization](https://knowledge.hubspot.com/email/use-personalization-tokens-in-your-emails) -
Personalizing your emails
-- End of: /integrations/hubspot/email-sync
-- Start of: /integrations/hubspot/field-mappings
---
title: Field Mappings
description:
Configure how HubSpot fields map to Quotient fields and work with custom
properties
order: 3
---
## Overview
Field mappings control how data flows between HubSpot and Quotient, ensuring
that information is correctly synchronized between the two systems. Quotient
uses a sophisticated two-phase transformation system that combines built-in
mappings for critical fields with user-configurable mappings for custom business
needs.
## How Field Mappings Work
### Two-Phase Transformation System
Quotient processes HubSpot data through two distinct phases:
**Phase 1: Built-in Transformations**
- Non-configurable logic for critical and complex fields
- Handles essential data like email addresses, IDs, and relationships
- Manages complex transformations like address parsing and revenue calculations
**Phase 2: Configurable Mappings**
- User-customizable mappings for standard and custom fields
- Default mappings provided for common HubSpot properties
- Support for custom properties and business-specific fields
This approach ensures data integrity for critical fields while providing
flexibility for your unique business requirements.
## Default Field Mappings
Quotient provides sensible default mappings for common HubSpot properties. These
can be customized to match your specific needs.
### Contact (HubSpot) → Person (Quotient)
HubSpot Field
Quotient Field
Type
Direction
email
emailAddress
Built-in
Bi-directional
firstname
firstName
Default
Inbound
lastname
lastName
Default
Inbound
jobtitle
jobTitle
Default
Inbound
phone
mainPhoneNumber
Default
Inbound
department
department
Default
Inbound
### Company (HubSpot) → Company (Quotient)
HubSpot Field
Quotient Field
Type
Direction
name
name
Built-in + Default
Bi-directional
description
description
Default
Inbound
industry
industry
Built-in + Default
Inbound
website
website
Default
Inbound
phone
phoneNumber
Default
Inbound
annualrevenue
revenue
Built-in
Inbound
numberofemployees
totalEmployees
Built-in
Inbound
Built-in vs Default Mappings
Built-in mappings handle critical fields and complex
transformations that ensure data integrity.{" "}
Default mappings are user-configurable and can be
modified to match your business needs.
## Built-in Transformations
These transformations are automatically applied and cannot be modified to ensure
data integrity:
### Contact Built-ins
- **`emailAddress`**: Critical for person identification and deduplication
- **`hubspotId`**: Maintains sync relationship between systems
- **`source`**: Automatically set to "HUBSPOT" for tracking
- **`associatedCompanyHubspotIds`**: Preserves company relationships
- **Email Marketing Defaults**: New contacts default to "NOT_SUBSCRIBED"
### Company Built-ins
- **Address Parsing**: HubSpot's combined address fields are decomposed into:
- `address` (street address)
- `city`
- `state`
- `zip`
- `country`
- **Revenue Processing**: Handles currency conversion and formatting
- **Industry Arrays**: Converts HubSpot industry strings to Quotient arrays
- **Social Media Links**: Extracts and formats social media URLs
### Deal Built-ins
- **Pipeline Mapping**: Preserves HubSpot pipeline and stage information
- **Amount Formatting**: Handles currency and decimal formatting
- **Date Processing**: Converts HubSpot date formats to Quotient standards
## Custom Properties
### Creating Custom Properties in HubSpot
Before mapping custom properties, ensure they exist in HubSpot:
1. **In HubSpot**, go to Settings → Properties
2. **Select the object type** (Contacts, Companies, or Deals)
3. **Create a new property** with these considerations:
- Choose an appropriate **field type** (text, number, date, etc.)
- Set a clear **internal name** (this will be used in mappings)
- Configure **field options** if using dropdowns or checkboxes
### Supported Property Types
Quotient supports all HubSpot property types with automatic data conversion:
HubSpot Type
Quotient Type
Notes
Single-line text
STRING
Direct mapping
Multi-line text
STRING
Preserves line breaks
Number
NUMBER
Handles decimals and integers
Date picker
DATE
Date only, no time
Date & time picker
DATETIME
Full timestamp with timezone
Dropdown select
SINGLE_SELECT
Maps option values, single choice
Multiple checkboxes
MULTI_SELECT
Multiple values from predefined options
Multi-line text (as list)
LIST
Flexible text list, line-separated
Radio select
ENUM
Single value selection
Yes/No
BOOLEAN
True/false values
HubSpot user
USER
Maps to Quotient users
### Mapping Custom Properties
To create a custom field mapping:
1. **Navigate** to
**[HubSpot integration settings](/s/most-recent-business/integrations/hubspot)**
2. **Go to Field Mappings** section
3. **Click "Add Field Mapping"**
4. **Select the HubSpot Field**: Choose from available HubSpot properties
5. **Configure the mapping**:
- **Quotient Field**: Choose existing field or create new custom property
- **Data Type**: Automatically detected but can be overridden
- **Sync Direction**: Choose Inbound, Outbound, or Bi-directional
### Example: Custom Lead Score Mapping
Let's say you have a custom "Lead Score" property in HubSpot that you want to
sync to Quotient:
**HubSpot Setup:**
- Property name: `lead_score`
- Type: Number
- Used for: Lead qualification scoring
**Quotient Mapping:**
- **HubSpot Field**: `lead_score`
- **Quotient Field**: `leadScore` (custom property)
- **Data Type**: `NUMBER`
- **Direction**: `INBOUND` (HubSpot is the source of truth)
## Advanced Mapping Scenarios
### Handling Enumeration Fields
For HubSpot dropdown and checkbox properties:
**HubSpot Options:**
```
- Option 1: "Enterprise"
- Option 2: "Mid-Market"
- Option 3: "SMB"
```
**Quotient Mapping:**
- Values are mapped exactly as they appear in HubSpot
- Multiple selections are joined with semicolons
- Empty selections map to null values
### Date and Time Handling
**Date Fields:**
- HubSpot date-only fields map to Quotient `DATE` type
- Time information is ignored for date-only fields
- Timezone is preserved for datetime fields
**DateTime Fields:**
- Full timestamp with timezone information
- Automatic conversion between HubSpot and Quotient formats
- Handles daylight saving time transitions
### User and Owner Mappings
**HubSpot Owner Fields:**
- `hubspot_owner_id` maps to Quotient user assignments
- Requires users to exist in both systems
- Falls back to null if user mapping not found
## Managing Field Mappings
### Viewing Current Mappings
In the HubSpot integration settings:
1. **Default Mappings**: Pre-configured mappings for standard fields
2. **Custom Mappings**: Your business-specific field mappings
3. **System Mappings**: Built-in mappings that cannot be modified
### Modifying Mappings
**To Edit a Mapping:**
1. Find the mapping in the Field Mappings section
2. Click the edit icon
3. Modify the configuration
4. Save changes (triggers a sync for affected records)
**To Delete a Mapping:**
1. Click the delete icon next to the mapping
2. Confirm the deletion
3. Data previously synced through this mapping remains unchanged
### Testing Mappings
**Field Mapping Validation:**
- Test mappings with sample data before full deployment
- Use the "Test Sync" feature for individual records
- Monitor sync logs for mapping errors or data type issues
## Troubleshooting Field Mappings
### Common Issues
**Data Not Syncing**
- Verify the field exists in both HubSpot and Quotient
- Check that data types are compatible
- Ensure the mapping direction allows the desired data flow
**Data Type Errors**
- Review HubSpot property type vs Quotient field type
- Check for invalid data in source fields (e.g., text in number fields)
- Verify enumeration options match between systems
**Missing Custom Properties**
- Ensure custom properties are created in HubSpot first
- Check property permissions and visibility settings
- Verify the property is associated with the correct object type
### Best Practices
**Naming Conventions**
- Use consistent naming between HubSpot and Quotient
- Avoid special characters in custom property names
- Use descriptive names that indicate the field's purpose
**Data Type Selection**
- Choose the most restrictive appropriate data type
- Use `ENUM` for fields with limited, known values
- Use `STRING` for flexible text fields
**Sync Direction Strategy**
- Use `INBOUND` when HubSpot is the authoritative source
- Use `OUTBOUND` when Quotient generates the data
- Use `BIDIRECTIONAL` carefully to avoid sync conflicts
## Read-Only Properties
When syncing data from HubSpot, you may want to mark certain Quotient properties
as **read-only**. This prevents users from editing these values in Quotient
since HubSpot is the source of truth.
**When to use read-only properties:**
- **Inbound-only sync**: Data flows from HubSpot to Quotient but not back
- **CRM-managed fields**: Values that should only be updated in HubSpot
- **Calculated fields**: Scores or metrics computed in HubSpot
- **Compliance data**: Information that requires CRM approval to change
**Setting up read-only properties:**
1. When creating or editing a custom property in Quotient, check the "Read-only"
checkbox
2. Read-only properties can still be used for segmentation and email
personalization
3. Users will see these values but cannot edit them in forms or preference pages
**Example use cases:**
- Lead scores calculated by HubSpot workflows
- Company industry classifications from HubSpot
- Deal stages and pipeline information
- Compliance flags or certification statuses
## Next Steps
Once you've configured field mappings:
1. **[Set Up List Synchronization](/docs/integrations/hubspot/lists)** - Configure list and
segment sync
2. **[Enable Email Sync](/docs/integrations/hubspot/email-sync)** - Sync email templates and
broadcasts
3. **[Monitor Sync Performance](/docs/integrations/hubspot/troubleshooting)** - Track and
optimize sync operations
---
**HubSpot Help Resources:**
- [HubSpot Properties Guide](https://knowledge.hubspot.com/properties) - How to
create and manage properties
- [Custom Properties in HubSpot](https://knowledge.hubspot.com/properties/create-and-edit-properties) -
Step-by-step property creation
- [HubSpot CRM Setup](https://knowledge.hubspot.com/crm-setup) - General CRM
configuration help
-- End of: /integrations/hubspot/field-mappings
-- Start of: /integrations/hubspot/index
---
title: HubSpot
description: Connect your HubSpot CRM with Quotient for powerful marketing automation
order: 1
---
## Overview
The Quotient HubSpot integration provides comprehensive two-way synchronization between your HubSpot CRM and Quotient's AI-powered marketing platform. This integration enables you to leverage your existing CRM data for sophisticated marketing campaigns while maintaining data consistency across both platforms.
### Key Benefits
- **Bi-directional sync** of contacts, companies, and deals
- **Automated sync scheduling** with daily updates and on-demand synchronization
- **Flexible field mappings** with support for custom properties
- **Smart list synchronization** that respects HubSpot's dynamic vs static list types
- **Email template and broadcast sync** with customizable branding
- **Automated workflows** that trigger based on CRM data changes
### What Gets Synced
The integration supports synchronization of the following HubSpot objects:
HubSpot Object
Quotient Equivalent
Sync Direction
Contacts
People
Bi-directional
Companies
Companies
Bi-directional
Deals
Deals
Inbound only
Dynamic Lists
Segments
Inbound only
Static Lists
Lists
Bi-directional
Marketing Emails
Email Templates & Broadcasts
Outbound only
## How It Works
The integration keeps your data synchronized through multiple processes:
1. **Daily Automatic Sync**: Complete synchronization of all enabled data every night at midnight
2. **Manual Sync**: On-demand synchronization you can trigger anytime
3. **Background Processing**: Automatic progress tracking and error handling
4. **Scheduled Updates**: Regular data refresh to keep information current
### Security & Privacy
The integration uses secure authentication with HubSpot to protect your data. All information is encrypted during transfer, and you have complete control over what data is synchronized between the two platforms.
## Getting Started
1. Setup & Configuration
Connect your HubSpot account and configure basic sync settings.
## Advanced Features
### Email Integration
Sync your Quotient email templates and broadcasts directly to HubSpot as marketing emails. The integration automatically creates a customizable `quotient-base.html` template in your HubSpot Design Manager.
[Learn about Email Sync →](/docs/integrations/hubspot/email-sync)
### Custom Properties & Advanced Mappings
Create sophisticated field mappings between HubSpot custom properties and Quotient's flexible data model. Support for all HubSpot property types including enumerations, dates, and calculated fields.
[Advanced Field Mappings →](/docs/integrations/hubspot/field-mappings#custom-properties)
## Support & Resources
### HubSpot Help Resources
- [HubSpot Knowledge Base](https://knowledge.hubspot.com/) - Official HubSpot help articles
- [HubSpot Community](https://community.hubspot.com/) - User forums and discussions
- [HubSpot Academy](https://academy.hubspot.com/) - Free training courses
- [HubSpot Support](https://help.hubspot.com/) - Contact HubSpot support directly
### Troubleshooting
Having issues with your HubSpot integration? Check our comprehensive troubleshooting guide.
[Troubleshooting Guide →](/docs/integrations/hubspot/troubleshooting)
---
**Need Help?** Contact our support team or ask Quotient for assistance with your HubSpot integration.
-- End of: /integrations/hubspot/index
-- Start of: /integrations/hubspot/lists
---
title: Lists and Segments
description:
Understand how HubSpot lists sync with Quotient segments and lists, including
dynamic vs static behavior
order: 4
---
## Overview
HubSpot's list system works differently from traditional static lists, offering
both dynamic (automatically updating) and static (manually managed) list types.
Quotient's integration intelligently maps these to the appropriate Quotient
equivalent: **dynamic lists become segments** and **static lists become lists**.
This smart routing ensures that the automatic updating behavior of HubSpot
dynamic lists is preserved in Quotient segments, while static lists maintain
their manual management characteristics.
## Understanding HubSpot List Types
### Dynamic Lists (Active Lists)
Dynamic lists in HubSpot automatically update their membership based on criteria
you define. When a contact meets or stops meeting the criteria, they're
automatically added or removed from the list.
**Key Characteristics:**
- **Automatically maintained** by HubSpot based on contact properties
- **Automatic updates** when contact data changes during sync cycles
- **Criteria-based membership** using HubSpot's filtering system
- **Cannot manually add/remove contacts** - membership is determined by criteria
**Common Use Cases:**
- Contacts in a specific lifecycle stage
- Companies with revenue above a threshold
- Contacts who haven't been contacted in 30 days
- Leads from specific marketing campaigns
Dynamic Lists → Quotient Segments
HubSpot dynamic lists sync to Quotient as segments{" "}
because both automatically update their membership based on criteria.
The filtering logic remains in HubSpot, while Quotient maintains the
membership list.
### Static Lists (Manual Lists)
Static lists in HubSpot are manually managed collections where you explicitly
add and remove contacts. They don't automatically update based on criteria.
**Key Characteristics:**
- **Manually managed** - you control who's in the list
- **Fixed membership** until you make changes
- **Can import contacts** from files or other sources
- **Supports bulk operations** for adding/removing contacts
**Common Use Cases:**
- Event attendee lists
- Webinar registrants
- Import lists from external sources
- One-time campaign targets
- Suppression lists
Static Lists → Quotient Lists
HubSpot static lists sync to Quotient as lists{" "}
because both are manually managed collections. You can add/remove
people in either system and changes will sync bi-directionally.
## How List Sync Works
### Smart Routing System
Quotient automatically determines the correct destination for each HubSpot list
based on its `processingType`:
HubSpot List Type
Processing Type
Quotient Destination
Sync Direction
Dynamic List
DYNAMIC
Segment
Inbound only
Static List
MANUAL
List
Bi-directional
Snapshot List
SNAPSHOT
List
Bi-directional
### Sync Dependencies
List synchronization requires contact synchronization to be enabled:
- **Contacts must be synced first** - lists are meaningless without the people
in them
- **Automatic dependency management** - enabling lists automatically enables
contact sync
- **Member resolution** - Quotient matches list members by email address
## Dynamic Lists → Segments
### What Gets Synced
When a HubSpot dynamic list syncs to a Quotient segment:
**Segment Properties:**
- **Name**: Copied from HubSpot list name
- **Description**: HubSpot description or auto-generated description
- **Criteria**: Empty placeholder (filtering logic remains in HubSpot)
- **Members**: Current list membership from HubSpot
**Sync Behavior:**
- **Inbound only** - changes flow from HubSpot to Quotient
- **Membership updates** - when HubSpot criteria add/remove contacts
- **Scheduled sync** - membership updates during daily sync cycles
- **Daily refresh** - complete membership sync during nightly sync
### Limitations
Since the filtering logic remains in HubSpot:
- **Cannot edit criteria in Quotient** - segment criteria are managed in HubSpot
- **Read-only membership** - cannot manually add/remove people in Quotient
- **HubSpot dependency** - segment updates require active HubSpot integration
Why Segments Are Read-Only
Segments created from HubSpot dynamic lists are read-only in Quotient
to prevent conflicts with HubSpot's automatic membership management.
The criteria and membership are controlled by HubSpot's filtering
system.
## Static Lists → Lists
### What Gets Synced
When a HubSpot static list syncs to a Quotient list:
**List Properties:**
- **Name**: Copied from HubSpot list name
- **Slug**: Auto-generated from name (with conflict resolution)
- **Description**: HubSpot description or auto-generated description
- **Members**: All contacts currently in the HubSpot list
**Sync Behavior:**
- **Bi-directional** - changes flow both ways
- **Member management** - add/remove people in either system
- **Conflict resolution** - most recent change wins
- **Bulk operations** - supports large membership changes
### Bi-directional Sync Capabilities
**From HubSpot to Quotient:**
- Adding contacts to HubSpot list adds people to Quotient list
- Removing contacts from HubSpot list removes people from Quotient list
- Renaming HubSpot list updates Quotient list name
**From Quotient to HubSpot:**
- Adding people to Quotient list adds contacts to HubSpot list
- Removing people from Quotient list removes contacts from HubSpot list
- List changes trigger immediate sync to HubSpot
### Smart Member Sync
The integration performs intelligent member synchronization:
**Contact Resolution:**
- Matches members by email address between systems
- Handles contacts that exist in one system but not the other
- Creates contacts in HubSpot if they don't exist (when syncing from Quotient)
**Conflict Handling:**
- Timestamp-based resolution for simultaneous changes
- Preserves manual additions/removals from both systems
- Logs conflicts for review and manual resolution
## Syncing Lists Back to HubSpot
### Creating New Lists in HubSpot
You can sync Quotient lists to HubSpot to create new static lists:
1. **In Quotient**, navigate to your list
2. **Click "Sync to HubSpot"** in the list actions menu
3. **Choose sync options**:
- Create new HubSpot list
- Link to existing HubSpot list
- One-time sync or ongoing synchronization
### Sync Process
**Initial Sync:**
1. **List Creation**: Creates a new static list in HubSpot with the same name
2. **Member Addition**: Adds all Quotient list members to the HubSpot list
3. **Link Establishment**: Creates sync relationship between the lists
**Ongoing Sync:**
- **Scheduled updates** when members are added/removed in Quotient
- **Batch processing** for large membership changes
- **Error handling** for contacts that don't exist in HubSpot
### Requirements for Outbound Sync
**Contact Requirements:**
- All list members must have email addresses
- Contacts should exist in HubSpot or be syncable to HubSpot
- Email addresses must be valid and not suppressed
**HubSpot Permissions:**
- Write access to HubSpot lists
- Contact creation permissions (if creating new contacts)
- Appropriate HubSpot plan with list functionality
## Managing List Sync
### Enabling List Synchronization
1. **Navigate** to HubSpot integration settings and go to the **Person** tab
2. **View the List Sync section** to see available list synchronization options
3. **Click "Enable Sync"** to activate list synchronization for the Person
object
### Monitoring List Sync
Monitor your list synchronization through the **Jobs** tab in the HubSpot
settings:
**Job Monitoring Features:**
- **Job History**: View all list sync jobs that have been executed
- **Progress Tracking**: Monitor sync progress with detailed progress bars
- **Job Status**: See which jobs are completed, running, or failed
- **Execution Details**: View start times, duration, and record counts
- **Object Types**: See what type of lists each job synchronized
### List Sync Details
You can also view detailed information about individual list sync operations:
**Sync Logs:**
- **Member changes**: Detailed log of additions/removals
- **Conflict resolution**: How conflicts were resolved
- **Error details**: Specific errors for failed operations
### Troubleshooting List Issues
**Lists Not Syncing:**
- Verify contact sync is enabled and working
- Check that lists contain contacts with email addresses
- Review HubSpot permissions for list access
**Member Mismatches:**
- Ensure email addresses match between systems
- Check for suppressed or invalid email addresses
- Review contact sync status for list members
**Sync Conflicts:**
- Review conflict resolution logs
- Check for simultaneous changes in both systems
- Verify network connectivity during sync operations
## Best Practices
### List Organization Strategy
**Use Dynamic Lists For:**
- Automated segmentation based on contact properties
- Lifecycle stage management
- Behavioral targeting (page views, email engagement)
- Lead scoring and qualification
**Use Static Lists For:**
- Event attendees and registrations
- Import lists from external sources
- One-time campaign targets
- Manual curation and suppression lists
### Naming Conventions
**Consistent Naming:**
- Use descriptive names that indicate the list purpose
- Include date ranges for time-sensitive lists
- Use prefixes to group related lists (e.g., "Event*", "Campaign*")
**Avoid Conflicts:**
- Check for existing list names before creating new ones
- Use unique identifiers for similar lists
- Consider slug generation when naming lists
### Performance Optimization
**Large Lists:**
- Monitor sync performance for lists with >10,000 members
- Consider breaking very large lists into smaller segments
- Use batch operations for bulk membership changes
**Sync Frequency:**
- Rely on daily automatic sync for regular updates
- Use manual sync when immediate updates are needed
- Monitor sync performance in the integration dashboard
## Next Steps
Once you've configured list synchronization:
1. **[Set Up Email Sync](/docs/integrations/hubspot/email-sync)** - Sync email templates and
broadcasts
2. **[Monitor Performance](/docs/integrations/hubspot/troubleshooting)** - Track sync
operations and optimize performance
3. **[Advanced Workflows](/docs/flow)** - Use synced lists in Quotient
automation flows
---
**HubSpot Help Resources:**
- [HubSpot Lists Guide](https://knowledge.hubspot.com/lists) - Complete guide to
HubSpot lists
- [Creating Lists in HubSpot](https://knowledge.hubspot.com/lists/create-active-or-static-lists) -
Step-by-step list creation
- [Managing Your Lists](https://knowledge.hubspot.com/lists/manage-your-lists) -
List management best practices
-- End of: /integrations/hubspot/lists
-- Start of: /integrations/hubspot/objects
---
title: Objects
description:
Configure which HubSpot objects sync with Quotient and understand sync
behavior
order: 2
---
## Overview
Quotient's HubSpot integration supports synchronization of multiple object
types, each with specific capabilities and sync directions. This page explains
how to enable and configure object synchronization to meet your business needs.
## Supported Objects
### Contacts ↔ People (Bi-directional)
HubSpot contacts sync with Quotient people, maintaining a complete
bi-directional relationship.
**Key Features:**
- **Full bi-directional sync** - changes in either system update the other
- **Email-based matching** - contacts are matched by email address
- **Company associations** - maintains relationships between contacts and
companies
- **Custom properties** - supports all HubSpot contact property types
**What Gets Synced:**
- Basic contact information (name, email, phone, job title)
- Company associations and relationships
- Custom properties and fields
- Contact owner assignments
- Lifecycle stage and lead status
Email Subscription Status
Contacts synced from HubSpot are initially set to "NOT_SUBSCRIBED" for
email marketing in Quotient. You'll need to manage email preferences
separately or use Quotient's double opt-in process.
### Companies (Bi-directional)
HubSpot companies sync with Quotient companies, including complex data like
addresses and revenue information.
**Key Features:**
- **Bi-directional sync** with intelligent conflict resolution
- **Address parsing** - HubSpot address fields are decomposed into structured
data
- **Revenue handling** - supports multiple currencies and revenue tracking
- **Industry categorization** - maps HubSpot industry fields to Quotient
categories
**What Gets Synced:**
- Company name and description
- Complete address information (street, city, state, zip, country)
- Revenue and employee count
- Industry and company type
- Website and social media links
- Custom company properties
### Deals (Inbound Only)
HubSpot deals are imported into Quotient for reporting and campaign attribution,
but changes in Quotient don't sync back to HubSpot.
**Key Features:**
- **Read-only sync** from HubSpot to Quotient
- **Deal stage tracking** - maintains HubSpot pipeline and stage information
- **Revenue attribution** - connects deals to marketing campaigns and activities
- **Company associations** - links deals to their associated companies
**What Gets Synced:**
- Deal name and description
- Deal amount and currency
- Pipeline and stage information
- Close date and probability
- Associated company and contacts
- Deal owner and team assignments
Why Deals Are Read-Only
Deals remain read-only in Quotient to maintain HubSpot as the
authoritative source for sales pipeline data. This prevents conflicts
and ensures your sales team continues to manage deals in their
familiar HubSpot environment.
## Enabling Object Sync
### Step 1: Access HubSpot Settings
1. Navigate to **Settings** → **Integrations** → **HubSpot**
2. Click the **Settings** button on your connected HubSpot integration
3. You'll be taken to the HubSpot settings page with tabs for each object type
you can sync
### Step 2: Configure Object Sync
In the HubSpot settings page, you'll see tabs for each available object type:
- **Person** tab - Configure HubSpot contacts sync with Quotient people
- **Company** tab - Configure company information sync (bi-directional)
- **Deal** tab - Configure HubSpot deals import (read-only)
- **Email** tab - Configure email template and broadcast sync
- **Jobs** tab - View and manage sync jobs and status
Click on each tab to enable and configure the sync settings for that object
type.
### Step 3: Understand Dependencies
Some objects have dependencies that are automatically managed:
**Lists & Segments** → **Contacts**
- Enabling Lists automatically enables Contacts sync
- Disabling Contacts automatically disables Lists sync
- This ensures list memberships can be properly maintained
### Step 4: Save and Sync
1. Click **Save Preferences** to apply your changes
2. Quotient will automatically trigger a sync for newly enabled objects
3. Monitor progress in the sync status dashboard
## Sync Behavior & Timing
### Initial Sync
When you first enable an object type:
1. **Full Import**: All existing records are imported from HubSpot
2. **Batch Processing**: Large datasets are processed in batches of 50 records
3. **Progress Tracking**: Real-time progress updates in the integration
dashboard
4. **Completion Notification**: Email notification when sync completes
### Ongoing Synchronization
After the initial sync, objects are kept in sync through:
**Daily ETL Process**
- Runs every night at midnight
- Processes all changes from the last 24 hours
- Handles bulk updates and data consistency checks
**Scheduled Updates**
- Regular synchronization during daily sync cycles
- Processes record changes during scheduled runs
- Maintains data consistency across platforms
**Manual Sync**
- On-demand synchronization available in settings
- Useful for testing or immediate updates
- Processes all enabled objects
## Advanced Configuration
### Sync Direction Control
While most objects support bi-directional sync, you can control sync behavior
through field mappings:
- **Inbound Only**: Data flows from HubSpot to Quotient only
- **Outbound Only**: Data flows from Quotient to HubSpot only
- **Bi-directional**: Changes in either system update the other
### Conflict Resolution
When the same record is updated in both systems:
1. **Timestamp Comparison**: Most recent change wins
2. **Field-Level Resolution**: Different fields can have different winners
3. **Manual Override**: Some conflicts require manual resolution
4. **Audit Trail**: All sync conflicts are logged for review
### Performance Optimization
For large HubSpot accounts:
- **Selective Sync**: Only enable objects you actively use in Quotient
- **Field Filtering**: Limit synced fields to reduce processing time
- **Batch Size Tuning**: Automatic optimization based on account size
- **Rate Limiting**: Respects HubSpot API limits to prevent throttling
## Monitoring & Troubleshooting
### Sync Jobs Monitoring
Monitor your object synchronization through the **Jobs** tab in the HubSpot
settings:
- **Job History**: View all sync jobs that have been executed
- **Job Status**: See which jobs are completed, running, or failed
- **Progress Tracking**: Monitor sync progress with detailed progress bars
- **Execution Details**: View start times, duration, and record counts for each
job
- **Object Types**: See what type of data each job synchronized (Person,
Company, List, etc.)
### Common Issues
**Records Not Syncing**
- Verify the object type is enabled in sync preferences
- Check that records meet sync criteria (e.g., have email addresses for
contacts)
- Review field mapping configuration for required fields
**Slow Sync Performance**
- Large datasets may take time for initial sync
- Consider enabling only essential objects initially
- Check HubSpot API rate limits in the dashboard
**Data Inconsistencies**
- Review conflict resolution logs
- Verify field mappings are configured correctly
- Check for data type mismatches between systems
## Next Steps
Once you've configured object synchronization:
1. **[Set Up Field Mappings](/docs/integrations/hubspot/field-mappings)** - Customize how
data maps between systems
2. **[Configure Lists & Segments](/docs/integrations/hubspot/lists)** - Set up list
synchronization
3. **[Enable Email Sync](/docs/integrations/hubspot/email-sync)** - Sync email templates and
broadcasts
---
**HubSpot Help Resources:**
- [HubSpot Knowledge Base](https://knowledge.hubspot.com/) - Official help
articles
- [Managing Contacts in HubSpot](https://knowledge.hubspot.com/contacts) -
Contact management guides
- [Working with Companies](https://knowledge.hubspot.com/companies) - Company
record help
- [HubSpot Deals Guide](https://knowledge.hubspot.com/deals) - Deal management
resources
-- End of: /integrations/hubspot/objects
-- Start of: /integrations/hubspot/setup
---
title: Setup
description:
Connect your HubSpot account to Quotient and configure basic sync settings
order: 1
---
## Prerequisites
Before setting up the HubSpot integration, ensure you have:
- **HubSpot Account**: A HubSpot account with appropriate permissions
- **Admin Access**: Administrative access to your HubSpot portal to authorize
the integration
- **Quotient Business**: An active Quotient business account
### Required HubSpot Permissions
The integration requires the following HubSpot scopes:
- **CRM Objects**: Read/write access to contacts, companies, and deals
- **Lists**: Read/write access to contact lists
- **Custom Properties**: Access to create and manage custom properties
- **Marketing Email** (optional): For email sync functionality
## Connecting Your HubSpot Account
### Step 1: Navigate to Integrations
1. In your Quotient workspace, go to
**[Integrations](/s/most-recent-business/integrations)**
2. Find the **HubSpot** integration card
3. Click **Connect** to begin the setup process
### Step 2: Authorize with HubSpot
1. You'll be redirected to HubSpot's authorization page
2. **Select your HubSpot portal** if you have access to multiple accounts
3. **Review the permissions** that Quotient is requesting
4. Click **Grant access** to authorize the integration
Secure Connection
Quotient uses secure authentication to connect with HubSpot. You'll be
redirected to HubSpot's official login page to authorize the
connection, ensuring your credentials remain safe.
### Step 3: Review Permissions
After authorizing with HubSpot, you'll be redirected back to Quotient where you
can review the permissions that were granted:
### Step 4: Verify Connection
After authorization, you'll be redirected back to Quotient where you should see:
- ✅ **Connection Status**: "Connected" with your HubSpot portal name
- 📊 **Account Info**: Your HubSpot portal ID and connected user
- 🔧 **Available Features**: List of enabled capabilities based on your HubSpot
plan
## Initial Configuration
### Sync Preferences
By default, **all sync options are disabled** to give you full control over what
data is synchronized. You'll need to explicitly enable the objects you want to
sync.
#### Available Sync Options
Object Type
Description
Dependencies
Contacts → People
Sync HubSpot contacts as Quotient people
None
Companies
Sync HubSpot companies with Quotient
None
Deals
Import HubSpot deals (read-only)
None
Lists & Segments
Sync HubSpot lists and dynamic segments
Requires Contacts sync
#### Enabling Sync Options
1. In the HubSpot integration settings, toggle on the objects you want to sync
2. **Smart Dependencies**: Enabling Lists automatically enables Contacts sync
(required dependency)
3. **Confirmation**: Review your selections and click **Save Preferences**
### First Sync
After enabling sync preferences, Quotient will automatically trigger an initial
synchronization:
1. **ETL Process**: A background job will start importing your HubSpot data
2. **Progress Tracking**: Monitor sync progress in the integration dashboard
3. **Completion**: You'll receive a notification when the initial sync completes
Initial Sync Duration
The initial sync duration depends on the amount of data in your
HubSpot account. Large datasets may take several hours to complete.
You can continue using Quotient while the sync runs in the background.
## Sync Schedule & Updates
### Automated Sync Schedule
- **Daily Automatic Sync**: Complete synchronization runs every night at
midnight
- **Manual Sync**: On-demand synchronization available in the integration
settings
- **Background Processing**: Continuous monitoring and progress tracking
### How Updates Work
Quotient keeps your data synchronized through scheduled processes. Changes made
in HubSpot will appear in Quotient after the next sync cycle:
- New contacts, companies, and deals are imported during daily sync
- Modified information is updated during scheduled sync runs
- List membership changes are processed automatically
- You can trigger manual sync for immediate updates when needed
## Verification & Testing
### Verify Your Setup
After the initial sync completes, verify everything is working correctly:
1. **Check Data**: Review synced contacts, companies, and deals in Quotient
2. **Test Updates**: Make a small change in HubSpot and verify it appears in
Quotient
3. **Review Mappings**: Ensure field mappings are working as expected
### Common Setup Issues
**Connection Failed**
- Verify you have admin permissions in HubSpot
- Check that your HubSpot plan includes the required features
- Ensure popup blockers aren't preventing the OAuth flow
**No Data Syncing**
- Confirm sync preferences are enabled for the desired objects
- Check that the initial ETL job completed successfully
- Verify your HubSpot account contains data to sync
**Missing Fields**
- Review field mappings in the integration settings
- Ensure custom properties exist in both systems
- Check data type compatibility between systems
## Next Steps
Once your HubSpot integration is connected and syncing:
1. **[Configure Object Sync](/docs/integrations/hubspot/objects)** - Fine-tune which objects
are synchronized
2. **[Set Up Field Mappings](/docs/integrations/hubspot/field-mappings)** - Customize how
data maps between systems
3. **[Enable Email Sync](/docs/integrations/hubspot/email-sync)** - Sync email templates and
broadcasts
4. **[Configure Lists](/docs/integrations/hubspot/lists)** - Set up list and segment
synchronization
---
**Need Help?** If you encounter issues during setup, check our
[troubleshooting guide](/docs/integrations/hubspot/troubleshooting) or contact support.
-- End of: /integrations/hubspot/setup
-- Start of: /integrations/hubspot/troubleshooting
---
title: Troubleshooting
description: Resolve common issues with your HubSpot integration
order: 6
---
## Common Issues & Solutions
### Connection & Authentication Issues
#### Integration Connection Failed
**Symptoms:**
- Unable to connect to HubSpot during setup
- "Authorization failed" error messages
- Redirect loops during OAuth flow
**Solutions:**
1. **Check HubSpot Permissions**
- Ensure you have admin access to the HubSpot portal
- Verify your user account has integration management permissions
- Confirm the HubSpot plan includes required features
2. **Browser & Network Issues**
- Disable popup blockers for Quotient and HubSpot domains
- Clear browser cache and cookies
- Try the connection process in an incognito/private window
- Check for corporate firewall restrictions
3. **Multiple HubSpot Accounts**
- Ensure you're logged into the correct HubSpot portal
- Log out of other HubSpot accounts before connecting
- Use a dedicated browser session for the integration setup
#### Token Refresh Failures
**Symptoms:**
- "Invalid token" errors in sync logs
- Intermittent sync failures
- Authentication errors after initial setup
**Solutions:**
1. **Reconnect Integration**
- Go to **[HubSpot integration settings](/s/most-recent-business/integrations/hubspot)**
- Click "Reconnect" to refresh OAuth tokens
- Complete the authorization flow again
2. **Check HubSpot App Status**
- Verify the Quotient app is still installed in HubSpot
- Check app permissions haven't been revoked
- Review HubSpot's connected apps settings
### Data Sync Issues
#### Records Not Syncing
**Symptoms:**
- New HubSpot contacts don't appear in Quotient
- Changes in one system don't reflect in the other
- Sync dashboard shows no recent activity
**Troubleshooting Steps:**
1. **Verify Sync Preferences**
```
✓ Check that object sync is enabled for the affected type
✓ Confirm sync direction allows the desired data flow
✓ Verify dependencies (e.g., Lists requires Contacts)
```
2. **Check Data Requirements**
- **Contacts**: Must have valid email addresses
- **Companies**: Must have a name
- **Lists**: Must contain contacts with email addresses
3. **Review Sync Logs**
- Check the integration dashboard for error messages
- Look for rate limiting or API quota issues
- Verify network connectivity during sync windows
4. **Manual Sync Test**
- Trigger a manual sync for the affected object type
- Monitor progress in real-time
- Check if specific records are causing failures
#### Field Mapping Issues
**Symptoms:**
- Data appears in one system but not the other
- Field values are incorrect or truncated
- Custom properties not syncing
**Solutions:**
1. **Verify Field Mappings**
- Check that mappings exist for the affected fields
- Ensure data types are compatible between systems
- Verify sync direction allows the desired data flow
2. **Data Type Compatibility**
```
HubSpot Text → Quotient STRING ✓
HubSpot Number → Quotient STRING ✗ (use NUMBER)
HubSpot Date → Quotient DATETIME ✗ (use DATE)
```
3. **Custom Property Setup**
- Ensure custom properties exist in both systems
- Check property permissions and visibility
- Verify property names match exactly in mappings
#### Duplicate Records
**Symptoms:**
- Multiple records for the same person/company
- Sync conflicts between similar records
- Data inconsistencies across systems
**Prevention & Resolution:**
1. **Email-Based Deduplication**
- Ensure all contacts have unique, valid email addresses
- Clean up duplicate emails in HubSpot before syncing
- Use HubSpot's built-in deduplication tools
2. **Company Matching**
- Verify company names are consistent between systems
- Use domain-based matching where possible
- Manually merge duplicates in both systems
3. **Sync Conflict Resolution**
- Review conflict resolution logs in the integration dashboard
- Understand timestamp-based conflict resolution
- Manually resolve conflicts that require business logic
### List & Segment Sync Issues
#### Lists Not Creating in Quotient
**Symptoms:**
- HubSpot lists don't appear in Quotient
- List sync shows errors or warnings
- Empty lists in Quotient despite HubSpot membership
**Solutions:**
1. **Check List Requirements**
- Verify the list contains contacts with email addresses
- Ensure list members are also synced as contacts
- Check that list sync is enabled in preferences
2. **List Type Compatibility**
- **Dynamic lists** → Quotient segments (inbound only)
- **Static lists** → Quotient lists (bi-directional)
- Verify the list type matches expected behavior
3. **Member Sync Dependencies**
- Ensure contact sync is enabled and working
- Check that list members exist in Quotient
- Review member email address validity
#### Bi-directional List Sync Conflicts
**Symptoms:**
- Members added in one system don't appear in the other
- Sync conflicts for list membership
- Inconsistent member counts between systems
**Solutions:**
1. **Conflict Resolution Strategy**
- Understand that most recent change wins
- Avoid simultaneous changes in both systems
- Use manual sync to resolve immediate conflicts
2. **Member Email Matching**
- Ensure members have matching email addresses
- Check for email format differences (case, spacing)
- Verify email addresses are not suppressed
### Email Sync Issues
#### Template Creation Failed
**Symptoms:**
- "Template setup failed" error messages
- Missing `quotient-base.html` template in HubSpot
- Email sync toggle won't enable
**Solutions:**
1. **HubSpot Plan Verification**
- Confirm Marketing Hub Starter or higher plan
- Verify marketing email API access is included
- Check Design Manager permissions
2. **Template Setup Process**
- Try the automated template setup again
- Manually verify template creation in HubSpot Design Manager
- Check for template naming conflicts
3. **Permission Issues**
- Ensure integration has content and marketing-email scopes
- Verify user permissions for Design Manager access
- Check HubSpot app installation status
#### Email Content Not Displaying
**Symptoms:**
- Blank emails in HubSpot
- Content not injecting into template
- Formatting issues in synced emails
**Solutions:**
1. **Template Validation**
- Verify `quotient-base.html` contains required modules
- Check for template modifications that break injection
- Test template with sample content
2. **Content Format Issues**
- Review HTML compatibility with HubSpot
- Check for unsupported CSS or JavaScript
- Verify image URLs are accessible
### Performance & Rate Limiting
#### Slow Sync Performance
**Symptoms:**
- Sync operations take hours to complete
- Timeouts during large data imports
- Delayed sync completion
**Optimization Strategies:**
1. **Selective Sync**
- Only enable objects you actively use in Quotient
- Disable unused custom property mappings
- Focus on essential data for initial sync
2. **Batch Size Optimization**
- Allow automatic batch size adjustment
- Monitor sync performance metrics
- Consider breaking large datasets into phases
3. **Timing Optimization**
- Schedule manual syncs during off-peak hours
- Avoid simultaneous large operations
- Rely on daily automatic sync for regular updates
#### API Rate Limiting
**Symptoms:**
- "Rate limit exceeded" errors in sync logs
- Sync operations failing intermittently
- Delayed sync completion
**Solutions:**
1. **Rate Limit Management**
- Monitor API usage in integration dashboard
- Spread sync operations across time
- Use HubSpot's rate limit headers for optimization
2. **Sync Frequency Adjustment**
- Reduce manual sync frequency
- Rely on scheduled daily sync for bulk updates
- Allow automatic sync processes to handle regular updates
## Best Practices
### Data Management
#### Maintain Data Quality
**Before Syncing:**
- Clean up duplicate records in HubSpot
- Standardize data formats (phone numbers, addresses)
- Validate email addresses and remove invalid ones
- Ensure required fields are populated
**Ongoing Maintenance:**
- Regularly review sync logs for errors
- Monitor data consistency between systems
- Set up alerts for sync failures
- Perform periodic data audits
#### Field Mapping Strategy
**Default Mappings:**
- Start with Quotient's default field mappings
- Only customize mappings when necessary
- Document custom mapping decisions
- Test mappings with sample data before full deployment
**Custom Properties:**
- Use consistent naming conventions between systems
- Choose appropriate data types for each field
- Avoid overly complex custom property structures
- Plan for future scalability
### Sync Configuration
#### Object Sync Strategy
**Phased Approach:**
1. **Phase 1**: Enable Contacts sync only
2. **Phase 2**: Add Companies after contact sync stabilizes
3. **Phase 3**: Enable Lists and Segments
4. **Phase 4**: Add Deals and Email sync
**Selective Enablement:**
- Only sync objects you'll actively use in Quotient
- Consider data volume and sync performance
- Plan for future growth and additional objects
#### Performance Optimization
**Large Datasets:**
- Expect longer initial sync times for large HubSpot accounts
- Monitor sync progress and performance metrics
- Consider data archiving for very old records
- Use HubSpot's data export tools for historical analysis
**Sync Strategy:**
- Rely on daily automatic sync for comprehensive updates
- Use manual sync only when immediate updates are needed
- Schedule intensive operations during off-peak hours
- Allow background processes to handle regular synchronization
### Monitoring & Maintenance
#### Proactive Monitoring
**Daily Checks:**
- Review sync status dashboard
- Monitor error rates and performance metrics
- Check for failed sync operations
- Verify sync scheduling and automation
**Weekly Reviews:**
- Analyze sync performance trends
- Review data consistency reports
- Check for new error patterns
- Update field mappings as needed
#### Maintenance Schedule
**Monthly Tasks:**
- Review and clean up sync logs
- Update custom field mappings
- Audit data quality across systems
- Test disaster recovery procedures
**Quarterly Reviews:**
- Assess integration performance and ROI
- Review and update sync preferences
- Plan for new feature adoption
- Conduct security and compliance audits
---
**Need Help?** Check the [HubSpot Knowledge Base](https://knowledge.hubspot.com/) for additional HubSpot-specific guidance, or contact support if issues persist.
-- End of: /integrations/hubspot/troubleshooting
-- Start of: /integrations/wordpress/index
---
title: WordPress
description: Connect your WordPress site to Quotient to automatically sync your blog posts and streamline your content marketing workflow
order: 3
---
Publishing a great blog post shouldn't require copying and pasting content between platforms or wrestling with WordPress's editor. If you're managing a blog, you want to focus on writing compelling content and optimizing for SEO, not dealing with the technical details of getting words onto your website.
That's why Quotient's WordPress integration lets you write your blog posts in Quotient and publish them directly to your WordPress site with one click. Make edits in Quotient, and your WordPress post updates automatically. Add a featured image in Quotient, and it uploads to WordPress without you lifting a finger. The whole workflow becomes seamless, letting you focus on what matters: creating great content.
## Core Concepts
When you connect WordPress to Quotient, here's how the pieces fit together:
**WordPress Site Connection**
Your WordPress site connects to Quotient using Application Passwords, a secure authentication method built into WordPress. Unlike traditional integrations that require OAuth, WordPress uses simple username and password authentication designed specifically for apps like Quotient. This means no redirect URLs, no expiring tokens, just straightforward, reliable access.
**Field Mappings**
Field mappings control which information from your Quotient blog goes where on your WordPress site. For example, you might map your Quotient blog title to the WordPress post title, and your Quotient tags to WordPress tags. Quotient sets up sensible defaults automatically (title to title, content to content, etc.), but you can customize these if your WordPress setup uses custom fields or has special requirements.
**Sync Status**
Once you publish a blog to WordPress, Quotient remembers the connection. The button changes from "Publish to WordPress" to "Update WordPress" so you can keep making changes in Quotient and push updates to your live WordPress post. Quotient tracks which Quotient blog corresponds to which WordPress post ID, so updates always go to the right place.
## Common Workflows
Here's how most teams use the WordPress integration day-to-day:
1. **Write your blog in Quotient.** Use Quotient's collaborative writing features, AI assistance, and content planning tools to craft your post.
2. **Add your featured image and tags.** Upload your hero image and add relevant tags for SEO.
3. **Click "Publish to WordPress."** Quotient sends your content to WordPress as a draft post. You can review it in WordPress and manually publish when ready.
4. **Make edits in Quotient as needed.** If you spot a typo or want to update the content, edit it in Quotient and click "Update WordPress" to sync your changes.
This workflow works whether you're publishing one blog post a week or managing dozens of posts across multiple WordPress sites. The integration handles the busy work of moving content between platforms so you can focus on writing and strategy.
## Getting Started
Ready to connect WordPress? The setup takes about 5 minutes:
1. **[Connect Your WordPress Site →](/docs/integrations/wordpress/setup)** - Create an Application Password and [link your WordPress site to Quotient](/s/most-recent-business/integrations/wordpress)
2. **[Publish Your First Blog →](/docs/integrations/wordpress/syncing)** - Send a blog post from Quotient to WordPress
If you run into issues, check out the **[Troubleshooting Guide →](/docs/integrations/wordpress/troubleshooting)** for solutions to common connection problems.
-- End of: /integrations/wordpress/index
-- Start of: /integrations/wordpress/setup
---
title: Setup
description: Connect your WordPress site to Quotient in 5 minutes
order: 851
---
Connecting your WordPress site to Quotient takes about 5 minutes. You'll need admin access to your WordPress dashboard and a self-hosted WordPress site (not WordPress.com). If you're not sure whether your site is self-hosted, don't worry - we'll help you figure that out as we go.
The connection process involves three main steps: updating your WordPress permalink settings, creating an Application Password for Quotient to use, and entering your credentials in Quotient. Let's walk through each one.
## Step 1: Update Your WordPress Permalink Settings
WordPress needs to have "pretty URLs" enabled for Quotient to work properly. By default, some WordPress installations use "plain" permalinks (URLs that look like `?p=123`), but Quotient requires the more readable "post name" format (URLs that look like `/my-blog-post`).
Log into your WordPress admin dashboard and navigate to **Settings → Permalinks**. You'll see several options for how WordPress structures your URLs. Select **"Post name"** if it's not already selected, then click **"Save Changes"** at the bottom of the page.

Don't worry - changing this setting won't break your existing links. WordPress automatically redirects old URLs to new ones, so any links to your site will continue to work.
## Step 2: Create an Application Password
Application Passwords are a secure way for apps like Quotient to access your WordPress site without using your main login password. Think of it like creating a key specifically for Quotient - you can revoke it anytime without changing your main password.
In your WordPress admin, go to **Users → Your Profile** (or **Users → Profile** depending on your WordPress version). Scroll down until you see the "Application Passwords" section. Type **"Quotient"** in the name field so you'll remember what this password is for later, then click **"Add New Application Password"**.

WordPress will generate a password that looks something like `abcd efgh ijkl mnop qrst uvwx`. Copy this password immediately and save it somewhere safe - you won't be able to see it again after you close this page.
Important
Save this password somewhere safe - you won't be able to see it again! If
you lose it, you'll need to create a new one.
## Step 3: Connect to Quotient
Now that you have your Application Password, you can connect your WordPress site to Quotient. In Quotient, navigate to **[Settings → Integrations](/s/most-recent-business/integrations)** and find the WordPress card. Click **"Connect"** to open the connection dialog.
You'll need to enter three pieces of information:
- **Website URL**: Your WordPress site's address, like `https://yoursite.com`. Make sure to include the `https://` and don't add a trailing slash at the end.
- **Username**: Your WordPress username - this is the same username you use to log into your WordPress admin dashboard.
- **Password**: The Application Password you just created in Step 2.
After you enter your credentials, click **"Connect WordPress"**. Quotient will test the connection to make sure everything is working properly. This usually takes just a few seconds.
## Understanding Field Mappings
Once you're connected, Quotient automatically configures field mappings that work for most WordPress sites. Field mappings determine which information from your Quotient blog goes into which fields on your WordPress site. For example, your Quotient blog title maps to the WordPress post title, your blog content maps to the WordPress post content, and so on.
The default mappings cover the essentials:
- **Title** → WordPress post title
- **Content** → WordPress post content
- **Summary** → WordPress excerpt (used for SEO and previews)
- **Tags** → WordPress tags
- **Featured Image** → WordPress featured image
Most users never need to change these mappings - they work great out of the box. However, if your WordPress site uses custom fields or you want to map additional information, you can customize the mappings in **[Settings → Integrations → WordPress](/s/most-recent-business/integrations/wordpress)** under the "Field Mappings" tab.
## You're All Set
That's it! Once your WordPress site is connected, you'll see a new "Publish to WordPress" button when you're viewing any blog post in Quotient. This button lets you send your finished content directly to WordPress without any copy-pasting or manual work.
Ready to publish your first blog? Check out the [Publishing Guide](/docs/integrations/wordpress/syncing) to learn how to send your content to WordPress.
## Troubleshooting Common Setup Issues
If you encounter problems during setup, here are the most common issues and their solutions:
**"Connection failed" error** - This usually means your permalinks aren't configured correctly, or there's an issue with your credentials. Double-check that you selected "Post name" in your permalink settings, that you're using your WordPress username (not "Quotient" or any other application name), and that you copied the Application Password exactly as shown.
**"Permission denied" error** - Your WordPress user account needs to be an Administrator or Editor to publish posts. If you're seeing this error, check your WordPress user role in **Users → All Users** and make sure you have the right permissions. If you're not an admin on the site, ask whoever manages your WordPress to grant you Editor or Administrator access.
If you're still having trouble, the [Troubleshooting Guide](/docs/integrations/wordpress/troubleshooting) has detailed solutions for these and other issues.
-- End of: /integrations/wordpress/setup
-- Start of: /integrations/wordpress/syncing
---
title: Publishing
description: Learn how to publish your Quotient blogs to WordPress with one click
order: 854
---
Once your WordPress site is connected to Quotient, publishing your finished blog posts is straightforward. The integration handles all the technical details of uploading content, images, and metadata to WordPress, so you can focus on creating great content.
## Publishing Your First Blog
When you're ready to publish a blog post to WordPress, open the blog in Quotient and look for the "Publish to WordPress" button near the top of the page. Before you click it, take a moment to make sure your blog is ready. Add a featured image if you haven't already - featured images make your blog posts more engaging and help with social media sharing. Include relevant tags for SEO, and make sure you've written a good summary that will appear in search results and previews.

When you click "Publish to WordPress," Quotient sends your content to WordPress and creates a new post. The publishing process usually takes 10-30 seconds depending on how many images need to be uploaded. Your blog post will be created as a draft in WordPress, giving you a chance to review how it looks on your site before making it live to your audience.
## What Gets Published to WordPress
When Quotient publishes a blog to WordPress, it sends all the essential elements of your post based on your field mappings. Your blog title becomes the WordPress post title, your content is converted to properly formatted HTML, and any images in your post are automatically uploaded to your WordPress media library. If you've added a featured image in Quotient, it gets uploaded and set as the WordPress featured image. Your tags map to WordPress tags, and your blog summary becomes the WordPress excerpt, which is used for SEO and post previews.
The field mappings you configured during setup control exactly what information goes where. Most users stick with the defaults, but if you've customized your mappings to include custom fields or specific WordPress metadata, those will be included as well.
## Updating Published Blogs
One of the most useful features of the WordPress integration is the ability to update your published posts. If you spot a typo, want to add more content, or need to update information in a blog post that's already on WordPress, you can make your changes in Quotient and sync them back to WordPress.
After you've published a blog once, the "Publish to WordPress" button changes to "Update WordPress." When you click it, Quotient finds the existing WordPress post and updates it with your changes. This is much easier than manually copying edits from Quotient into WordPress's editor.
It's worth noting that if you make edits directly in WordPress after publishing from Quotient, those changes will be overwritten the next time you update from Quotient. For this reason, we recommend treating Quotient as the source of truth and making all your edits there. If you need to make WordPress-specific changes that Quotient doesn't support, make those changes in WordPress after you're done updating from Quotient.
## Publishing Best Practices
Before you publish, take a few minutes to double-check your content. Proofread your text carefully - while you can update the post later, it's better to get it right the first time. Make sure your featured image looks good and is appropriately sized for your WordPress theme. Check that your tags are relevant and will help readers find your content. And review your summary to ensure it accurately represents your post and includes important keywords for SEO.
After publishing, visit your WordPress site to see how the post looks in your theme. Sometimes formatting that looks great in Quotient needs minor adjustments to work perfectly with your specific WordPress design. If everything looks good, you can manually publish the post from draft to live in WordPress. Then share your new post on social media or in your newsletter to get it in front of your audience.
## Common Questions
**How long does publishing take?**
Publishing typically takes 10-30 seconds. If your blog has several large images, it might take a bit longer as Quotient uploads each image to your WordPress media library. You'll see a progress indicator while the sync is happening.
**What status do posts get published as?**
All posts are published to WordPress as drafts, not as live published posts. This gives you a chance to review how the post looks on your site and make any final adjustments before making it live to your audience. When you're ready, you can manually publish the post in your WordPress admin dashboard.
**Can I edit the blog in WordPress after publishing?**
Yes, you can edit the post directly in WordPress. However, if you later update the post from Quotient, your WordPress changes will be overwritten. It's best to treat Quotient as your source of truth and make all edits there. Think of WordPress as the publishing platform and Quotient as your content management and editing platform.
**What happens if publishing fails?**
If publishing fails, Quotient will show you an error message explaining what went wrong. Common issues include connection problems, permission errors, or issues with specific images. Check the [Troubleshooting Guide](/docs/integrations/wordpress/troubleshooting) for solutions to specific error messages. You can always try publishing again once you've resolved the issue.
**Can I publish the same blog to multiple WordPress sites?**
Not directly from a single blog post. If you need to publish the same content to multiple WordPress sites, you'll need to create separate blog posts in Quotient for each site. However, you can use the duplicate feature to copy a blog and then publish each copy to a different WordPress site.
## Related Topics
-- End of: /integrations/wordpress/syncing
-- Start of: /integrations/wordpress/troubleshooting
---
title: Troubleshooting
description: Fix common WordPress connection and publishing issues
order: 852
---
If you're having trouble connecting your WordPress site to Quotient or publishing blog posts, you're not alone. Most WordPress connection issues come down to a few common problems that are easy to fix once you know what to look for. This guide walks through the most frequent issues and their solutions.
## Connection Problems
### "Connection failed" Error
The most common cause of connection failures is that your WordPress site has permalinks set to "Plain" rather than "Post name." WordPress needs to use pretty URLs for Quotient to communicate with it properly. To fix this, log into your WordPress admin and go to **Settings → Permalinks**. Select **"Post name"** instead of "Plain," then click **"Save Changes"** at the bottom of the page. After making this change, return to Quotient and try connecting again.
Another common cause is entering your site URL incorrectly. Make sure you're including the `https://` at the beginning and that you're not adding a trailing slash at the end. The URL should look like `https://yoursite.com`, not `https://yoursite.com/` or `yoursite.com`.
### "Permission denied" Error
If you're seeing a "Permission denied" error, it means the WordPress user account you're trying to connect with doesn't have sufficient permissions to create and edit posts. WordPress requires that the user be either an Administrator or an Editor to use Quotient.
First, double-check that you're using your actual WordPress username - the one you log in with - not the word "Quotient" or any other application name. If you're certain you're using the right username, you'll need to check your user role in WordPress. Log into your WordPress admin and go to **Users → All Users**. Find your account in the list and check what role you have. If you're not an Administrator or Editor, you'll need to ask whoever manages your WordPress site to upgrade your permissions.
### "Invalid username or password" Error
This error means that either your username or your Application Password is incorrect. Start by verifying that you're using your WordPress username correctly - this is the username you use to log into your WordPress dashboard, not your email address or display name.
If your username is correct, the issue is likely with the Application Password. Application Passwords are long strings that look like `abcd efgh ijkl mnop qrst uvwx`, and it's easy to accidentally miss a character when copying them. The simplest solution is to create a fresh Application Password. Go to **Users → Your Profile** in WordPress, scroll down to the "Application Passwords" section, create a new one called "Quotient," and copy the new password carefully. Then try connecting again in Quotient with the new password.
## Publishing Problems
### Blog Doesn't Appear on WordPress
If you've successfully published a blog from Quotient but can't find it on your WordPress site, don't panic. The most likely explanation is that the post was created as a draft, which is the expected behavior. Log into your WordPress admin and go to **Posts → All Posts**. Look for your post in the list - it should be there with a "Draft" status. You can then review the post and manually publish it when you're ready.
Sometimes it takes a few moments for the post to appear in WordPress's admin interface, especially if your WordPress site is on a slower hosting plan. Give it a minute and refresh the page. If the post still doesn't appear after a few minutes, check the Quotient interface to see if there was an error message during publishing.
In rare cases, the post might be published but not visible on your site's homepage because of your WordPress theme's settings or because it was assigned to a category that's not displayed on the front page. Check your WordPress theme settings and make sure the post is in a category that appears on your site.
### Images Not Showing Up
If your blog text appears on WordPress but the images are missing, this usually means that either the images failed to upload or your WordPress installation doesn't allow the image file type. JPG and PNG images work with virtually all WordPress sites, but some hosting providers restrict certain file types or have file size limits.
Try using JPG or PNG format for your images, and make sure each image is under 5MB. Very large images can fail to upload, especially on hosting plans with strict resource limits. If you're working with high-resolution images, compress them before adding them to Quotient. There are many free online tools for image compression that can reduce file sizes without noticeably affecting quality.
If specific images continue to fail, try uploading them directly to WordPress's media library to see if you get a more specific error message about what's preventing the upload.
### Publishing Is Very Slow
Publishing can take anywhere from a few seconds to a minute or more, depending on your blog and your WordPress hosting. This is normal, especially if your blog contains multiple large images. Each image needs to be uploaded to your WordPress media library, which takes time.
If publishing consistently takes more than a minute, consider compressing your images before adding them to Quotient. Smaller image files upload much faster. You might also want to look at your WordPress hosting plan - slower shared hosting plans can struggle with handling uploads, while managed WordPress hosting from providers like WP Engine or Kinsta typically handles uploads much more quickly.
## Understanding WordPress.com vs. Self-Hosted WordPress
One source of confusion that often leads to connection errors is the difference between WordPress.com and self-hosted WordPress. These are two different things, and Quotient only works with self-hosted WordPress.
**WordPress.com** is a hosting service run by Automattic where you can create a WordPress site without managing your own hosting. If your site address looks like `yoursite.wordpress.com`, you're using WordPress.com. These sites have limited access to the WordPress REST API unless you pay for a Business plan, which means Quotient can't connect to them in most cases.
**Self-hosted WordPress** refers to WordPress software that you've installed on your own web hosting. These sites typically have custom domains like `yoursite.com` and give you full control over plugins, themes, and settings. Self-hosted WordPress works perfectly with Quotient. Common hosting providers for self-hosted WordPress include WP Engine, Bluehost, SiteGround, Kinsta, and many others.
If you're not sure which type you have, check your site's URL. If it ends in `.wordpress.com` and you can't install plugins freely, you're likely on WordPress.com and will need to either upgrade to a Business plan or move to self-hosted WordPress to use Quotient.
## Getting Additional Help
If you've tried the solutions above and are still having problems, here are some steps to take before reaching out for support.
First, try disconnecting and reconnecting your WordPress site in Quotient. Sometimes connection issues resolve themselves when you establish a fresh connection. Go to **Settings → Integrations → WordPress** in Quotient, disconnect your site, and then go through the connection process again with a new Application Password.
Test whether the problem is specific to a particular blog or affects all your content. Try publishing a very simple blog post with just text and no images. If that works but a complex post with many images doesn't, you've narrowed down the problem to something specific about that content.
Finally, verify that you can create posts normally in your WordPress admin. If you can't create or edit posts when logged into WordPress directly, the issue is with your WordPress installation rather than with Quotient. You'll need to resolve the WordPress issue first before the integration can work.
If you need to contact support, include these details in your message: your WordPress site URL, the exact error message you're seeing in Quotient, whether you're using WordPress.com or self-hosted WordPress, and what hosting company you use if you know. This information helps support diagnose the issue much more quickly.
## Quick Troubleshooting Checklist
Before you try anything else, run through this quick checklist to make sure all the basics are covered:
- WordPress permalinks are set to "Post name" (not "Plain")
- You're using your actual WordPress username, not "Quotient" or any other name
- Your WordPress user account is an Administrator or Editor
- You copied the Application Password exactly as shown, including all spaces
- Your WordPress site is self-hosted, not WordPress.com
- You can create and edit posts normally in your WordPress admin
- Your site URL in Quotient includes `https://` and doesn't have a trailing slash
If you can check all of these boxes and are still having issues, the problem is likely something more specific that will require deeper troubleshooting or support assistance.
-- End of: /integrations/wordpress/troubleshooting
-- Start of: /mcp/connecting-tools/github-private-repos
---
title: Accessing Private GitHub Repositories
description:
Use a personal access token to give Quotient read access to private repos via
the GitHub MCP server
order: 1
---
The GitHub MCP connection in the marketplace uses OAuth to connect through
Quotient's GitHub App. This works well for public repositories, but GitHub's
hosted MCP server does not surface private repositories or organization
repositories through this OAuth flow. Since the most common reason to connect
GitHub is to work with private repos — drafting changelogs from commits,
summarizing PRs, writing release notes — this is a meaningful limitation.
The workaround is straightforward: create a GitHub personal access token (PAT)
and connect the GitHub MCP server as a custom server using that token. Quotient
will authenticate as you through the PAT and will be able to see any repo the
token has access to.
## Step 1: Create a Personal Access Token
GitHub offers two types of personal access tokens: **fine-grained tokens**
(recommended) and **classic tokens**. Both work with this setup. Fine-grained
tokens are more precise and let you restrict access to specific repositories;
classic tokens are simpler to configure.
Go to
[GitHub > Settings > Developer settings > Personal access tokens](https://github.com/settings/tokens)
to create one.
### A note on read-only access
A personal access token essentially lets Quotient authenticate to GitHub on your
behalf, with whatever permissions the token carries. **We strongly recommend
keeping your token read-only.** Quotient's primary use case for GitHub is
reading commits, pull requests, and diffs to generate content — it does not need
write access for this.
We do not document write-scope configurations here. If you have a specific use
case that requires write access (for example, having Quotient open PRs or create
issues), reach out to us and we can help you configure appropriate scopes.
### Fine-grained token (recommended)
Fine-grained tokens let you limit access to specific repositories and grant only
the permissions you need.
When creating the token, configure the following:
- **Resource owner:** Your personal account, or the GitHub organization that
owns the repositories you want Quotient to access. If you select an
organization, the org may need to approve the token before it becomes active.
- **Repository access:** Select **Only select repositories** and choose the
repos you want Quotient to be able to read, or select **All repositories** if
you want broad access across your account or org.
- **Permissions:** Under Repository permissions, set the following to
**Read-only**:
- **Contents** — required to read files, commits, and diffs
- **Metadata** — required for basic repo info (always read-only, enabled
automatically)
- **Pull requests** — required to read PR descriptions and diffs
### Classic token
Classic tokens are scoped by category rather than individual permission. When
creating the token, select:
- **`repo`** — grants full access to repositories, but within the `repo` scope,
you are not able to request read-only on its own. This is a known limitation
of classic tokens. If fine-grained tokens are an option for you, they are
preferable because they allow true read-only access.
If you are connecting Quotient to an organization's repositories, you may also
need:
- **`read:org`** — allows Quotient to read organization membership and
repository lists within the org
Do not select any write or admin scopes. Leave all other checkboxes unchecked.
## Step 2: Connect as a Custom MCP Server
Once you have your token, go to
**[Settings > MCP Servers](/s/most-recent-business/settings/mcp-servers)** and
click **Custom Server** at the bottom of the marketplace list.
Configure the server with the following:
- **URL:** `https://api.githubcopilot.com/mcp/`
- **Authentication:** API Key
- **Token:** Paste your personal access token
Save the connection. Quotient will immediately be able to use the GitHub MCP
tools with the permissions carried by your token.
## What Happens Next
Once connected, Quotient can read any repository that your token has access to.
You can ask it to summarize recent commits, compare branches, draft a changelog
from merged PRs, or pull context from a specific file — all without leaving
Quotient.
If you need to rotate or revoke the token at any point, generate a new one in
GitHub, then update the custom server in Quotient's settings with the new value.
-- End of: /mcp/connecting-tools/github-private-repos
-- Start of: /mcp/connecting-tools/index
---
title: Connect Tools to Quotient
description: Give Quotient access to outside tools like GitHub, Notion, and Ahrefs by connecting them as MCP servers.
order: 1
---
Want to use Quotient from ChatGPT, Claude, or another AI app? See
[Use Quotient in Other AI Apps](/docs/mcp/from-other-apps).
MCP (Model Context Protocol) is an open standard that extends what Quotient can
do by giving it access to other systems. When you connect an
MCP server to Quotient, you're giving it a set of **tools** it can call during
conversations — for example, the ability to look up GitHub pull requests, pull
SEO data from Ahrefs, or read documents from Notion.
You can think of it like a universal adapter: once a tool supports MCP, any AI
application (including Quotient) can plug into it. Many applications now
offer MCP servers, and connecting one to Quotient takes just a few clicks.
**A note on how this differs from Quotient's built-in integrations.** MCP
connections give Quotient specific tools it can use during conversations.
Built-in integrations like your CRM or Slack are more deeply embedded into the
platform. Your CRM integration doesn't just give Quotient a tool to call; it
continuously syncs your customer data so it can power audience segments,
personalization, and reporting. The Slack integration lets you talk to Quotient
without leaving your workspace. MCP connections, by contrast, extend what
Quotient can do in a conversation, and nothing more.
## What You Can Do with MCP
Here are some of the most common ways Quotient customers use MCP connections
today.
**Bridge the gap between product and marketing.** Connect Linear, GitHub, or
monday.com so Quotient can read issues, boards, pull requests, and commit
history. This is useful for product marketing: instead of waiting for
engineering to write up release notes or explain what shipped, you can ask
Quotient to look at the last sprint's PRs and draft a changelog, blog post, or
launch email. This reduces back-and-forth between teams.
**Inform campaigns with SEO data.** Connect Ahrefs, Semrush, or DataForSEO
and ask Quotient to pull keyword research, competitor analysis, or backlink
data while you're planning a campaign. Instead of switching between tabs and
copy-pasting data, you can have a conversation: "What keywords are we ranking
for in the enterprise analytics space?" and Quotient will look it up and
factor the results into its recommendations.
**Give Quotient access to your company knowledge.** Many teams keep important
context in Notion — product briefs, competitive intel, messaging frameworks,
onboarding docs. Connecting Notion lets Quotient read those documents directly,
which means it can draw on that context when writing content or making strategic
recommendations. You can even ask Quotient to read specific Notion pages and
save the key points as memories for future conversations.
## Connecting an MCP Server
Navigate to
**[Settings > MCP Servers](/s/most-recent-business/settings/mcp-servers)** to
see the list of available connections. The marketplace shows all supported
providers — just click one to begin the connection process.
Most providers use OAuth. You'll be redirected to authorize Quotient's access
and then sent back to the settings page once the connection is established.
**Semrush** asks you to paste an API key instead of going through OAuth. Create
a Version 4 key in Semrush under **My Profile → API Keys**, then paste it when
you click Connect.
Once connected, you don't need to do anything special to use it. Quotient
automatically discovers the tools that each connected server provides and will
use them when relevant. If you ask Quotient something that one of your connected
tools can help with, it will reach for it naturally.
You can disconnect a server at any time from the same settings page using the
menu on each connected provider. If an OAuth connection stops working (for
example, if you revoked access on the provider's side), you can use the
**Reconnect** option in the same menu to re-authorize without removing and
re-adding the server. API key providers don't have a reconnect flow — disconnect
and connect again with a new key if you need to rotate it.
## Custom MCP Servers
The marketplace covers the most popular tools, but MCP is an open standard —
many applications and services now offer MCP servers. If you want to connect
something that isn't in the marketplace, you can add it as a custom server.
To add a custom server, click **Custom Server** at the bottom of the marketplace
list. You'll need to provide the server's URL and choose an authentication
method.
**OAuth** is the most common authentication method for MCP servers. When you
choose OAuth, Quotient will redirect you to the service's login page to
authorize access — the same flow you'd use when connecting a marketplace
provider. Most major SaaS tools that offer MCP servers support OAuth.
**API Key** authentication is the alternative. Some MCP servers require you to
generate an API key or token in their settings and provide it to Quotient
directly. If you're connecting a server that uses API keys, you'll typically
find instructions for generating one in that service's documentation, usually
under a section called "API Keys," "Tokens," or "Developer Settings."
If you're not sure which authentication method to use, check the documentation
for the MCP server you're trying to connect — it will tell you what's supported.
OAuth is generally the simpler option when available, since you don't need to
manage any keys yourself.
-- End of: /mcp/connecting-tools/index
-- Start of: /mcp/from-other-apps/index
---
title: Use Quotient in Other AI Apps
description: Connect Quotient to AI apps like ChatGPT, Claude, Cursor, and Codex so they can do work in your Quotient account on your behalf.
order: 2
---
[MCP (Model Context Protocol)](https://modelcontextprotocol.io/) is an open
standard that lets AI apps securely connect to other software.
Connect ChatGPT, Claude, and other AI apps to Quotient so they can work in your
account without leaving the app you're using. To give Quotient access to tools
like GitHub or Notion, see
[Connect Tools to Quotient](/docs/mcp/connecting-tools).
Quotient's MCP server also works with Claude Code, Codex, and Cursor through a
secure connection.
Use the buttons below to add Quotient to ChatGPT or Claude, then sign in when
prompted. For other apps, follow the
[setup instructions](/docs/mcp/from-other-apps/setup-instructions).
## Common Use Cases
* Create product marketing materials for a feature you just shipped with Claude Code.
* Recreate an email template made in Claude Design.
* Pull marketing analytics and campaign data for a strategy memo written in Claude Cowork.
* Draft social posts or create campaigns without switching back to Quotient.
## How Quotient's MCP Server Works
Quotient's MCP server exposes two main types of tools:
* **Action tools:** These mirror what you can do in Quotient yourself — creating campaigns, launching emails, publishing social posts, reading memories, and so on. Use them for direct, well-defined actions.
* **Agent-to-agent tools:** Instead of acting directly, these let another app talk to Quotient the same way you would. For example, Claude Code can send Quotient a message and get a response back. This is the best way to handle complex tasks that need a lot of Quotient-specific know-how.
Some tasks are best handled by talking to Quotient directly rather than calling individual tools:
* Creating and editing **email broadcasts** or **email templates**
* Defining complex **flows**, e.g. welcome series, customer win-back, and CRM automations
* Working with dynamic **audience segments**
* Analyzing data and creating **analytics reports**
These tasks rely on deep knowledge of Quotient's features, best practices, and internal formats, so it's usually best to **ask Quotient** to do them for you rather than stitching the individual steps together yourself.
## Tips for Getting the Most Out of It
* **Reach for agent-to-agent on anything complex.** If a task touches emails, flows, segments, or analysis, just ask Quotient in plain language instead of chaining individual tools together.
* **Be specific.** The more context you give — audience, goal, tone, dates — the better Quotient's output, the same as if you were briefing a teammate.
* **Lean on memory.** Quotient draws on your saved brand and business [memory](/docs/working-with-ai/memory), so the more you've taught it, the better your results across every connected app.
* **Start small.** Connect one app first, try a simple task like drafting a social post, then expand once you're comfortable.
## Next Up
-- End of: /mcp/from-other-apps/index
-- Start of: /mcp/from-other-apps/setup-instructions
---
title: MCP Setup Instructions
description: Step-by-step instructions for connecting ChatGPT, Claude, Cursor, Codex, and other AI apps to the Quotient MCP server.
order: 1
---
You can install Quotient directly from the ChatGPT and Claude listings below.
For other AI apps, connect to the Quotient MCP server at
`https://www.getquotient.ai/mcp`. Most clients support remote MCP natively; for
those that don't, use the `mcp-remote` bridge shown under
[Other clients](#other-clients). After you add Quotient, you'll be prompted to
sign in to authorize access.
Once connected, your AI app will show Quotient as an available MCP server and
ask you to authorize access before it can read or change anything in your
account.
## ChatGPT
Use the ChatGPT button above, then sign in to Quotient when prompted.
## Claude
Use the Claude button above, then sign in to Quotient when prompted. You can
also add it manually from Claude
**Settings → Connectors** by selecting **Add custom connector** and entering
`https://www.getquotient.ai/mcp`.
## Claude Code
```sh
claude mcp add --transport http quotient https://www.getquotient.ai/mcp
```
Then run `/mcp` in a session to complete authentication.
## Codex
```sh
codex mcp add quotient --url https://www.getquotient.ai/mcp
```
This prompts you to log in with your Quotient account. (First-time MCP users must set `experimental_use_rmcp_client = true` under `[features]` in `~/.codex/config.toml`.)
## Cursor
Open **Settings → MCP Tools → Add custom MCP**, then add:
```json
{
"mcpServers": {
"quotient": {
"url": "https://www.getquotient.ai/mcp"
}
}
}
```
## VS Code
`CMD/CTRL + P` → **MCP: Add Server** → **HTTP**, then enter the URL `https://www.getquotient.ai/mcp` and name it **Quotient**. Start it via **MCP: List Servers**.
## Windsurf
`CMD/CTRL + ,` → **Cascade → MCP servers → Add custom server**:
```json
{
"mcpServers": {
"quotient": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://www.getquotient.ai/mcp"]
}
}
}
```
## Zed
`CMD + ,` to open settings, then add:
```json
{
"context_servers": {
"quotient": {
"source": "custom",
"command": "npx",
"args": ["-y", "mcp-remote", "https://www.getquotient.ai/mcp"],
"env": {}
}
}
}
```
## Other clients
For any client that doesn't yet support remote MCP natively, use the [`mcp-remote`](https://github.com/geelen/mcp-remote) bridge:
* **Command**: `npx`
* **Arguments**: `-y mcp-remote https://www.getquotient.ai/mcp`
* **Environment**: None
## Next Up
-- End of: /mcp/from-other-apps/setup-instructions
-- Start of: /mcp/from-other-apps/tools-reference
---
title: MCP Tools Reference
description: A complete reference of every tool the Quotient MCP server exposes, grouped by area — campaigns, email, social, audience, and more.
order: 2
---
These are the tools available once you've connected to the Quotient MCP server. New to MCP? Start with the [overview](/docs/mcp/from-other-apps), or see the [setup instructions](/docs/mcp/from-other-apps/setup-instructions) to connect your app.
Each tool lists the permission it needs in parentheses. Read tools only fetch
data; write tools can create or update data.
## Agent (A2A)
Send messages to Quotient and collect its replies — useful for tasks the dedicated tools don't cover, like authoring emails.
* `a2a-send-message`: Send a message to Quotient to start a new conversation or continue an existing one.
* `a2a-get-response`: Collect Quotient's reply to a previously sent message.
## Memory
Quotient's persistent memory, organized into folders. (Requires `MEMORY_READ` / `MEMORY_WRITE`.)
* `memory-cat`: Read one or more memories by path. Returns each memory's content as a separate part.
* `memory-ls`: List the folders and memories directly inside a folder, one page at a time.
* `memory-search`: Search across all memories by meaning to find the most relevant sections.
* `memory-write`: Write or update a memory at a given path (content, tags, and/or pinned state).
* `memory-mkdir`: Create a folder. Parent folders are auto-created.
* `memory-mv`: Move or rename a memory or folder, including all of a folder's contents.
* `memory-rm`: Remove a memory or folder. It's archived rather than permanently deleted, so it can be recovered.
## Campaigns
Campaigns and their tasks. Briefs and task descriptions are written and returned as Markdown. (Requires `CAMPAIGN_READ` / `CAMPAIGN_WRITE`.)
* `create-campaign`: Create a campaign from a name and a Markdown brief, optionally with initial tasks.
* `update-campaign`: Update a campaign's name, brief, and/or dates (the brief replaces the entire brief).
* `get-campaign`: Get a campaign by id — its brief as Markdown, plus its tasks and deliverables (blogs, posts, emails, documents).
* `list-campaigns`: Browse campaigns, most recent start date first, one page at a time. Optionally filter by start-date range.
* `create-campaign-task`: Create a task on a campaign.
* `update-campaign-task`: Update a task's fields and/or status (the description replaces the entire description).
* `get-campaign-task`: Get a campaign task by id — its fields and description as Markdown.
* `list-campaign-tasks`: Browse campaign tasks, most recently updated first, one page at a time. Optionally filter by campaign and/or status.
## Email
Read-only access to email broadcasts; broadcasts are created by asking Quotient directly (`a2a-send-message`). (Requires `EMAIL_READ`.)
* `get-email-broadcast`: Get an email broadcast by id — name, status, launch date, target segments and lists, and a summary of the current email version.
* `list-email-broadcasts`: List your email broadcasts, most recently updated first, one page at a time.
## Analytics
Run reports over your marketing data — web traffic, email engagement, social performance, marketing events, and custom events — and manage saved reports. A report is a JSON query naming metrics, dimensions, and filters; read `describe-report-catalog` once before writing your first one. (Requires `ANALYTICS_READ` / `ANALYTICS_WRITE`.)
* `describe-report-catalog`: The reference for writing report queries — the document shape, every metric and dimension with what it means and which pair together, filter and time rules, and worked examples.
* `run-report`: Run a report query and get back a typed table, the resolved date windows, a CSV download link, and a run id. Nothing is saved.
* `get-report-rows`: Page through the rows of a completed report run by run id.
* `create-report`: Save a named report and run it now. The run becomes the report's snapshot. (Requires both `ANALYTICS_READ` and `ANALYTICS_WRITE`, since it returns the result.)
* `update-report`: Update a saved report's name, query, or visualization. Query changes refresh the snapshot in the background.
* `get-report`: Get a saved report by id — its query, visualization config, and current snapshot.
* `list-reports`: Browse saved reports, one page at a time, optionally searching by name.
* `list-custom-events`: List the custom event types defined for the business, with the ids to use in reports.
* `create-custom-event`: Define a new custom event type. The event id is immutable once created.
## Blog
Blog posts, written and returned as Markdown. (Requires `BLOG_READ` / `BLOG_WRITE`.)
* `create-blog`: Create a blog post from a title and Markdown content (created as a draft).
* `update-blog`: Update a blog post's title, content, meta description, and/or tags (content replaces the whole body).
* `get-blog`: Get a blog post by id — content as Markdown, status, slug, meta description, and tags.
* `list-blogs`: Browse blog posts, most recently updated first, one page at a time.
* `publish-blog`: Publish a blog post immediately, or schedule it for a future date.
* `unpublish-blog`: Revert a published or scheduled blog post back to a draft, taking it offline.
## Social
Create, schedule, and publish social posts across X, LinkedIn, Instagram, Facebook, and TikTok. (Requires `SOCIAL_READ` / `SOCIAL_WRITE`.)
* `list-social-accounts`: List your connected social accounts — id, platform, handle, and connection status.
* `create-social-post`: Create a new social media post with platform-specific optimizations (created as a draft).
* `update-social-post`: Update a draft post's content, attached assets, internal name, or platform-specific metadata.
* `get-social-post`: Retrieve a post's full details — content, status, publish date, attached assets, and the live platform URL once published.
* `list-social-posts`: Browse social posts, most recently created first, one page at a time.
* `search-social-posts`: Search social posts by name, body copy, or related meaning, with optional platform, status, and campaign filters. Paged.
* `publish-social-post`: Publish a social post immediately, or pass `publishAt` to schedule it for a future date.
* `unschedule-social-post`: Return a scheduled post to a draft. No platform side effects.
## Documents
Documents, written and returned as Markdown. (Requires `DOCUMENT_READ` / `DOCUMENT_WRITE`.)
* `create-document`: Create a document from Markdown content.
* `update-document`: Update a document's title and/or content (content replaces the whole document).
* `get-document`: Get a document by id — its title and current content as Markdown.
* `list-documents`: Browse your documents, most recently updated first, one page at a time.
## Assets
Your media library. (Requires `ASSET_READ` / `ASSET_WRITE`.)
* `create-asset-from-url`: Download an image or file from a public URL into the media library. Private or internal URLs are refused.
* `get-asset`: Get a media asset's metadata and CDN link by id — name, type, size, dimensions, and status.
* `list-assets`: Browse the media library, most recently updated first, one page at a time. Optionally filter by media type.
* `search-assets`: Find media assets by a text query over their names and descriptions.
## Audience (CRM)
People and companies can be created, read, updated, and listed; deals are read-only (synced from your connected CRM). (Requires the matching `AUDIENCE_*_READ` / `AUDIENCE_*_WRITE` scope.)
* `create-person`: Create a person in your audience, identified by email address.
* `update-person`: Update an existing person by id or email. Only provided fields change.
* `get-person`: Get a person's full profile by id — contact fields, subscription status, engagement, company link, and custom properties.
* `list-people`: Browse people, newest first, one page at a time. Optionally search and filter by subscription status.
* `create-company`: Create a company in your audience (only the name is required).
* `update-company`: Update an existing company by id. Only provided fields change.
* `get-company`: Get a company's full profile by id — firmographics, location, social links, associated people and deals, and custom properties.
* `list-companies`: Browse companies, name-ascending, one page at a time. Optionally search and filter by industry.
* `list-deals`: Browse your deals, one page at a time, optionally filtered by status. Read-only — synced from the connected CRM.
## Documentation
* `search-docs`: Search the Quotient documentation for features, setup guides, and troubleshooting. Returns the most relevant pages with an excerpt each, one page at a time.
* `get-doc`: Read the full content of a Quotient documentation page by its slug.
## Next Up
-- End of: /mcp/from-other-apps/tools-reference
-- Start of: /analytics/custom-events/index
---
title: Custom Events
description:
Record important website conversions and connect them to the marketing that
drove them
order: 4
---
Quotient's tracking tag records page views and sessions automatically, but not
the other things people do on your site, like clicking a button or submitting a
form. Those are often the actions that matter most: requesting a demo,
downloading a whitepaper, watching a video, or logging into your product.
To record these actions, you create **custom events** in Quotient and send them
from your website. Quotient then attributes each one, often called a conversion,
to the person who performed it and to the campaign content that brought them to
your site, so you can measure how many conversions your marketing drove.
When your site records a custom event, Quotient includes the visitor's current
session and attribution context. This lets you answer questions such as "Which
campaign drove the most demo requests?" instead of stopping at clicks and page
views.
This guide covers events that happen in a visitor's browser. If the conversion
completes on your server instead, such as an account created in an OAuth
callback, see
[Server-Side Conversions](/docs/analytics/custom-events/server-side-conversions).
Before you begin,
[install Quotient website tracking](/docs/analytics/on-site-tracking/custom-website)
on your site.
## Create the Custom Event in Quotient
Open
[Analytics → Custom Events](/s/most-recent-business/analytics/custom-events) and
click **Create Custom Event**. Each custom event has three fields:
- **Display Name** is the readable name shown in Quotient, such as "Requested
Demo."
- **Event ID** is the value your website sends, such as `requested_demo`. It
must start with a letter and contain only letters, numbers, and underscores.
- **Description** explains what the event means and when your site should send
it.
The event ID cannot be changed after you create the event, although you can edit
its display name and description. Choose one ID and reuse it everywhere that
records the same action.
You must create the event before your website sends it. Quotient rejects an
event ID that is not registered for your business.
## Record the Completed Action
Send the event after the action succeeds. For example, a demo-request event
should run after the form submission is accepted, not when someone first clicks
the submit button.
```javascript
async function handleDemoRequest(formData) {
const response = await fetch("/api/demo-requests", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(formData),
});
if (!response.ok) {
showSubmissionError();
return;
}
showSuccess();
void client.analytics.event({
eventType: "custom",
customEventId: "requested_demo",
});
}
```
Replace `requested_demo` with the event ID you created in Quotient. The browser
SDK sends analytics in the background, so the tracking request does not hold up
the form's success state.
The example uses the `client` created by `@quotientjs/client`. In a React
application, get the same client from the
[`useQuotient()` hook](/docs/sdk/react).
## If the Form Also Adds the Person to Quotient
It's common for a form to do two things at once:
[identify the person](/docs/analytics/identifying-users) and record a custom
event. In that case, wait for Quotient to identify the person before recording
the event:
```javascript
async function handleDemoRequest(formData) {
try {
await client.audience.people.identify({
emailAddress: formData.email,
firstName: formData.firstName,
lastName: formData.lastName,
});
} catch (error) {
console.error("Failed to save lead", error);
showSubmissionError();
return;
}
showSuccess();
void client.analytics.event({
eventType: "custom",
customEventId: "requested_demo",
});
}
```
`identify()` returns only after Quotient has saved the person and added their ID
to the browser client. The custom event sent immediately afterward therefore
belongs to that person.
Do not send these calls together with `Promise.all()`. The event could reach
Quotient before the person has been identified, causing it to be recorded as an
event that is not linked to a known person.
If the visitor has already been identified by a tagged email link or an earlier
`identify()` call, you only need to send the custom event.
## What Quotient Records
The SDK adds context automatically. In addition to the custom event ID, Quotient
records the current page, browsing session, and attribution from the visitor's
`utm_*` and `qt_*` URL parameters. When the browser knows the person, their
Quotient person ID is included too.
An event can still be useful when Quotient does not know the visitor's identity.
Quotient can attribute it to the campaign, email, social post, and session that
brought the visitor to your site, even when it cannot name the person.
Custom events do not currently accept additional event properties. Do not add
form fields, email addresses, or other personal information to the analytics
call. Store person information with `people.identify()` instead.
## Test Your Event
Test from a domain included in your public API key's allowed origins:
1. Open your browser's developer tools and select **Network**.
2. Complete the action that should send the event.
3. Search the requests for `analytics/web`.
4. Select the request and confirm that its status is `200`.
A `422` response usually means the `customEventId` does not exactly match an
event registered in Quotient. Event IDs are case-sensitive. A `403` response
usually means the site's domain is missing from the API key's allowed origins,
or the key does not have **Analytics: write** permission.
Once the request succeeds, ask Quotient a question such as:
> How many Requested Demo events did we record in the last 30 days, broken down
> by UTM source?
## Tips for Useful Events
- Track completed outcomes instead of button clicks or attempted submissions.
- Use one stable event ID for the same action across your site.
- Avoid sending the same event from more than one handler, which would count one
action twice.
- Upsert the person first when the same form also adds them to Quotient.
## Next Steps
-- End of: /analytics/custom-events/index
-- Start of: /analytics/custom-events/server-side-conversions
---
title: Server-Side Conversions
description:
Connect the conversions your server records to the marketing that brought the
visitor to your site
order: 1
---
Some conversions never happen in the browser. An OAuth callback creates the
account, a payment provider's webhook confirms the purchase, a background job
marks the trial as started. Your server knows the conversion happened, but the
marketing that caused it was only ever visible in the visitor's browser: the
newsletter link they clicked, the campaign in the URL, the session they were in.
This guide shows how to carry that browser-side knowledge to your server, so a
server-recorded event is attributed the same way a browser event would be.
Before you begin:
- [Install Quotient website tracking](/docs/analytics/on-site-tracking/custom-website) on your
site. The browser SDK is what collects the attribution in the first place.
- Install `@quotientjs/server` and create a private API key with
**Analytics: write** permission. See the
[server analytics API](/docs/sdk/analytics#track-a-server-event) for the
event call itself.
- [Create the custom event](/docs/analytics/custom-events) in Quotient. Server
events use the same registered event IDs as browser events.
## How the Browser Hands Off What It Knows
The browser SDK keeps a small record of the current visitor: which device and
session they are in, who they are if a tagged link or `people.upsert()` has
identified them, the page that referred them, and the `utm_*` and `qt_*`
attribution from the URL they arrived on. Quotient calls this record the
**browser context**. It reaches your server in one of two ways.
**The `qt_browser_context` cookie.** On every tracked event, the SDK writes the
browser context to a first-party cookie named `qt_browser_context`. The browser
attaches it to every request to your own domain, including requests that no page
of yours sends, such as an OAuth callback. Read it when the request that
completes the conversion is a request to your own domain.
The cookie expires 30 minutes after the visitor's last tracked event, the same
lifetime as the analytics session. If the cookie is present, the session it
describes is still live.
**`client.getBrowserContext()`.** Cookies do not travel to other domains. When
your conversion request goes to an API on a different domain, ask the browser
SDK for the same record and send it in your request body:
```typescript
const browserContext = client.getBrowserContext();
await fetch("https://api.yourcompany.com/signup", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ ...formData, browserContext }),
});
```
## What the Browser Context Contains
Both paths give you the same object:
```typescript
type BrowserContext = {
version: 1;
deviceId?: string; // random ID minted the first time this browser loaded the SDK
sessionId: string; // the rolling 30-minute session
personId?: string; // set once a tagged link or people.upsert() identified the visitor
referrerUrl?: string; // the external page that sent the visitor
attribution: Attribution; // utm_* and qt_* parameters from the arrival URL; {} when untagged
};
```
The cookie value is `encodeURIComponent(JSON.stringify(browserContext))`.
This shape is a stable contract. Fields are only ever added while `version`
stays `1`, so it is safe to store the object or forward it through your own
systems. If your code sees a `version` it does not recognize, ignore the object
rather than guessing at its contents.
## Record the Event on Your Server
Read the cookie (or the body field), parse it, and pass the result as
`browserContext` on the server event. Quotient then stores the event with the
same session, device, referrer, and attribution a browser event would carry, so
the source, campaign, and content dimensions in your reports include it.
```typescript
import {
BROWSER_CONTEXT_COOKIE_NAME,
type BrowserContext,
} from "@quotientjs/server";
// The cookie is untrusted input. Treat anything unreadable as "no context"
// so a bad cookie can never break your own signup handler.
function readBrowserContext(
cookieValue: string | undefined,
): BrowserContext | undefined {
if (!cookieValue) return undefined;
try {
return JSON.parse(decodeURIComponent(cookieValue));
} catch {
return undefined;
}
}
// inside your signup handler, after the account is actually created
// (Next.js shown; `cookies.get()` returns an object with a `value`)
const browserContext = readBrowserContext(
request.cookies.get(BROWSER_CONTEXT_COOKIE_NAME)?.value,
);
await quotient.analytics.event({
eventType: "custom",
personId: person.id,
customEventId: "signedUp",
browserContext,
});
```
Send the event after the conversion has actually succeeded, the same rule as for
browser events. If the account was not created, there is nothing to attribute.
## What Quotient Trusts
The browser context is a claim about attribution, and only that. It comes from
the visitor's browser, so Quotient never lets it decide who an event belongs to:
- `personId` on the event itself decides the person. `browserContext.personId`
is ignored, and the API still checks that `personId` belongs to your business.
- A `browserContext` the API cannot make sense of (an unknown `version`, or
attribution that breaks the URL-tagging rules) is dropped, and the event is
recorded without attribution. A stale or tampered cookie never costs you the
conversion itself.
## Next Steps
-- End of: /analytics/custom-events/server-side-conversions
-- Start of: /analytics/on-site-tracking/custom-website
---
title: Custom Website
description: Install website tracking on a site you build and host yourself
order: 1
---
When someone reaches your website from a Quotient email, social post, or
campaign, the Quotient pixel shows you what they do next. It records the pages
they visit while preserving the content that brought them to your site as the
source.
This guide covers websites that you build yourself, from static HTML hosted on
GitHub Pages to applications built with React, Next.js, Remix, or React Router.
If you use a hosted website builder, follow the instructions for that platform
instead.
## Create a Public API Key
Create a key in
[Settings → Developers](/s/most-recent-business/settings/developers). Choose a
**Public** key and give it the **Analytics: write** permission.
Add every domain where you will run the pixel to the key's allowed origins. For
example, you might add:
- `https://example.com` for your production site
- `https://your-name.github.io` for a GitHub Pages site
- `http://localhost:3000` for local development
Each origin must match exactly, including `https://`. If your site loads on both
`https://example.com` and `https://www.example.com`, add both.
Allowed origins prevent another website from using your key. The key you copy
should begin with `pk_`. Never put a private key beginning with `sk_` in code
that runs in a browser.
## Choose an Installation Method
The right installation method depends on how your site is built.
### Static HTML
Use this method for a site made from HTML files, including a static site hosted
on GitHub Pages. Add the following code before the closing `