SurveyGuard announces January Launch

Developer docs

Integrate SurveyGuard
in minutes

The JavaScript SDK, server-side API, platform guides and a full API
reference — everything you need to protect your surveys.

Getting started

Quick start

Add SurveyGuard to a survey in three steps.

01

Get your API key

Sign up, create a project for your survey and copy the API key from the project settings.

02

Add the script

Paste the SDK just before the closing </body> tag of your survey page.

03

Review in the dashboard

Every submission is analyzed in the background and appears in your dashboard with a Trust Score.

survey.html

<script src="https://cdn.surveyguard.ca/sdk.js"></script>
<script>
  SurveyGuard.init('YOUR_API_KEY');
</script>

survey.html

<script
  src="https://cdn.surveyguard.ca/sdk.js"
  data-api-key="YOUR_API_KEY">
</script>

JavaScript SDK

Configuration

Pass an options object as the second argument to SurveyGuard.init(). Every option is optional.

Option Type Description
apiUrl
string
Custom API URL.
autoAttach
boolean
Attach to the forms on the page automatically.
blockHighRisk
boolean
Silently block HIGH-risk submissions. The respondent only sees a generic error.
showWarnings
boolean
Show fraud details to respondents. Keep this off — results belong in your dashboard.
riskThreshold
number
Risk threshold, from 0 to 100.
autoDetectIp
boolean
Detect the respondent’s IP address automatically. Defaults to true.

config.js

SurveyGuard.init('YOUR_API_KEY', {
  apiUrl: 'https://api.surveyguard.com',  // custom API URL
  autoAttach: true,         // attach to forms automatically
  blockHighRisk: true,      // silently block HIGH risk
  showWarnings: false,      // never show fraud details to users
  riskThreshold: 50,        // 0-100
  autoDetectIp: true        // default: true
});

JavaScript SDK

Manual analysis

Want to decide what happens yourself? Call SurveyGuard.check() and branch on the result.

survey.js

const result = await SurveyGuard.check({
  email: 'user@example.com',
  userAgent: navigator.userAgent,
  answers: { question1: 'Answer 1', question2: 'Answer 2' }
});

if (result.riskLevel === 'HIGH') {
  // block the submission
} else if (result.riskLevel === 'MEDIUM') {
  // flag it for review
} else {
  // proceed normally
}

The result includes trustScore, riskLevel and flags. Use them for your own logic, but never show them to respondents.

Integrations

Custom forms & frameworks

Call the API from your own submit handler, then continue with your normal submission.

form.js

form.addEventListener('submit', async (e) => {
  e.preventDefault();
  const res = await fetch('https://api.surveyguard.com/v1/responses', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer YOUR_API_KEY'
    },
    body: JSON.stringify({
      email: form.email.value,
      userAgent: navigator.userAgent,
      answers: Object.fromEntries(new FormData(form))
    })
  });
  const { data } = await res.json();
  if (data.riskLevel === 'HIGH') return; // show a generic error
  // continue with your own submit...
});

SurveyForm.jsx

const handleSubmit = async (e) => {
  e.preventDefault();
  const res = await fetch('https://api.surveyguard.com/v1/responses', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer YOUR_API_KEY'
    },
    body: JSON.stringify({ email, userAgent: navigator.userAgent, answers: { name, email } })
  });
  const { data } = await res.json();
  if (data.riskLevel === 'HIGH') return; // show a generic error

  await fetch('/api/submit-survey', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ email, name, trustScore: data.trustScore })
  });
};

SurveyForm.vue

async handleSubmit() {
  const res = await fetch('https://api.surveyguard.com/v1/responses', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer YOUR_API_KEY'
    },
    body: JSON.stringify({
      email: this.email,
      userAgent: navigator.userAgent,
      answers: { name: this.name, email: this.email }
    })
  });
  const { data } = await res.json();
  if (data.riskLevel === 'HIGH') return; // show a generic error
  // submit to your backend...
}

