ViewsAPI Documentation: Integrating Tracking

Welcome to ViewsAPI! Our goal is to provide simple, privacy-focused website analytics. Integrating ViewsAPI is designed to be straightforward by adding a small tracking script to your website.

This guide explains how to add the ViewsAPI tracking code to your website to start collecting visitor data, including optional tracking for your logged-in users.

1. How Tracking Works (Client-Side)

ViewsAPI works by using a small client-side JavaScript snippet. This is key: the actual tracking happens in your visitor's web browser, not directly on your server.

Here's the process:

  1. Your Server Sends HTML: Your website (built with PHP, Node, Python, static HTML, etc.) sends the HTML page to the visitor's browser.
  2. Browser Finds Script: The browser reads the HTML and finds our <script> tag.
  3. Browser Runs Script: The browser downloads and executes the JavaScript from our servers (public-call/).
  4. Data Collection: The script gathers anonymous data directly from the browser (page URL, referrer, screen size, language, country, etc.).
  5. Visitor ID: It generates or retrieves a unique, anonymous visitor ID using the browser's localStorage. This avoids traditional third-party cookies.
  6. Data Transmission: The script sends this collected data, along with your Website ID (and optional logged-in user info), directly from the visitor's browser to ViewsAPI's secure tracking endpoint.

Because the tracking intelligence is in the client-side JavaScript, the integration method for you is always the same: Ensure the <script> tag is included in the HTML your site generates. How you achieve that depends on your specific backend technology or framework, as shown in the examples below.

2. Getting Started: Your Website ID ("webid")

