Beginner~12 min setupCommunication & CRMVerified April 2026
Slack logo
Copper logo

How to Log Slack Messages to Copper CRM with Make

When a message is posted in a designated Slack channel, Make captures it instantly and creates an activity note on the matching Copper contact record.

Steps and UI details are based on platform versions at time of writing — check each platform for the latest interface.

Best for

Sales or CS teams using Slack for customer conversations who need every interaction captured in Copper without manual copy-paste

Not ideal for

Teams who want to log every Slack message company-wide — scope this to specific channels or you will flood Copper with noise

Sync type

real-time

Use case type

sync

Real-World Example

💡

A 12-person B2B SaaS company creates a dedicated Slack channel per customer during onboarding. Their CS reps were copying key messages into Copper by hand, taking 5-10 minutes per conversation and frequently skipping it under deadline pressure. With this scenario running, every message posted in those channels lands in Copper as a timestamped activity note within 30 seconds — no manual entry.

What Will This Cost?

Drag the slider to your expected monthly volume.

/mo
505005K50K

Each platform counts differently — Zapier: 1 task per trigger. Make: 1 operation per module per record. n8n: 1 execution per run.

Prices shown for annual billing. Based on published pricing as of April 2026.

Estimated ROI

1000

min saved/mo

$583

labor value/mo

Free

no platform cost

Based on ~2 min manual effort per operation at $35/hr fully loaded labor cost.

Implementation

Skip the setup

Import this workflow directly into Make

Copy the pre-built Make blueprint and paste it straight into Make. All modules, filters, and field mappings are already configured — you just need to connect your accounts.

Before You Start

Make sure you have everything ready.

Slack workspace admin access or permission to install Make as an app — the OAuth connection requires 'channels:read', 'messages:read', and 'users:read' scopes
Copper account with API access enabled — retrieve your API key from Copper under Settings > Integrations > API Keys
The Copper API key user must have permission to create activities on contact records in your workspace
A Make account with at least the Core plan — the free tier does not support instant (webhook-based) triggers, which this workflow requires
At least one Slack channel already set up and dedicated to customer communication — logging works best when channels are scoped per customer or account, not a catch-all #general

Field Mapping

Map these fields between your apps.

FieldAPI Name
Required
Contact ID (Parent)parent.id
Parent Typeparent.type
Activity Typetype.id
Activity Detailsdetails
Activity Dateactivity_date
Slack Message Text
Slack User Email
Slack Message Timestamp (ts)
2 optional fields▸ show
Slack Sender Display Name
Slack Channel Name

Step-by-Step Setup

1

make.com > Scenarios > Create a new scenario

Create a new scenario in Make

Log into make.com and click the blue 'Create a new scenario' button in the top-right of your dashboard. You will land on the visual scenario builder — a blank canvas with a large plus icon in the center. This is where you add your first module. Give the scenario a name right away by clicking the default title at the top; name it something like 'Slack → Copper: Log Customer Messages' so it's immediately identifiable in your scenario list.

  1. 1Click 'Create a new scenario' in the top-right
  2. 2Click the large plus icon on the canvas to open the app picker
  3. 3Type 'Slack' in the search bar
  4. 4Select 'Slack' from the results
What you should see: The Slack module picker opens showing a list of available Slack triggers and actions.
Common mistake — Make auto-saves scenario names only after you run the scenario once. If you close the tab before that, the name reverts to 'New scenario'. Name it and run a test immediately.
2

Scenario Canvas > Slack Module > Watch Messages

Configure the Slack trigger: Watch Messages

From the Slack module list, select 'Watch Messages' as your trigger — this fires instantly when a new message is posted in a channel you specify. You will be prompted to connect your Slack workspace if you haven't already; click 'Add' and follow the OAuth flow. Once connected, set the Channel field to the specific customer-facing channel you want to monitor, such as #customer-acme or a channel group pattern. Set the trigger to watch 'New Messages' only, not thread replies, unless you want replies logged too.

  1. 1Select 'Watch Messages' from the Slack trigger list
  2. 2Click 'Add' next to the Connection field to authenticate with Slack
  3. 3Authorize Make in the Slack OAuth popup
  4. 4Set the Channel dropdown to your target customer channel
  5. 5Set 'Message type' to 'Messages' (not replies) unless you need both
