Paste a call transcript and this scores it automatically against the referral-outreach rubric — critical guardrails, core execution, and professionalism — using the same tiered logic as the master scorecard.
Basic identifiers for the record.
| Staff Name | |
| Date | |
| Call ID |
Pull a call straight from Aircall, and send finished audits to a Google Sheet. Both go through one small relay script you deploy once — see setup below.
ANTHROPIC_API_KEY (from console.anthropic.com → API Keys) — this is required for the "Run AI audit" button to work at all; it proxies the scoring call through this script so the key is never exposed in the page. Also add AIRCALL_API_ID and AIRCALL_API_TOKEN (from Aircall Dashboard → Company Settings → API Keys) if you want the Aircall import button too — that part is optional.function doPost(e) {
var body = JSON.parse(e.postData.contents);
if (body.action === 'submit') return handleSubmit(body.payload);
if (body.action === 'fetchCall') return handleFetchCall(body.callId);
if (body.action === 'auditCall') return handleAuditCall(body.payload);
return json_({error: 'Unknown action'});
}
function doGet(e) {
return json_({status: 'Audit relay is running'});
}
var TARGET_SPREADSHEET_ID = '1y_iwRNLomBeeXM9g6nXzIJwfq-X_xMhrsUQnTjHTjCE';
var TARGET_GID = 2132488623;
function getTargetSheet_() {
var ss = SpreadsheetApp.openById(TARGET_SPREADSHEET_ID);
var sheets = ss.getSheets();
for (var i = 0; i < sheets.length; i++) {
if (sheets[i].getSheetId() === TARGET_GID) return sheets[i];
}
throw new Error('Tab with gid ' + TARGET_GID + ' not found in the target spreadsheet.');
}
function handleSubmit(payload) {
var sh = getTargetSheet_();
if (sh.getLastRow() === 0) {
sh.appendRow(['Timestamp','Staff Name','Date','Call ID','Identity','Safety','Consent',
'Intro','Program','Insurance','Scheduling','Closing','Objection','Tone',
'SLA','Canvas','Consent Sent','Total Score %','Tier','Needs Review','Note']);
}
sh.appendRow([new Date(), payload.staffName, payload.date, payload.callId,
payload.identity, payload.safety, payload.consent, payload.intro, payload.program,
payload.insurance, payload.scheduling, payload.closing, payload.objection, payload.tone,
payload.sla, payload.canvas, payload.consent_sent, payload.total, payload.tier, payload.needsReview,
payload.note]);
return json_({status: 'ok'});
}
function handleFetchCall(callId) {
var props = PropertiesService.getScriptProperties();
var apiId = props.getProperty('AIRCALL_API_ID');
var apiToken = props.getProperty('AIRCALL_API_TOKEN');
var auth = Utilities.base64Encode(apiId + ':' + apiToken);
var opts = { headers: { Authorization: 'Basic ' + auth }, muteHttpExceptions: true };
var callRes = UrlFetchApp.fetch('https://api.aircall.io/v1/calls/' + callId, opts);
var call = JSON.parse(callRes.getContentText());
if (call.error) return json_({error: call.error, troubleshoot: call.troubleshoot});
var transcriptText = '';
try {
var trRes = UrlFetchApp.fetch('https://api.aircall.io/v1/calls/' + callId + '/transcription', opts);
var tr = JSON.parse(trRes.getContentText());
if (tr.transcription && tr.transcription.utterances) {
transcriptText = tr.transcription.utterances.map(function(u) {
return (u.participant && u.participant.name ? u.participant.name : 'Speaker') + ': ' + u.text;
}).join('\\n');
}
} catch (err) {
transcriptText = '';
}
return json_({
callId: callId,
staffName: call.call && call.call.user ? call.call.user.name : '',
date: call.call ? new Date(call.call.started_at * 1000).toISOString().slice(0,10) : '',
recording: call.call ? call.call.recording : '',
transcript: transcriptText
});
}
function handleAuditCall(payload) {
var props = PropertiesService.getScriptProperties();
var apiKey = props.getProperty('ANTHROPIC_API_KEY');
if (!apiKey) return json_({error: 'ANTHROPIC_API_KEY is not set in Script Properties.'});
var opts = {
method: 'post',
contentType: 'application/json',
headers: { 'x-api-key': apiKey, 'anthropic-version': '2023-06-01' },
payload: JSON.stringify({
model: 'claude-sonnet-4-6',
max_tokens: 1800,
system: payload.system,
messages: [{ role: 'user', content: payload.userMessage }]
}),
muteHttpExceptions: true
};
var res = UrlFetchApp.fetch('https://api.anthropic.com/v1/messages', opts);
var data = JSON.parse(res.getContentText());
if (data.error) return json_({error: data.error.message || 'Anthropic API error'});
var text = (data.content || []).filter(function(b){ return b.type === 'text'; })
.map(function(b){ return b.text; }).join('\n');
return json_({text: text});
}
function json_(obj) {
return ContentService.createTextOutput(JSON.stringify(obj)).setMimeType(ContentService.MimeType.JSON);
}
Transcript import needs Aircall's AI Assist add-on enabled on your account. Without it, "Import from Aircall" still pulls staff name, date, and the recording link — paste the transcript in manually alongside it.
Paste the full call transcript below, then run the audit — the AI will determine whether any critical guardrail failed, and will suggest a point score for every Core Execution / Situational / Professionalism item. You can also fill in everything manually without running the AI at all, and you can override any AI-suggested number.
| Tiered Scoring Framework | Quality Metrics | Scores |
|---|---|---|
| Green Zone (≥ 90%) → Excellent quality call | Critical Guardrail | — |
| Yellow Zone (85–89%) → Acceptable but improvable | Core Execution | — |
| Red Zone (< 85%) → Needs coaching or corrective action | Process/Compliance | — |
| Total Score | — |