Before integrating, you need your unique Website ID (we call it `webid`) from ViewsAPI. This links the collected data to your specific website in our system.

  1. Sign up / Log in: Access your account at viewsapi.amandevelops.com/login/ (or sign up if you're new).
  2. Add Your Website: Navigate to the "Add Website" section (viewsapi.amandevelops.com/add-website/) and fill in your website's domain and other required information.
    Note: Currently, each `webid` is valid for one specific domain only. Subdomains (e.g., `blog.example.com` vs `www.example.com`) require separate website entries and unique `webid`s.
  3. Find Your `webid`: Once your site is added, go to your Dashboard (viewsapi.amandevelops.com/dashboard/). Select your website to view its analytics. Your unique `webid` (e.g., your-unique-site-id-123) will be displayed there, usually alongside the tracking code snippet.

Copy this `webid` – you'll need it for the script tag.

3. The Tracking Code Snippet

This is the HTML code you need to add to your website. Choose the snippet that fits your needs.

Basic Tracking

For standard anonymous visitor tracking:

<!-- Script for ViewsAPI -->
<script src="https://viewsapi.amandevelops.com/v1/public-call/?id=YOUR_WEBSITE_ID" async></script>

Replace YOUR_WEBSITE_ID with your actual webid.

Tracking Logged-in Users (Optional)

If your website has a user login system, you can optionally associate page views with your internal user identifiers. This helps you understand how specific registered users interact with your site.

To do this, add the user and optionally name parameters to the script URL:

<!-- Script for ViewsAPI (Tracking Logged-in User) -->
<script src="https://viewsapi.amandevelops.com/v1/public-call/?id=YOUR_WEBSITE_ID&user=USER_ID&name=USER_DISPLAY_NAME" async></script>

Parameter Details:

  • id=YOUR_WEBSITE_ID: Required. Your specific webid.
  • user=USER_ID: Optional. Provide a unique, non-personally identifiable ID for the logged-in user (e.g., a database ID like 12345, a UUID like a1b2c3d4-e5f6...). Do NOT use sensitive information like email addresses or usernames here.
  • name=USER_DISPLAY_NAME: Optional. Provide a display name or reference for the user (e.g., "John Doe", "AdminUser"). This is purely for your reference in the ViewsAPI interface. Remember to URL-encode the name if it contains spaces or special characters (most backend frameworks handle this automatically when building URLs).

Important: You only add the user and name parameters if the visitor is actually logged in. Your backend code needs to conditionally add these parameters to the URL string. See examples below.

Attribute Explanation:

  • <script ...>: Standard HTML tag to load external JavaScript.
  • src="...": The URL to the ViewsAPI tracking script including your specific parameters.
  • async: This attribute is important! It tells the browser to download the script without pausing the HTML parsing, and execute it as soon as it's ready. This prevents the script from slowing down your page load time.

4. Where to Place the Code

You should place the tracking code snippet once on every page you want to track.

The recommended place is inside the <head> section of your HTML document:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Your Website Title</title>

    <!-- Other meta tags, CSS links, etc. -->

    <!-- Script for ViewsAPI - Place it here -->
    <script src="https://viewsapi.amandevelops.com/v1/public-call/?id=YOUR_WEBSITE_ID" async></script>
    <!-- OR -->
    <!-- <script src="https://viewsapi.amandevelops.com/v1/public-call/?id=YOUR_WEBSITE_ID&user=USER_ID&name=USER_DISPLAY_NAME" async></script> -->

</head>
<body>
    <!-- Your website content -->
</body>
</html>

Alternatively, you can place it just before the closing </body> tag. However, placing it in the <head> with async ensures tracking starts as early as possible without blocking page rendering.

5. Integration Examples (Step-by-Step)

Remember, the goal is always to get the correct <script> tag into the final HTML sent to the browser. Here’s how you might do that using various technologies. Replace placeholders like YOUR_WEBSITE_ID, USER_ID, USER_DISPLAY_NAME with actual values or variables from your application.

A. Static HTML Websites

Directly edit your .html files and paste the script tag into the <head> section.

<!-- In your index.html, about.html, etc. -->
<head>
    <title>My Static Site</title>
    <!-- ... other tags ... -->

    <!-- Basic Tracking -->
    <script src="https://viewsapi.amandevelops.com/v1/public-call/?id=YOUR_WEBSITE_ID" async></script>
    <!-- NOTE: Cannot easily track logged-in users dynamically on purely static sites -->
</head>

B. Backend Frameworks / Server-Side Generated Sites

These examples show how to dynamically insert the script, including conditional logic for logged-in users.

PHP (Plain)

Use PHP variables and conditional logic to build the script URL.

<?php
$viewsApiWebsiteId = 'YOUR_WEBSITE_ID'; // Load from config ideally

// --- Check if user is logged in (Example logic) ---
session_start(); // Example session usage
$loggedInUserId = $_SESSION['user_id'] ?? null; // e.g., 12345
$loggedInUserName = $_SESSION['user_name'] ?? null; // e.g., "Jane Doe"
// ------------------------------------------------

$scriptSrc = 'https://viewsapi.amandevelops.com/v1/public-call/?id=' . htmlspecialchars($viewsApiWebsiteId, ENT_QUOTES, 'UTF-8');

// Append user parameters if logged in
if ($loggedInUserId !== null) {
    $scriptSrc .= '&user=' . urlencode($loggedInUserId); // Ensure ID is URL safe
    if ($loggedInUserName !== null) {
        $scriptSrc .= '&name=' . urlencode($loggedInUserName); // Ensure name is URL safe
    }
}
?>
<!DOCTYPE html>
<html>
<head>
    <title>PHP Site</title>
    <!-- Output the final script tag -->
    <script src="<?php echo $scriptSrc; ?>" async></script>
</head>
<body><!-- Content --></body>
</html>

PHP (Laravel Framework)

Edit your main Blade layout (e.g., resources/views/layouts/app.blade.php). Use config values and auth helpers.

<!-- In resources/views/layouts/app.blade.php -->
@php
    $viewsApiWebsiteId = config('services.viewsapi.website_id'); // Get ID from config/services.php
    $scriptSrc = '';
    if ($viewsApiWebsiteId) {
        $scriptSrc = 'https://viewsapi.amandevelops.com/v1/public-call/?id=' . e($viewsApiWebsiteId);

        if (Auth::check()) { // Check if user is logged in
            $user = Auth::user();
            $scriptSrc .= '&user=' . urlencode($user->id); // Use user's primary key (e.g., id)
            if (!empty($user->name)) { // Assuming a 'name' attribute exists
                 $scriptSrc .= '&name=' . urlencode($user->name);
            }
        }
    }
@endphp
<!DOCTYPE html>
<html>
<head>
    <title>Laravel Site</title>
    <!-- Output the script tag -->
    @if($scriptSrc)
        <script src="{{ $scriptSrc }}" async></script>
    @endif
</head>
<body>@yield('content')</body>
</html>

Make sure to add your website_id to your config/services.php file:

// config/services.php
return [
    // ... other services
    'viewsapi' => [
        'website_id' => env('VIEWS_API_WEBSITE_ID', 'YOUR_DEFAULT_ID_IF_ANY'),
    ],
];

And set the `VIEWS_API_WEBSITE_ID` in your `.env` file.

Node.js (Express Framework - EJS Templates)

Pass data from your route handler to the EJS template via the context object.

// In your Express route (e.g., routes/index.js)
router.get('/', function(req, res, next) {
  const viewsApiWebsiteId = process.env.VIEWS_API_WEBSITE_ID || 'YOUR_WEBSITE_ID';
  let scriptSrc = null;

  if (viewsApiWebsiteId) {
      scriptSrc = `https://viewsapi.amandevelops.com/v1/public-call/?id=${encodeURIComponent(viewsApiWebsiteId)}`;

      // Example: Check if user is logged in (using Passport.js session)
      if (req.isAuthenticated && req.isAuthenticated()) {
        const userId = req.user.id; // Assuming user object has an id
        const userName = req.user.displayName || req.user.username; // Use a display name or username
        scriptSrc += `&user=${encodeURIComponent(userId)}`;
        if (userName) {
            scriptSrc += `&name=${encodeURIComponent(userName)}`;
        }
      }
  }

  res.render('index', {
    title: 'Express Site',
    viewsApiScriptSrc: scriptSrc // Pass final URL string to template
  });
});
<!-- In your EJS layout (e.g., views/layout.ejs) -->
<!DOCTYPE html>
<html>
<head>
    <title><%= title %></title>
    <% if (typeof viewsApiScriptSrc !== 'undefined' && viewsApiScriptSrc) { %>
        <script src="<%- viewsApiScriptSrc %>" async></script> <!-- Use <%- for unescaped output -->
    <% } %>
</head>
<body><%- body %></body>
</html>

Python (Flask Framework - Jinja2 Templates)

Build the script URL in your route and pass it to the Jinja2 template.

# In your Flask app.py or views.py
from flask import Flask, render_template, session # Example using session
import os
import urllib.parse

app = Flask(__name__)
app.secret_key = 'your secret key' # Needed for session
VIEWS_API_WEBSITE_ID = os.environ.get('VIEWS_API_WEBSITE_ID', 'YOUR_WEBSITE_ID')

@app.route('/')
def index():
    script_src = None
    if VIEWS_API_WEBSITE_ID:
        params = {'id': VIEWS_API_WEBSITE_ID}

        # Example: Check session for logged-in user
        if 'user_id' in session:
            params['user'] = str(session['user_id']) # Ensure string
            if 'user_name' in session:
                params['name'] = session['user_name']

        query_string = urllib.parse.urlencode(params)
        script_src = f"https://viewsapi.amandevelops.com/v1/public-call/?{query_string}"

    return render_template('base.html', views_api_script_src=script_src)
<!-- In templates/base.html -->
<!DOCTYPE html>
<html>
<head>
    <title>Flask Site</title>
    {% if views_api_script_src %}
    <script src="{{ views_api_script_src }}" async></script>
    {% endif %}
</head>
<body>{% block content %}{% endblock %}</body>
</html>

Python (Django Framework - Django Templates)

Use Django settings and authentication context in your view or a context processor.

# In your Django views.py or a context_processors.py
from django.conf import settings
import urllib.parse

def viewsapi_context(request): # Example context processor
    context = {'views_api_script_src': None}
    views_api_website_id = getattr(settings, 'VIEWS_API_WEBSITE_ID', None)

    if views_api_website_id:
        params = {'id': views_api_website_id}

        # Example: Check Django's authentication system
        if request.user.is_authenticated:
            params['user'] = str(request.user.pk) # Use primary key
            display_name = request.user.get_full_name() or request.user.username
            if display_name:
                params['name'] = display_name

        query_string = urllib.parse.urlencode(params)
        context['views_api_script_src'] = f"https://viewsapi.amandevelops.com/v1/public-call/?{query_string}"

    return context

# Remember to add your context processor to TEMPLATES['OPTIONS']['context_processors'] in settings.py
<!-- In templates/base.html -->
<!DOCTYPE html>
<html>
<head>
    <title>Django Site</title>
    {% if views_api_script_src %}
    <script src="{{ views_api_script_src }}" async></script>
    {% endif %}
</head>
<body>{% block content %}{% endblock %}</body>
</html>

Ruby on Rails (ERB Templates)

Create a helper method to generate the script source URL.

# In app/helpers/application_helper.rb (or a specific helper)
module ApplicationHelper
  def views_api_script_src
    website_id = ENV['VIEWS_API_WEBSITE_ID']
    return nil unless website_id.present?

    params = { id: website_id }
    if user_signed_in? # Assumes Devise or similar authentication
      params[:user] = current_user.id.to_s
      # Add name if available, e.g., current_user.name or current_user.email
      user_name = current_user.try(:name) || current_user.try(:email)
      params[:name] = user_name if user_name.present?
    end

    "https://viewsapi.amandevelops.com/v1/public-call/?#{params.to_query}"
  end
end
<!-- In app/views/layouts/application.html.erb -->
<!DOCTYPE html>
<html>
<head>
  <title>Rails App</title>
  <%= csrf_meta_tags %>
  <%= csp_meta_tag %>
  <%= stylesheet_link_tag 'application', media: 'all' %>
  <%= javascript_pack_tag 'application' %>

  <%# ViewsAPI Script %>
  <% script_src = views_api_script_src %>
  <% if script_src %>
    <script src="<%= script_src %>" async></script>
  <% end %>
</head>
<body>
  <%= yield %>
</body>
</html>

Java (Spring Boot with Thymeleaf)

Build the URL in your controller and pass it to the Thymeleaf template model.

// In your Spring Controller
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.StringJoiner;
import java.util.Objects;

@Controller
public class HomeController {

    @Value("${viewsapi.website.id:}") // Load from application.properties
    private String viewsApiWebsiteId;

    @GetMapping("/")
    public String home(Model model, Authentication authentication) {
        if (viewsApiWebsiteId != null && !viewsApiWebsiteId.isEmpty()) {
            StringJoiner queryParams = new StringJoiner("&");
            queryParams.add("id=" + encodeValue(viewsApiWebsiteId));

            // Example check for logged-in user (Spring Security)
            if (authentication != null && authentication.isAuthenticated()) {
                 Object principal = authentication.getPrincipal();
                 if (principal instanceof UserDetails) {
                    UserDetails user = (UserDetails) principal;
                    // Use username or a custom ID field from your UserDetails implementation
                    String userId = user.getUsername();
                    queryParams.add("user=" + encodeValue(userId));

                    // Add name if available from UserDetails (e.g., a getDisplayName() method)
                    // String name = user.getDisplayName();
                    // if(name != null && !name.isEmpty()){
                    //    queryParams.add("name=" + encodeValue(name));
                    // }
                 } else {
                     // Handle other principal types if necessary
                     String userId = principal.toString(); // Fallback
                     queryParams.add("user=" + encodeValue(userId));
                 }
            }
            String scriptSrc = "https://viewsapi.amandevelops.com/v1/public-call/?" + queryParams.toString();
            model.addAttribute("viewsApiScriptSrc", scriptSrc);
        }
        return "index"; // Renders src/main/resources/templates/index.html
    }

    private String encodeValue(String value) {
        try {
            return URLEncoder.encode(value, StandardCharsets.UTF_8.toString());
        } catch (Exception e) {
            // Fallback or logging
            return value;
        }
    }
}
<!-- In src/main/resources/templates/index.html -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Spring Boot App</title>
    <!--/* ViewsAPI Script */-->
    <script th:if="${viewsApiScriptSrc}" th:src="${viewsApiScriptSrc}" async></script>
</head>
<body>
    <h1>Welcome</h1>
    <!-- Content -->
</body>
</html>

ASP.NET Core (Razor Pages / MVC)

Use configuration and user claims in your main layout file (`_Layout.cshtml`).

<!-- In Pages/Shared/_Layout.cshtml or Views/Shared/_Layout.cshtml -->
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration
@using System.Security.Claims
@using System.Net
@using System.Text

@{
    var viewsApiWebsiteId = Configuration["ViewsApi:WebsiteId"]; // Get from appsettings.json
    string scriptSrc = null;

    if (!string.IsNullOrEmpty(viewsApiWebsiteId))
    {
        var queryBuilder = new StringBuilder();
        queryBuilder.Append($"id={WebUtility.UrlEncode(viewsApiWebsiteId)}");

        // Example check for logged-in user
        if (User.Identity != null && User.Identity.IsAuthenticated)
        {
            var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); // Standard claim for user ID
            var name = User.Identity.Name; // Usually the username

            if (!string.IsNullOrEmpty(userId)) {
                queryBuilder.Append($"&user={WebUtility.UrlEncode(userId)}");
                if (!string.IsNullOrEmpty(name)) {
                     queryBuilder.Append($"&name={WebUtility.UrlEncode(name)}");
                }
            }
        }
        scriptSrc = $"https://viewsapi.amandevelops.com/v1/public-call/?{queryBuilder.ToString()}";
    }
}
<!DOCTYPE html>
<html>
<head>
    <title>ASP.NET Core App</title>
    @if (!string.IsNullOrEmpty(scriptSrc))
    {
        <script src="@scriptSrc" async></script>
    }
    @await RenderSectionAsync("Styles", required: false)