Integrations

Server-side integration

The most robust option: check each response on your server before you save it.

server.js

app.post('/submit-survey', async (req, res) => {
  const { email, answers } = req.body;

  const check = await fetch('https://api.surveyguard.com/v1/responses', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${process.env.SURVEYGUARD_API_KEY}`
    },
    body: JSON.stringify({
      email,
      ipAddress: req.ip,
      userAgent: req.headers['user-agent'],
      answers
    })
  });
  const { data } = await check.json();

  if (data.riskLevel === 'HIGH') {
    return res.status(403).json({ error: 'Unable to process' });
  }
  // save the response...
  res.json({ success: true, trustScore: data.trustScore });
});

app.py

@app.route('/submit-survey', methods=['POST'])
def submit_survey():
    data = request.json
    result = requests.post(
        'https://api.surveyguard.com/v1/responses',
        headers={
            'Content-Type': 'application/json',
            'Authorization': f'Bearer {os.getenv("SURVEYGUARD_API_KEY")}'
        },
        json={
            'email': data.get('email'),
            'ipAddress': request.remote_addr,
            'userAgent': request.headers.get('User-Agent'),
            'answers': data.get('answers', {})
        }
    ).json()

    if result['data']['riskLevel'] == 'HIGH':
        return jsonify({'error': 'Unable to process'}), 403
    # save the response...
    return jsonify({'success': True, 'trustScore': result['data']['trustScore']})

submit.php

$payload = [
    'email'     => $_POST['email'],
    'ipAddress' => $_SERVER['REMOTE_ADDR'] ?? '',
    'userAgent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
    'answers'   => $_POST
];

$ch = curl_init('https://api.surveyguard.com/v1/responses');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Authorization: Bearer ' . getenv('SURVEYGUARD_API_KEY')
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);

if ($result['data']['riskLevel'] === 'HIGH') {
    die(json_encode(['error' => 'Unable to process']));
}
// save the response...

Keep your API key on the server. Read it from an environment variable such as SURVEYGUARD_API_KEY.

Integrations

Survey platforms

Platform How to connect
Typeform
Settings → Integrations → add a webhook, then call SurveyGuard from your webhook handler.
Google Forms
Add an Apps Script onSubmit trigger that sends each response to the API.
WordPress · Contact Form 7
Listen for the wpcf7mailsent event and send the form data.
Wufoo
Form Settings → Webhooks → add your backend URL and process it like the Typeform example.

webhook.js

app.post('/typeform-webhook', async (req, res) => {
  const answers = req.body.form_response.answers;
  const email = answers.find(a => a.type === 'email')?.email;

  await fetch('https://api.surveyguard.com/v1/responses', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${process.env.SURVEYGUARD_API_KEY}`
    },
    body: JSON.stringify({
      email, ipAddress: req.ip, userAgent: req.headers['user-agent'], answers
    })
  });
  res.sendStatus(200);
});

Code.gs

function onSubmit(e) {
  const response = e.response;
  const payload = {
    email: response.getRespondentEmail(),
    userAgent: 'Google Forms',
    answers: response.getItemResponses().map(a => ({
      question: a.getItem().getTitle(),
      answer: a.getResponse()
    }))
  };
  UrlFetchApp.fetch('https://api.surveyguard.com/v1/responses', {
    method: 'POST',
    headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
    contentType: 'application/json',
    payload: JSON.stringify(payload)
  });
}

footer.js

document.addEventListener('wpcf7mailsent', async (event) => {
  const formData = new FormData(event.target);
  await fetch('https://api.surveyguard.com/v1/responses', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer YOUR_API_KEY'
    },
    body: JSON.stringify({
      email: formData.get('your-email'), // adjust the field name
      userAgent: navigator.userAgent,
      answers: Object.fromEntries(formData)
    })
  });
});

Reference

API reference

POST

/v1/responses