What you should see: The module card shows your connected Slack workspace name and the selected channel name. You should see a green dot or 'Connected' indicator next to the connection field.
Common mistake — The 'Watch Messages' trigger only captures messages posted after the scenario is activated. It will not backfill historical Slack messages. If you need historical data, that requires a separate bulk-import approach.
Message template
📬 New entry: {{1.name}}
Email: {{1.email}}
Details: {{1.description}}
Make
+
click +
search apps
Slack
SL
Slack
Configure the Slack trigger:…
Slack
SL
module added
3

Scenario Canvas > Add Module > Slack > Get User Info

Add a Text Parser to extract contact email

Most Slack messages won't contain the customer email directly, but Slack user profiles often do. Add a 'Tools > Get a Variable' module or, more practically, add the Slack 'Get User Info' module to resolve the message sender's Slack user ID into a real name and email address. Connect it immediately after the trigger. Map the 'User' field from the Watch Messages output (it returns a user ID like U04XKPL2B) into the 'User ID' field of Get User Info. This email is what you will use to look up the matching Copper contact in the next step.

  1. 1Click the right edge of the Slack trigger module to add a new module
  2. 2Search for 'Slack' and select it
  3. 3Choose 'Get User Info' from the action list
  4. 4Map the 'User' output from the Watch Messages trigger into the 'User ID' field
  5. 5Save the module
What you should see: The Get User Info module shows the mapped User ID token. When you run a test, it should return a profile object including the user's display name and email address.
4

Scenario Canvas > Add Module > Copper > Search Contacts

Search Copper for the matching contact

Add a Copper module and choose 'Search Contacts'. Connect your Copper account via OAuth — Make uses Copper's v1 REST API, and you will need your Copper API key plus the email address associated with your Copper account for authentication. In the search filter, map the email from the Slack Get User Info output (profile.email) into the Email search field. This locates the Copper contact record that matches the person who sent the Slack message. If no match is found, you can route the scenario differently using a Router in the next step.

  1. 1Click the plus icon after the Get User Info module
  2. 2Search for 'Copper' and select it
  3. 3Choose 'Search Contacts' from the action list
  4. 4Click 'Add' to connect Copper — enter your Copper API key and account email
  5. 5Map 'profile.email' from the Slack module into the Email filter field
What you should see: The Copper module shows a valid connection and the Email field displays the mapped Slack email token. A test run should return a Copper contact object including the contact's ID, name, and existing activity count.
Common mistake — Copper's API key is per-user, not per-workspace. If the person who connects Copper leaves your company, the connection breaks for everyone. Use a shared admin account email when setting up the API key.
5

Scenario Canvas > Connection Line > Add Router

Add a Router to handle missing contacts

Not every Slack user will have a matching Copper contact — internal team members, bots, and new prospects won't be found. Add a Router module after the Search Contacts step. This splits your scenario into two paths: one for when a contact is found, one for when it isn't. The Router in Make is added by clicking the small wrench icon on the connection line between modules and selecting 'Add a router'. You will set conditions on each path in the next step.

  1. 1Right-click the connection line after the Copper Search Contacts module
  2. 2Select 'Add a router' from the context menu
  3. 3Two output paths appear from the Router node
  4. 4Label Path 1 'Contact Found' and Path 2 'No Contact — Skip'
What you should see: The canvas now shows a diamond-shaped Router module with two outgoing paths. Each path has a filter icon where you will set conditions.
6

Scenario Canvas > Router > Filter Icon

Set filter conditions on each Router path