</head>
<body>
    @RenderBody()
    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>

Add your Website ID to `appsettings.json`:

{
  "Logging": { /*...*/ },
  "AllowedHosts": "*",
  "ViewsApi": {
    "WebsiteId": "YOUR_WEBSITE_ID"
  }
}

C. Frontend Frameworks / Single Page Applications (SPAs)

React / Vue / Angular

For SPAs, include the script tag once in the main `public/index.html` (or equivalent) file in the <head> section.

<!-- In public/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>My SPA</title>
    <!-- Basic Tracking (most common for SPAs, user details handled via API calls) -->
    <script src="https://viewsapi.amandevelops.com/v1/public-call/?id=YOUR_WEBSITE_ID" async></script>
</head>
<body><div id="root"></div></body> <!-- React example mount point -->
</html>

Tracking Logged-in Users in SPAs: Since index.html is static, you typically cannot dynamically insert the user and name parameters there based on login state. If you need to associate analytics with logged-in users in an SPA, contact support about potential future options for sending user data via a dedicated API call after login.

Our script automatically tracks page view changes using the History API in most SPAs. If you find that "virtual" page views within your SPA are not being tracked correctly, please contact support.

D. Content Management Systems (CMS)

WordPress

The easiest method is often using a plugin that allows adding scripts to the website header.

  1. Log in to your WordPress Admin dashboard.
  2. Go to Plugins > Add New.
  3. Search for "Insert Headers and Footers", "WPCode", or a similar plugin for adding code snippets.
  4. Install and activate a suitable plugin (e.g., WPCode – Insert Headers and Footers).
  5. Navigate to the plugin's settings page (e.g., Code Snippets > Header & Footer).
  6. Paste the basic ViewsAPI script tag into the "Header" section.
    <!-- Script for ViewsAPI -->
    <script src="https://viewsapi.amandevelops.com/v1/public-call/?id=YOUR_WEBSITE_ID" async></script>
  7. Save Changes.

