SpeedOf.Me API - Vue.js Integration

This example demonstrates how to integrate the SpeedOf.Me speed test API with Vue.js 3.

Live Demo

A working example built on the Vue 3 CDN build is linked from this folder's page. Opening the source file directly will not run a test: the API validates the page URL against your registered domain, so serve your copy over http or https from that domain.

Prerequisites

Quick Start

Option 1: CDN (for quick prototyping)

The index.html file shows how to use Vue 3 with the CDN build. Great for demos.

Option 2: Vite + Vue (recommended for production)

  1. Create a new Vue project:
    npm create vite@latest my-speedtest -- --template vue
    cd my-speedtest
    npm install
  2. Add the API script to index.html:
    <script src="https://speedof.me/api/api.js"></script>
  3. Create the composable (src/composables/useSpeedTest.js):
    import { ref, onMounted } from 'vue';
    
    export function useSpeedTest({ apiKey, domain, sustainTime = 6 }) {
        const status = ref('idle');
        const result = ref(null);
        const progress = ref(null);
        const error = ref(null);
    
        onMounted(() => {
            window.SomApi.account = apiKey;
            window.SomApi.domainName = domain;
            window.SomApi.config.sustainTime = sustainTime;
    
            window.SomApi.onTestCompleted = (testResult) => {
                result.value = testResult;
                progress.value = null;
                status.value = 'completed';
            };
    
            window.SomApi.onProgress = (data) => {
                progress.value = data;
            };
    
            window.SomApi.onError = (err) => {
                error.value = err;
                status.value = 'error';
            };
        });
    
        function startTest() {
            status.value = 'running';
            result.value = null;
            error.value = null;
            window.SomApi.startTest();
        }
    
        return { status, result, progress, error, startTest };
    }
  4. Use in your component (src/components/SpeedTest.vue):
    <script setup>
    import { useSpeedTest } from '../composables/useSpeedTest';
    
    const { status, result, progress, error, startTest } = useSpeedTest({
        apiKey: 'YOUR_API_KEY',
        domain: 'your-domain.com'
    });
    </script>
    
    <template>
        <div>
            <button @click="startTest" :disabled="status === 'running'">
                {{ status === 'running' ? 'Testing...' : 'Start Test' }}
            </button>
    
            <div v-if="result">
                <p>Download: {{ result.download }} Mbps</p>
                <p>Upload: {{ result.upload }} Mbps</p>
            </div>
        </div>
    </template>

Configuration

// Required
window.SomApi.account = 'YOUR_API_KEY';
window.SomApi.domainName = 'your-domain.com';

// Optional
window.SomApi.config.sustainTime = 6;        // 1-8 seconds
window.SomApi.config.testServerEnabled = true;
window.SomApi.config.userInfoEnabled = true;
window.SomApi.config.latencyTestEnabled = true;
window.SomApi.config.uploadTestEnabled = true;
window.SomApi.config.progress.enabled = true;   // fire onProgress during the test
window.SomApi.config.progress.verbose = true;   // add currentSpeed and maxSpeed to it

Handling Results

The onTestCompleted callback receives a result object:

{
    download: 150.5,      // Download speed in Mbps
    upload: 25.3,         // Upload speed in Mbps ('' if uploadTestEnabled is false)
    maxDownload: 162.0,   // Peak download speed in Mbps
    maxUpload: 27.1,      // Peak upload speed in Mbps ('' if uploadTestEnabled is false)
    latency: 12,          // Latency in ms ('' if latencyTestEnabled is false)
    jitter: 3,            // Jitter in ms, whole number ('' if latencyTestEnabled is false)
    testServer: 'Los Angeles 3', // Test server location ('' if testServerEnabled is false)
    ip_address: '...',    // Client IP ('0.0.0.0' if userInfoEnabled is false)
    hostname: '...',     // Client hostname ('' if userInfoEnabled is false)
    userAgent: '...',    // Browser user agent string
    testDate: '...'      // Test timestamp, ISO 8601
}

Every field is always present. Disabling a test blanks its fields rather than removing them.

Progress Updates

The onProgress callback receives progress data:

{
    type: 'download',     // 'latency', 'download' or 'upload'
    percentDone: 75,      // 0-100
    pass: 3,              // Current test pass ('' during the latency phase)
    currentSpeed: 145.2,  // Current speed in Mbps, verbose mode only: '' unless
                          // config.progress.verbose is true, and always ''
                          // on latency events
    maxSpeed: 162.0,      // Peak speed in Mbps, same rule as currentSpeed
    latency: '',          // Latency in ms, only on the final latency event
                          // (type 'latency' at percentDone 100), '' otherwise
    jitter: ''           // Jitter in ms, same rule as latency
}

Guard currentSpeed before formatting it, because the latency phase carries '':

const speed = typeof progress.currentSpeed === 'number'
    ? `${progress.currentSpeed.toFixed(1)} Mbps`
    : '';

Error Handling

{
    code: 1001,
    message: 'User data error: Invalid Account'
}

Error codes:

Code 2006, and 2005 with status 0, mean the request never left the browser, which is almost always an ad blocker, a content blocker or a privacy extension on the visitor's device. The one thing to check on your own side is a frame-src Content-Security-Policy: it must allow https://speedof.me, or the engine iframe can never load. A 2005 carrying any other status is a real HTTP response, so treat it as a server-side failure.

Options API Alternative

If you prefer the Options API:

<script>
export default {
    data() {
        return {
            status: 'idle',
            result: null,
            progress: null,
            error: null
        };
    },
    mounted() {
        window.SomApi.account = 'YOUR_API_KEY';
        window.SomApi.domainName = 'your-domain.com';

        window.SomApi.onTestCompleted = (result) => {
            this.result = result;
            this.status = 'completed';
        };

        window.SomApi.onProgress = (data) => {
            this.progress = data;
        };

        window.SomApi.onError = (err) => {
            this.error = err;
            this.status = 'error';
        };
    },
    methods: {
        startTest() {
            this.status = 'running';
            window.SomApi.startTest();
        }
    }
};
</script>

TypeScript Support

For TypeScript projects, see the React example's TypeScript section for type definitions that work with Vue as well.

Production Considerations

  1. API Key Security: Use environment variables via Vite's import.meta.env.VITE_API_KEY.
  2. Loading State: Consider using onMounted to check if window.SomApi exists.
  3. Pinia Integration: For larger apps, consider storing test results in a Pinia store.

Links