Copy from Pipeline
✉
Copy All Emails@
Copy All InstagramExport
⬇
Export Pipeline CSV
Show:
People pipeline
Contacts
Your saved prospects and customers
⌕
Copy Socials
Copy All Socials
@
Copy All Instagram✉
Copy All EmailsExport / Import
⬇
Export as CSVImport CSV
Manage
Find & Remove Duplicates
Remove Empty Contacts
Filters
0 selected
Daily execution
Tasks
Create follow-ups in plain English, then work through what needs doing next.
Quick add
Type naturally: “Call Jane tomorrow 3pm” or use the chips below.
Today
Tomorrow
This week
Pick date
Time
High
Medium
Low
Set a time
Context
Notes
Store call notes, reminders, and useful context attached to your contacts.
Reusable outreach
Message Templates
Create reusable messages and use them from any contact profile.
⌕
Outbound setup
Email Settings
Choose how email links open when you tap an address or the Email button on a contact.
Currently using
Default Mail App
Choose your email client
Custom URL scheme
Your custom compose URL pattern
Available variables:
{{email}} {{subject}} {{body}} {{name}}Preview
When you tap email on a contact, it will open:
mailto:[email protected]
Note: Web-based clients (Gmail, Outlook web, Yahoo) open in a new browser tab. Desktop/app clients (Apple Mail, Windows Mail, Thunderbird, Spark) use URL schemes handled by your OS. On mobile, your installed apps will be offered automatically.
Connections
Integrations
Connect your CRM to external tools. Data syncs automatically on every save.
📊
Google Sheets Sync
Auto-sync all contacts to a Google Sheet on every update
● Live
Apps Script Webhook URL
Paste your Google Apps Script deployment URL here
Last synced: never
📋 Setup Guide
▼
Step 1 — Create your Google Sheet
Open Google Sheets and create a new spreadsheet. Name it anything you like (e.g. "Pipeline CRM").
Step 2 — Open Apps Script
In your sheet, click Extensions → Apps Script. Delete any existing code in the editor.
Step 3 — Paste this script
function doPost(e) {
try {
var data = JSON.parse(e.postData.contents);
var ss = SpreadsheetApp.getActiveSpreadsheet();
var stages = data.stages || [];
var contacts = data.contacts || [];
var headers = ["First Name","Last Name","Company","Email","Phone","Instagram","Website","Value","Tags","Notes","Created","Updated"];
// Track which sheet names we use this sync
var usedSheets = [];
// ── One sheet per stage ──
stages.forEach(function(stage) {
var sheetName = stage.name.substring(0, 100); // Sheet names max 100 chars
var sheet = ss.getSheetByName(sheetName);
if (!sheet) sheet = ss.insertSheet(sheetName);
sheet.clearContents();
// Header row
sheet.appendRow(headers);
// Style header row
var headerRange = sheet.getRange(1, 1, 1, headers.length);
headerRange.setFontWeight("bold");
headerRange.setBackground("#f3f3f3");
// Contacts in this stage
var stageContacts = contacts.filter(function(c) { return c.stage === stage.id; });
stageContacts.forEach(function(c) {
sheet.appendRow([
c.firstName||"", c.lastName||"", c.company||"", c.email||"",
c.phone||"", c.instagram||"", c.website||"", c.value||0,
(c.tags||[]).join(", "), c.notes||"",
c.createdAt ? new Date(c.createdAt).toLocaleDateString() : "",
c.updatedAt ? new Date(c.updatedAt).toLocaleDateString() : ""
]);
});
// Auto-resize columns
sheet.autoResizeColumns(1, headers.length);
usedSheets.push(sheetName);
});
// ── Move stage sheets to the end, in pipeline order ──
var allSheets = ss.getSheets();
var nonStageSheets = allSheets.filter(function(s) {
return usedSheets.indexOf(s.getName()) === -1;
});
// Keep non-stage sheets at front (index 0..n), then append stage sheets in order
var insertPos = nonStageSheets.length;
usedSheets.forEach(function(name, i) {
var s = ss.getSheetByName(name);
if (s) ss.moveActiveSheet && ss.setActiveSheet(s) && ss.moveActiveSheet(insertPos + i + 1);
});
return ContentService.createTextOutput(JSON.stringify({ok:true})).setMimeType(ContentService.MimeType.JSON);
} catch(err) {
return ContentService.createTextOutput(JSON.stringify({ok:false,error:err.message})).setMimeType(ContentService.MimeType.JSON);
}
}
function doGet(e) {
return ContentService.createTextOutput(JSON.stringify({ok:true,status:"Pipeline CRM webhook active"})).setMimeType(ContentService.MimeType.JSON);
}
Step 4 — Deploy as a Web App
Click Deploy → New deployment
• Type: Web app
• Execute as: Me
• Who has access: Anyone (no sign-in required)
Click Deploy, authorise when prompted, then copy the Web app URL.
Step 5 — Paste URL above & test
Paste the URL into the field above and click Save & Test. Your sheet will update automatically every time you add or edit a contact.
Automation
Workflows
Create sequences, add leads, and assign tasks per step.
Data movement
Import / Export
Bring contacts into the CRM, map their stage, remove duplicates, or export your current data.
1Choose default stageWhere unmatched contacts should go.
2Upload CSVDrop a file or browse from your device.
3Review mappingCheck duplicates and import clean data.
Export data
Download all contacts or just the current pipeline.
Import CSV
Start with a default stage, then upload your file. Duplicate removal stays on by default during import.
Default Status
Used when a row has no status, or its value can't be matched below
Duplicates found
↑
Drop your CSV here
or tap to browse · auto-maps common columns
Top Of CRM
Job Board
Review new opportunities as soon as the CRM opens, and send any posting straight into your contact pipeline with the original details attached.
Help document
Tutorial Document
Use this embedded guide when you need help setting up or using the CRM.