Click the filter icon on Path 1 and set the condition: the Copper Search Contacts result ID field 'Exists' (is not empty). This means a contact was found. On Path 2, set the opposite condition: ID 'Does not exist'. For Path 2, you can simply add a Slack module to post a message to a private admin channel like #crm-alerts saying a Slack message had no matching Copper contact — giving your team a chance to create the contact manually. This prevents silent data loss.

  1. 1Click the filter icon on the first Router path
  2. 2Set Field to the Copper contact ID output token
  3. 3Set Condition to 'Exists'
  4. 4Click the filter icon on the second path
  5. 5Set the same field with condition 'Does not exist'
What you should see: Both paths now show a small filter badge. Running a test with a known Slack user who has a Copper record should route to Path 1. An unknown user routes to Path 2.
Common mistake — Make evaluates Router conditions top-to-bottom and stops at the first match. If both filters are misconfigured identically, all records go to Path 1. Double-check that the conditions are truly opposite before activating.
Slack
SL
trigger
filter
Condition
matches criteria?
yes — passes through
no — skipped
Copper
CO
notified
7

Scenario Canvas > Router Path 1 > Copper > Create Activity

Add Copper 'Create Activity' on the matched-contact path

On Path 1, add a Copper module and select 'Create Activity'. This is where the Slack message gets written to the contact's timeline in Copper. Set the 'Parent Type' to 'contact' and map the Copper contact ID from the Search Contacts output into the 'Parent ID' field. Set the Activity Type to 'Note' — Copper supports custom activity types too, but Note is universally available. In the Details field, you will build a formatted string combining the Slack message text, sender name, channel name, and timestamp.

  1. 1Click the plus icon on Path 1 of the Router
  2. 2Search for and select 'Copper'
  3. 3Choose 'Create Activity'
  4. 4Set 'Parent Type' to 'contact'
  5. 5Map the Copper contact ID into 'Parent ID'
  6. 6Set 'Activity Type' to 'Note'
What you should see: The Create Activity module shows the Parent ID field populated with the mapped contact ID token and Activity Type set to Note.
8

Scenario Canvas > Copper Create Activity > Details Field

Build the activity detail field with formatted message content

Click into the 'Details' field of the Create Activity module. Use Make's text editor to compose the note body. Type a label, then insert dynamic tokens from the previous modules. A good format is: '[Slack] #channel-name | Sender: display_name | Date: timestamp\n\n message_text'. Use Make's built-in formatDate() function to convert the Slack Unix timestamp (it comes as seconds since epoch) into a readable format. The formatDate() call wraps the timestamp token like this: formatDate(timestamp * 1000; "YYYY-MM-DD HH:mm"). Without the * 1000, Make misreads the Unix timestamp as milliseconds.

  1. 1Click into the Details field in the Copper Create Activity module
  2. 2Type '[Slack] #' then click the token picker and select the Slack channel name
  3. 3Add ' | Sender: ' then map the Slack user display name
  4. 4Add ' | Date: ' then insert formatDate(ts * 1000; "YYYY-MM-DD HH:mm")
  5. 5Press Enter twice, then map the Slack message text field
What you should see: The Details field shows a mix of static text and orange token chips. A test run should produce a readable note like: '[Slack] #customer-acme | Sender: Jane Park | Date: 2024-03-15 14:32\n\nCan we push the go-live to next Tuesday?'
Common mistake — Slack's 'ts' field is a Unix timestamp string, not an integer. Wrap it in a multiply or convert it before passing to formatDate(). If you skip this, Copper will receive an unreadable epoch number as the date.
Message template
📬 New entry: {{1.name}}
Email: {{1.email}}
Details: {{1.description}}
Slack fields
text
user
channel
ts
thread_ts
available as variables:
1.props.text
1.props.user
1.props.channel
1.props.ts
1.props.thread_ts
9

Scenario Canvas > Copper Create Activity > All Fields

Map remaining activity fields