Tracking Logged-in Users (Advanced): This typically requires custom PHP code. You would need to add code to your theme's functions.php file (or preferably, a custom plugin) that hooks into a WordPress action like wp_head. Inside the hook, you would check if a user is logged in using `is_user_logged_in()`, get their ID using `get_current_user_id()`, and dynamically echo the script tag with the added `user` and `name` parameters. This requires PHP development knowledge.

Other CMS (Shopify, Joomla, Drupal, etc.)

The principle is the same: Find the setting or template file within your CMS that allows you to add custom JavaScript or tracking codes to the <head> section of all pages.

  • Shopify: Go to Online Store > Themes > Actions > Edit code. Find the `theme.liquid` file and paste the basic script tag before the closing `` tag.
  • Joomla: Look for template settings or use extensions designed for adding custom code.
  • Drupal: Check theme settings or use modules like "Asset Injector".

Consult your specific CMS's documentation or community forums for the best way to inject header scripts. Implementing logged-in user tracking might require specific plugins or theme customization for that platform.

6. Verifying Your Integration

After adding the script:

  1. Save & Clear Cache: Save your changes. Clear any server-side, CMS, or CDN caches, and clear your browser cache for your website.
  2. Visit Your Site: Open your website in your browser. If testing logged-in tracking, ensure you are logged in.
  3. Check Dashboard: Log in to your ViewsAPI dashboard (viewsapi.amandevelops.com/dashboard/) and select your website. You should start seeing visitor data appear within a few minutes (it might not be instantaneous). If tracking logged-in users, look for associated `User ID` or `User Name` data points in relevant reports.
  4. Browser DevTools (Optional Technical Check):
    • Open your browser's developer tools (usually by pressing F12).
    • Go to the Network tab.
    • Refresh your page.
    • Filter the requests by typing `viewsapi` or `track`. Look for a request going to https://viewsapi.amandevelops.com/v1/track/.... If you see a 2xx status code (like 200 or 204), the tracking data was likely sent successfully. Click on the request to inspect its details, checking the "Headers" (specifically the Request URL) or "Payload" tab to ensure the `id`, `user`, and `name` parameters are being sent correctly.
    • Go to the Application (or Storage) tab, select Local Storage in the left panel, and click on your website's domain. You should see a key named _vsid with a long string value (this is the anonymous visitor ID).

If data isn't appearing, double-check that you replaced YOUR_WEBSITE_ID with your actual webid and that the script tag is present and correctly formatted in the HTML source code of your pages.

7. Privacy Considerations (GDPR)

  • Our Approach: ViewsAPI uses first-party localStorage, not third-party cookies, and aims for anonymous data collection. IP addresses are processed for geolocation but not stored long-term linked to the visitor ID.
  • Your Responsibility: You must ensure your website's overall privacy policy is accurate and informs users about the analytics tools used.
  • Logged-in User Tracking: Be extra cautious when sending user and name. Only send non-sensitive identifiers. Clearly state in your privacy policy if you associate analytics data with registered user accounts and ensure you have a legal basis (like explicit consent or legitimate interest, depending on your jurisdiction and data processing details) for doing so.
  • Consent: Depending on your location and how you use the data (especially if tracking logged-in users or combining data), you might still need user consent (e.g., via a cookie/privacy banner) before loading the tracking script. Consult with legal counsel familiar with data privacy regulations like GDPR or CCPA if you are unsure.

Read the ViewsAPI Privacy Policy (Coming Soon)

8. Need Help?

If you encounter any issues during integration or have questions, please don't hesitate to reach out:

We're here to help you get ViewsAPI running smoothly!