Spotify Ads Server-Side vs Client-Side | OpsBlu Docs

Spotify Ads Server-Side vs Client-Side

Comparison and implementation guidance for server-side and client-side Spotify tracking.

Overview

Spotify Ads primarily uses client-side pixel tracking, with server-side attribution available through promo codes and custom URL tracking.

Client-Side Tracking

Implementation

<script type="text/javascript">
(function(s,p,o,t,i,f,y){s['SpotifyPixelObject']=i;s[i]=s[i]||function(){
(s[i].q=s[i].q||[]).push(arguments)},s[i].l=1*new Date();f=p.createElement(o),
y=p.getElementsByTagName(o)[0];f.async=1;f.src=t;y.parentNode.insertBefore(f,y)
})(window,document,'script','https://pixel.spotify.com/v1/pixel.js','spotify');

spotify('init', 'PIXEL_ID');
spotify('track', 'PageView');
</script>

Advantages

  • Easy implementation
  • Automatic user tracking
  • Real-time attribution
  • No server infrastructure needed

Limitations

  • Ad blockers can block (20-40%)
  • Third-party cookie restrictions
  • Privacy compliance required

Server-Side Attribution

Promo Code Tracking

from flask import Flask, request
import time

app = Flask(__name__)

@app.route('/api/promo-code', methods=['POST'])
def track_promo_code():
    data = request.json
    code = data.get('code', '').upper()

    if code.startswith('SPOTIFY'):
        # Store attribution
        db.attributions.insert_one({
            'code': code,
            'source': 'spotify_audio_ad',
            'timestamp': time.time(),
            'user_id': data.get('user_id'),
            'order_id': data.get('order_id')
        })

        return {'status': 'success', 'source': 'spotify'}

    return {'status': 'invalid_code'}

Custom URL Tracking

// Server-side Node.js
const express = require('express');
const app = express();

app.get('/spotify-offer', (req, res) => {
  const utmSource = req.query.utm_source;
  const utmCampaign = req.query.utm_campaign;

  if (utmSource === 'spotify') {
    // Store attribution
    trackSpotifyAttribution({
      source: utmSource,
      campaign: utmCampaign,
      timestamp: Date.now(),
      ip: req.ip,
      userAgent: req.get('user-agent')
    });
  }

  res.render('landing-page');
});

Advantages

  • Bypasses ad blockers
  • Privacy-friendly
  • Offline conversion tracking
  • Full data control

Limitations

  • No automatic pixel tracking
  • Manual attribution setup required
  • Relies on promo codes or custom URLs

Implementation

// Client-side: Track with pixel
spotify('track', 'Purchase', {
  value: 99.99,
  order_id: 'ORDER_12345'
});

// Also send to server
fetch('/api/spotify/conversion', {
  method: 'POST',
  body: JSON.stringify({
    orderId: 'ORDER_12345',
    value: 99.99,
    promoCode: getPromoCode()
  })
});
# Server-side: Store for attribution
@app.route('/api/spotify/conversion', methods=['POST'])
def track_conversion():
    data = request.json

    db.conversions.insert_one({
        'order_id': data['order_id'],
        'value': data['value'],
        'promo_code': data.get('promo_code'),
        'source': determine_source(data.get('promo_code')),
        'timestamp': time.time()
    })

    return {'status': 'success'}

def determine_source(promo_code):
    if promo_code and promo_code.startswith('SPOTIFY'):
        return 'spotify_audio_ad'
    return 'organic'

Use Case Recommendations

Scenario Client-Side Server-Side Hybrid
Website conversions
Audio ad attribution
Promo code tracking
Offline sales
Real-time tracking

Best Practices

  • Use client-side pixel for website conversions
  • Implement promo codes for audio ad attribution
  • Track both pixel and promo codes for hybrid approach
  • Use unique promo codes per campaign
  • Monitor both attribution methods
  • Document attribution logic