Still in the Create Activity module, fill in the optional but useful fields. Set 'Activity Date' to the formatted date from the previous step — Copper uses ISO 8601 format (YYYY-MM-DD) for this field, separate from the note details text. If your Copper account has custom activity categories, match the closest one. Leave 'User ID' blank unless you want to attribute the activity to a specific Copper user rather than the API key owner. Check that the 'Parent ID' correctly references the Copper contact ID, not the person ID from Slack.

  1. 1Set 'Activity Date' to formatDate(ts * 1000; "YYYY-MM-DD")
  2. 2Leave 'User ID' blank unless attributing to a specific rep
  3. 3Confirm 'Parent Type' is 'contact' not 'lead' or 'opportunity'
  4. 4Save the module
What you should see: All required fields in the Create Activity module have either mapped tokens or static values. No fields show a red required-field error.
Common mistake — Copper treats 'contact' and 'lead' as different parent types with separate ID spaces. Passing a contact ID with Parent Type set to 'lead' returns a 404 error from Copper's API. Confirm your parent type matches your actual Copper record type.
10

Scenario Canvas > Run Once (bottom toolbar)

Activate the scenario and test with a real message

Click 'Run once' in the bottom-left of the scenario builder to fire a test. Go to your Slack workspace and post a test message in the target channel from an account that has a matching Copper contact. Return to Make and watch the execution flow animate across the modules — green checkmarks mean data passed through, orange badges show the record count per module. Click any module to inspect the exact data it received and output. Confirm the Copper contact now shows the new activity in its timeline.

  1. 1Click 'Run once' in the bottom-left toolbar
  2. 2Post a test Slack message in the target channel
  3. 3Watch the execution animation in Make
  4. 4Click the Copper Create Activity module bubble to inspect the output
  5. 5Open Copper and find the contact — check the Activity tab for the new note
What you should see: The Copper contact's Activity tab shows a new Note entry with the correct Slack message text, sender name, channel, and formatted timestamp. The Make execution history shows all modules with green checkmarks.
Common mistake — Map fields using the variable picker — don't type field names manually. Hand-typed variable names often have invisible spacing errors that produce blank output.
Message template
📬 New entry: {{1.name}}
Email: {{1.email}}
Details: {{1.description}}
Make
▶ Run once
executed
Slack
Copper
Copper
🔔 notification
received
11

Scenario Canvas > Toggle (bottom-left) > Scenario Settings

Schedule and activate the scenario

Once the test passes, click the toggle in the bottom-left of the scenario builder to switch from 'Off' to 'On'. Because this uses Slack's event-based trigger via Make's webhook infrastructure, the scenario fires within seconds of each new Slack message — you do not need to set a polling interval. Set the maximum number of cycles per execution to 1 (the default) since each Slack message fires its own trigger. In the scenario settings, enable 'Auto-commit' so partial runs don't leave incomplete data in Copper.

  1. 1Click the toggle at the bottom-left to set the scenario to 'On'
  2. 2Click the clock icon to open scheduling settings
  3. 3Confirm the scenario is set to respond to webhooks, not a timed interval
  4. 4Open Scenario Settings and enable 'Auto-commit'
  5. 5Save settings
What you should see: The scenario status shows 'Active' with a green indicator. The next time a message is posted in your target Slack channel, it will appear in Copper within 30 seconds.
Common mistake — Confirm your workflow timezone matches your business timezone — n8n uses the instance timezone by default. Also verify the workflow is saved and set to Active, since Schedule Triggers won't fire on inactive workflows.

This formula goes in the Details field of the Copper Create Activity module. It conditionally appends a '[URGENT]' tag to the note if the Slack message contains certain keywords, so your team can filter high-priority interactions in Copper's activity feed.