Analyzes a single survey response and returns its Trust Score, risk level and flags.

Headers

POST /v1/responses
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json

Request body

Field Type Description
email
string
The respondent’s email address.
ipAddress
string
Optional. Detected automatically when omitted.
userAgent
string
Optional. The respondent’s browser user agent.
answers
object
The survey answers, keyed by question.

Request

{
  "email": "user@example.com",
  "ipAddress": "8.8.8.8",
  "userAgent": "Mozilla/5.0 ...",
  "answers": {
    "question1": "Answer 1",
    "question2": "Answer 2"
  }
}

Response · 200

{
  "success": true,
  "data": {
    "trustScore": 85,
    "riskLevel": "LOW",
    "flags": [],
    "details": {
      "emailValidation": { ... },
      "ipReputation": { ... }
    },
    "responseId": "uuid-here"
  }
}

Reference

Risk levels & flags

Every response gets a Trust Score from 0 to 100 and one of three risk levels.

Risk level Trust Score Suggested action
LOW
80 or higher
Accept the response.
MEDIUM
50 – 79
Flag it for review.
HIGH
Below 50
Block it, or exclude it from your results.

Flags

The flags array explains why a response scored the way it did. The most common ones:

Flag Meaning
EMAIL_INVALID
Invalid email format
EMAIL_DISPOSABLE
Disposable email address
EMAIL_SPAMTRAP
Spam trap detected
IP_ANONYMIZER
Proxy, VPN or Tor detected
IP_HIGH_RISK
High fraud score for the IP address

All flags by category:

Category Flags
Email
EMAIL_INVALID EMAIL_DISPOSABLE EMAIL_SPAMTRAP EMAIL_HONEYPOT EMAIL_RECENT_ABUSE EMAIL_FREQUENT_COMPLAINER EMAIL_HIGH_RISK EMAIL_MEDIUM_RISK
Network & IP
IP_ANONYMIZER IP_ACTIVE_ANONYMIZER IP_HIGH_RISK IP_MEDIUM_RISK IP_REPUTATION_HIGH_RISK IP_RECENT_ABUSE IP_FREQUENT_ABUSER IP_ATTACK_HISTORY IP_BOT_DETECTED IP_CRAWLER IP_SHARED_CONNECTION IP_HIGH_ABUSE_VELOCITY
Device
DEVICE_BOT DEVICE_CRAWLER DEVICE_EMULATOR_OR_SPOOF DEVICE_ACTIVE_ANONYMIZER DEVICE_NOT_UNIQUE DEVICE_RECENT_ABUSE DEVICE_HIGH_RISK DEVICE_MEDIUM_RISK
Behavior
BEHAVIOR_BOT_LIKE BEHAVIOR_FAST_SUBMISSION BEHAVIOR_SPEED_SUBMISSION BEHAVIOR_NO_MOUSE BEHAVIOR_NO_TYPING BEHAVIOR_NO_SCROLL BEHAVIOR_NO_FIELD_NAVIGATION BEHAVIOR_EXCESSIVE_PASTE BEHAVIOR_BURST_ACTIVITY
Velocity
VELOCITY_EMAIL_DUPLICATE VELOCITY_EMAIL_HIGH VELOCITY_EMAIL_VERY_HIGH VELOCITY_IP_MODERATE VELOCITY_IP_HIGH VELOCITY_IP_VERY_HIGH VELOCITY_DEVICE_MODERATE VELOCITY_DEVICE_HIGH VELOCITY_DEVICE_VERY_HIGH
Answer quality
OPEN_TEXT_GIBBERISH OPEN_TEXT_LOW_QUALITY STRAIGHT_LINING

Guides

Best practices

Privacy by design. Scores, flags and risk levels are only visible in your dashboard. High-risk respondents get a generic “Unable to process” message.

Help

Need a hand?

Our team can help you plan an integration or debug a tricky setup.

Scroll to Top