JavaScript — Custom Functionif(
▸ Show code
if(
  or(
    contains(lower(text); "urgent"),

... expand to see full code

if(
  or(
    contains(lower(text); "urgent"),
    contains(lower(text); "escalate"),
    contains(lower(text); "cancel"),
    contains(lower(text); "refund")
  );
  "[URGENT] [Slack] #" + channel_name + " | Sender: " + profile.display_name + " | Date: " + formatDate(ts * 1000; "YYYY-MM-DD HH:mm") + "\n\n" + text;
  "[Slack] #" + channel_name + " | Sender: " + profile.display_name + " | Date: " + formatDate(ts * 1000; "YYYY-MM-DD HH:mm") + "\n\n" + text
)

Going live

Production Checklist

Before you turn this on for real, confirm each item.

Troubleshooting

Common errors and how to fix them.

Frequently Asked Questions

Common questions about this workflow.

Analysis

VerdictWhy Make for this workflow

Use Make for this if your team needs conditional routing — specifically, the ability to handle cases where a Slack sender has no matching Copper contact without crashing the whole scenario. Make's visual Router module handles this in about 3 clicks. You also get formatDate() and string manipulation functions built directly into the field editor, which matters here because Slack's timestamps arrive as Unix epoch strings that need conversion before Copper will accept them. The one scenario where you'd skip Make: if your team already uses Zapier for everything else and the person setting this up has never used Make before. The learning curve is real, and for this specific workflow, Zapier can do it too.

Cost

The math is straightforward. Each Slack message that triggers the scenario runs through 4 modules: Watch Messages, Get User Info, Search Contacts, Create Activity. That's 4 operations per message. Make's free tier gives you 1,000 operations per month — enough for 250 logged messages. At 500 messages per month (a mid-sized team with two active customer channels), you need Make's Core plan at $9/month, which includes 10,000 operations. Zapier's equivalent would run you $20/month on the Starter plan for similar volume. Make is cheaper by $11/month at this scale, and the gap widens as volume grows.

Tradeoffs

Zapier's main advantage here is setup speed — their Slack + Copper Zap templates are pre-built and take about 6 minutes to configure if you don't need conditional logic. n8n handles this workflow well if you self-host and want to parse complex Slack message payloads using JavaScript directly in a Code node — no formula gymnastics. Power Automate technically supports both Slack and Copper but requires custom connectors for Copper since it's not a first-party Microsoft connector, which adds 45+ minutes to setup and breaks unpredictably after updates. Pipedream is worth considering if you're comfortable with Node.js and want to write the Copper API call directly — it gives you full control over the request body and handles retry logic out of the box. Make wins here for teams who want a visual setup, can tolerate 30 minutes of configuration, and don't want to write code.

Three things you will hit after going live. First, Slack threads. The 'Watch Messages' trigger fires on top-level messages but not thread replies by default — if your customer conversations happen in threads, you'll miss most of the content. You need to explicitly enable thread reply watching, which then requires a filter to avoid double-logging the parent message. Second, Copper's activity search has no deduplication — if your scenario has a bug and fires twice on the same message, you get two identical activities on the contact with no easy way to clean them up in bulk. Add an idempotency check using the Slack message ts as a unique key before writing to Copper. Third, Slack will occasionally send duplicate events for the same message during network issues. Copper doesn't deduplicate on its end, so you need to store the ts values in a Make data store and skip any message whose ts you've already processed.

Ideas for what to build next

  • Log to Copper Opportunities TooExtend the scenario with a second Copper search that checks if the contact is linked to an open opportunity, and creates the activity on both the contact and the deal record simultaneously.
  • Build a Daily Slack Digest of Logged MessagesAdd a second Make scenario on a daily schedule that pulls all Copper activities created in the last 24 hours and posts a summary to a #sales-digest Slack channel — gives leadership visibility without opening Copper.
  • Auto-create Missing Copper Contacts from SlackOn the Router's 'no contact found' path, instead of just sending an alert, add a Copper Create Contact module that auto-creates the contact using the Slack user's name and email — so no customer falls through the cracks.

Related guides

Was this guide helpful?
Slack + Copper overviewMake profile →