Recherche avancée

Médias (1)

Mot : - Tags -/remix

Autres articles (34)

  • Personnaliser les catégories

    21 juin 2013, par

    Formulaire de création d’une catégorie
    Pour ceux qui connaissent bien SPIP, une catégorie peut être assimilée à une rubrique.
    Dans le cas d’un document de type catégorie, les champs proposés par défaut sont : Texte
    On peut modifier ce formulaire dans la partie :
    Administration > Configuration des masques de formulaire.
    Dans le cas d’un document de type média, les champs non affichés par défaut sont : Descriptif rapide
    Par ailleurs, c’est dans cette partie configuration qu’on peut indiquer le (...)

  • Les formats acceptés

    28 janvier 2010, par

    Les commandes suivantes permettent d’avoir des informations sur les formats et codecs gérés par l’installation local de ffmpeg :
    ffmpeg -codecs ffmpeg -formats
    Les format videos acceptés en entrée
    Cette liste est non exhaustive, elle met en exergue les principaux formats utilisés : h264 : H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 m4v : raw MPEG-4 video format flv : Flash Video (FLV) / Sorenson Spark / Sorenson H.263 Theora wmv :
    Les formats vidéos de sortie possibles
    Dans un premier temps on (...)

  • Ajouter notes et légendes aux images

    7 février 2011, par

    Pour pouvoir ajouter notes et légendes aux images, la première étape est d’installer le plugin "Légendes".
    Une fois le plugin activé, vous pouvez le configurer dans l’espace de configuration afin de modifier les droits de création / modification et de suppression des notes. Par défaut seuls les administrateurs du site peuvent ajouter des notes aux images.
    Modification lors de l’ajout d’un média
    Lors de l’ajout d’un média de type "image" un nouveau bouton apparait au dessus de la prévisualisation (...)

Sur d’autres sites (6513)

  • FFMPEG : sws_scale returns error : Slice parameters 0, 2160 are invalid

    21 janvier 2020, par Matthew Czarnek

    I’m trying to follow a tutorial to display ffmpeg AVFrame output in SDL. The tutorial(and all examples I’m seeing online) are still using ’sws_getContext’, which has been deprecated and removed from the newest version of ffmpeg. Trying to change current pixel format from whatever it currently is to PIX_FMT_YUV420P, so I can display it. I believe I need the sws_scale function to accomplish this.

    However, sws_scale is the function that causes a command line error of :
    Slice parameters 0, 2160 are invalid

    Here is all my code associate with swsContext :

    struct SwsContext* av_sws_ctx = NULL;
    av_sws_ctx = sws_alloc_context();

    sws_init_context(av_sws_ctx, NULL, NULL);

    sws_scale(av_sws_ctx, (uint8_t const* const*)av_frame->data,
                           av_frame->linesize, 0, av_codec_context->height,
                           av_frame->data, av_frame->linesize);

    Further complicating the matter, SwsContext is only defined internal to ffmpeg, externally I can’t set/get any variables or even view them in the debugger.

    int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[] )

    The vales of other parameters, other than av_sws_ctx :

    srcSlice: av_frame->data =
        8 arrays, first is filled with "\x10\x10\x10\x10\x10..."
        second and third are "€€€€€€€€€€€€€€€€€..."
        rest are NULL
    linesize(av_frame->linesize) is an array:
       3840,1920,1920,0,0,0,0,0
    srcSliceY:0
    srcSliceH:2160
    dest: same as second parameter (av_frame->data)
    dstStride: av_frame->linesize again

    If I drill into sws_scale source code, I find that this error is thrown by this chunk of code :

    if ((srcSliceY & (macro_height-1)) ||
           ((srcSliceH& (macro_height-1)) && srcSliceY + srcSliceH != c->srcH) ||
           srcSliceY + srcSliceH > c->srcH) {
           av_log(c, AV_LOG_ERROR, "Slice parameters %d, %d are invalid\n", srcSliceY, srcSliceH);
           return AVERROR(EINVAL);
       }

    I assume that the issue therefore is that the height of my video is bigger than sws_context(4k video). But can’t figure out how to tell sws_context what it’s height should be using sws_alloc_context or sws_init_context or any other function.

    See something I’m missing ? Thank you.

  • Can not add tmcd stream using libavcodec to replicate behavior of ffmpeg -timecode option

    2 août, par Sailor Jerry

    I'm trying to replicate option of command line ffmpeg -timecode in my C/C++ code. For some reasons the tcmd stream is not written to the output file. However the av_dump_format shows it in run time

    


    Here is my minimal test

    


    #include <iostream>&#xA;extern "C" {&#xA;#include <libavcodec></libavcodec>avcodec.h>&#xA;#include <libavformat></libavformat>avformat.h>&#xA;#include <libavutil></libavutil>avutil.h>&#xA;#include <libswscale></libswscale>swscale.h>&#xA;#include <libavutil></libavutil>opt.h>&#xA;#include <libavutil></libavutil>imgutils.h>&#xA;#include <libavutil></libavutil>samplefmt.h>&#xA;}&#xA;bool checkProResAvailability() {&#xA;  const AVCodec* codec = avcodec_find_encoder_by_name("prores_ks");&#xA;  if (!codec) {&#xA;    std::cerr &lt;&lt; "ProRes codec not available. Please install FFmpeg with ProRes support." &lt;&lt; std::endl;&#xA;    return false;&#xA;  }&#xA;  return true;&#xA;}&#xA;&#xA;int main(){&#xA;  av_log_set_level(AV_LOG_INFO);&#xA;&#xA;  const char* outputFileName = "test_tmcd.mov";&#xA;  AVFormatContext* formatContext = nullptr;&#xA;  AVCodecContext* videoCodecContext = nullptr;&#xA;&#xA;  if (!checkProResAvailability()) {&#xA;    return -1;&#xA;  }&#xA;&#xA;  std::cout &lt;&lt; "Creating test file with tmcd stream: " &lt;&lt; outputFileName &lt;&lt; std::endl;&#xA;&#xA;  // Allocate the output format context&#xA;  if (avformat_alloc_output_context2(&amp;formatContext, nullptr, "mov", outputFileName) &lt; 0) {&#xA;    std::cerr &lt;&lt; "Failed to allocate output context!" &lt;&lt; std::endl;&#xA;    return -1;&#xA;  }&#xA;&#xA;  if (avio_open(&amp;formatContext->pb, outputFileName, AVIO_FLAG_WRITE) &lt; 0) {&#xA;    std::cerr &lt;&lt; "Failed to open output file!" &lt;&lt; std::endl;&#xA;    avformat_free_context(formatContext);&#xA;    return -1;&#xA;  }&#xA;&#xA;  // Find ProRes encoder&#xA;  const AVCodec* videoCodec = avcodec_find_encoder_by_name("prores_ks");&#xA;  if (!videoCodec) {&#xA;    std::cerr &lt;&lt; "Failed to find the ProRes encoder!" &lt;&lt; std::endl;&#xA;    avio_close(formatContext->pb);&#xA;    avformat_free_context(formatContext);&#xA;    return -1;&#xA;  }&#xA;&#xA;  // Video stream setup&#xA;  AVStream* videoStream = avformat_new_stream(formatContext, nullptr);&#xA;  if (!videoStream) {&#xA;    std::cerr &lt;&lt; "Failed to create video stream!" &lt;&lt; std::endl;&#xA;    avio_close(formatContext->pb);&#xA;    avformat_free_context(formatContext);&#xA;    return -1;&#xA;  }&#xA;&#xA;  videoCodecContext = avcodec_alloc_context3(videoCodec);&#xA;  if (!videoCodecContext) {&#xA;    std::cerr &lt;&lt; "Failed to allocate video codec context!" &lt;&lt; std::endl;&#xA;    avio_close(formatContext->pb);&#xA;    avformat_free_context(formatContext);&#xA;    return -1;&#xA;  }&#xA;&#xA;  videoCodecContext->width = 1920;&#xA;  videoCodecContext->height = 1080;&#xA;  videoCodecContext->pix_fmt = AV_PIX_FMT_YUV422P10;&#xA;  videoCodecContext->time_base = (AVRational){1, 30}; // Set FPS: 30&#xA;  videoCodecContext->bit_rate = 2000000;&#xA;&#xA;  if (avcodec_open2(videoCodecContext, videoCodec, nullptr) &lt; 0) {&#xA;    std::cerr &lt;&lt; "Failed to open ProRes codec!" &lt;&lt; std::endl;&#xA;    avcodec_free_context(&amp;videoCodecContext);&#xA;    avio_close(formatContext->pb);&#xA;    avformat_free_context(formatContext);&#xA;    return -1;&#xA;  }&#xA;&#xA;  if (avcodec_parameters_from_context(videoStream->codecpar, videoCodecContext) &lt; 0) {&#xA;    std::cerr &lt;&lt; "Failed to copy codec parameters to video stream!" &lt;&lt; std::endl;&#xA;    avcodec_free_context(&amp;videoCodecContext);&#xA;    avio_close(formatContext->pb);&#xA;    avformat_free_context(formatContext);&#xA;    return -1;&#xA;  }&#xA;&#xA;  videoStream->time_base = videoCodecContext->time_base;&#xA;&#xA;  // Timecode stream setup&#xA;  AVStream* timecodeStream = avformat_new_stream(formatContext, nullptr);&#xA;  if (!timecodeStream) {&#xA;    std::cerr &lt;&lt; "Failed to create timecode stream!" &lt;&lt; std::endl;&#xA;    avcodec_free_context(&amp;videoCodecContext);&#xA;    avio_close(formatContext->pb);&#xA;    avformat_free_context(formatContext);&#xA;    return -1;&#xA;  }&#xA;&#xA;  timecodeStream->codecpar->codec_type = AVMEDIA_TYPE_DATA;&#xA;  timecodeStream->codecpar->codec_id = AV_CODEC_ID_TIMED_ID3;&#xA;  timecodeStream->codecpar->codec_tag = MKTAG(&#x27;t&#x27;, &#x27;m&#x27;, &#x27;c&#x27;, &#x27;d&#x27;); // Timecode tag&#xA;  timecodeStream->time_base = (AVRational){1, 30}; // FPS: 30&#xA;&#xA;  if (av_dict_set(&amp;timecodeStream->metadata, "timecode", "00:00:30:00", 0) &lt; 0) {&#xA;    std::cerr &lt;&lt; "Failed to set timecode metadata!" &lt;&lt; std::endl;&#xA;    avcodec_free_context(&amp;videoCodecContext);&#xA;    avio_close(formatContext->pb);&#xA;    avformat_free_context(formatContext);&#xA;    return -1;&#xA;  }&#xA;&#xA;  // Write container header&#xA;  if (avformat_write_header(formatContext, nullptr) &lt; 0) {&#xA;    std::cerr &lt;&lt; "Failed to write file header!" &lt;&lt; std::endl;&#xA;    avcodec_free_context(&amp;videoCodecContext);&#xA;    avio_close(formatContext->pb);&#xA;    avformat_free_context(formatContext);&#xA;    return -1;&#xA;  }&#xA;&#xA;  // Encode a dummy video frame&#xA;  AVFrame* frame = av_frame_alloc();&#xA;  if (!frame) {&#xA;    std::cerr &lt;&lt; "Failed to allocate video frame!" &lt;&lt; std::endl;&#xA;    avcodec_free_context(&amp;videoCodecContext);&#xA;    avio_close(formatContext->pb);&#xA;    avformat_free_context(formatContext);&#xA;    return -1;&#xA;  }&#xA;&#xA;  frame->format = videoCodecContext->pix_fmt;&#xA;  frame->width = videoCodecContext->width;&#xA;  frame->height = videoCodecContext->height;&#xA;&#xA;  if (av_image_alloc(frame->data, frame->linesize, frame->width, frame->height, videoCodecContext->pix_fmt, 32) &lt; 0) {&#xA;    std::cerr &lt;&lt; "Failed to allocate frame buffer!" &lt;&lt; std::endl;&#xA;    av_frame_free(&amp;frame);&#xA;    avcodec_free_context(&amp;videoCodecContext);&#xA;    avio_close(formatContext->pb);&#xA;    avformat_free_context(formatContext);&#xA;    return -1;&#xA;  }&#xA;&#xA;  // Fill frame with black&#xA;  memset(frame->data[0], 0, frame->linesize[0] * frame->height); // Y plane&#xA;  memset(frame->data[1], 128, frame->linesize[1] * frame->height / 2); // U plane&#xA;  memset(frame->data[2], 128, frame->linesize[2] * frame->height / 2); // V plane&#xA;&#xA;  // Encode the frame&#xA;  AVPacket packet;&#xA;  av_init_packet(&amp;packet);&#xA;  packet.data = nullptr;&#xA;  packet.size = 0;&#xA;&#xA;  if (avcodec_send_frame(videoCodecContext, frame) == 0) {&#xA;    if (avcodec_receive_packet(videoCodecContext, &amp;packet) == 0) {&#xA;      packet.stream_index = videoStream->index;&#xA;      av_interleaved_write_frame(formatContext, &amp;packet);&#xA;      av_packet_unref(&amp;packet);&#xA;    }&#xA;  }&#xA;&#xA;  av_frame_free(&amp;frame);&#xA;&#xA;  // Write a dummy packet for the timecode stream&#xA;  AVPacket tmcdPacket;&#xA;  av_init_packet(&amp;tmcdPacket);&#xA;  tmcdPacket.stream_index = timecodeStream->index;&#xA;  tmcdPacket.flags |= AV_PKT_FLAG_KEY;&#xA;  tmcdPacket.data = nullptr; // Empty packet for timecode&#xA;  tmcdPacket.size = 0;&#xA;  tmcdPacket.pts = 0; // Set necessary PTS&#xA;  tmcdPacket.dts = 0;&#xA;  av_interleaved_write_frame(formatContext, &amp;tmcdPacket);&#xA;&#xA;  // Write trailer&#xA;  if (av_write_trailer(formatContext) &lt; 0) {&#xA;    std::cerr &lt;&lt; "Failed to write file trailer!" &lt;&lt; std::endl;&#xA;  }&#xA;&#xA;  av_dump_format(formatContext, 0, "test.mov", 1);&#xA;&#xA;  // Cleanup&#xA;  avcodec_free_context(&amp;videoCodecContext);&#xA;  avio_close(formatContext->pb);&#xA;  avformat_free_context(formatContext);&#xA;&#xA;  std::cout &lt;&lt; "Test file with timecode created successfully: " &lt;&lt; outputFileName &lt;&lt; std::endl;&#xA;&#xA;  return 0;&#xA;}&#xA;</iostream>

    &#xA;

    The code output is :

    &#xA;

    Creating test file with tmcd stream: test_tmcd.mov&#xA;[prores_ks @ 0x11ce05790] Autoselected HQ profile to keep best quality. It can be overridden through -profile option.&#xA;[mov @ 0x11ce04f20] Timestamps are unset in a packet for stream 0. This is deprecated and will stop working in the future. Fix your code to set the timestamps properly&#xA;[mov @ 0x11ce04f20] Encoder did not produce proper pts, making some up.&#xA;Output #0, mov, to &#x27;test.mov&#x27;:&#xA;  Metadata:&#xA;    encoder         : Lavf61.7.100&#xA;  Stream #0:0: Video: prores (HQ) (apch / 0x68637061), yuv422p10le, 1920x1080, q=2-31, 2000 kb/s, 15360 tbn&#xA;  Stream #0:1: Data: timed_id3 (tmcd / 0x64636D74)&#xA;      Metadata:&#xA;        timecode        : 00:00:30:00&#xA;Test file with timecode created successfully: test_tmcd.mov&#xA;

    &#xA;

    The ffprobe output is :

    &#xA;

    $ ffprobe  test_tmcd.mov&#xA;ffprobe version 7.1.1 Copyright (c) 2007-2025 the FFmpeg developers&#xA;  built with Apple clang version 16.0.0 (clang-1600.0.26.6)&#xA;  configuration: --prefix=/opt/homebrew/Cellar/ffmpeg/7.1.1_3 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags=&#x27;-Wl,-ld_classic&#x27; --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libaribb24 --enable-libbluray --enable-libdav1d --enable-libharfbuzz --enable-libjxl --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librist --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-videotoolbox --enable-audiotoolbox --enable-neon&#xA;  libavutil      59. 39.100 / 59. 39.100&#xA;  libavcodec     61. 19.101 / 61. 19.101&#xA;  libavformat    61.  7.100 / 61.  7.100&#xA;  libavdevice    61.  3.100 / 61.  3.100&#xA;  libavfilter    10.  4.100 / 10.  4.100&#xA;  libswscale      8.  3.100 /  8.  3.100&#xA;  libswresample   5.  3.100 /  5.  3.100&#xA;  libpostproc    58.  3.100 / 58.  3.100&#xA;Input #0, mov,mp4,m4a,3gp,3g2,mj2, from &#x27;test_tmcd.mov&#x27;:&#xA;  Metadata:&#xA;    major_brand     : qt  &#xA;    minor_version   : 512&#xA;    compatible_brands: qt  &#xA;    encoder         : Lavf61.7.100&#xA;  Duration: N/A, start: 0.000000, bitrate: N/A&#xA;  Stream #0:0[0x1]: Video: prores (HQ) (apch / 0x68637061), yuv422p10le, 1920x1080, 15360 tbn (default)&#xA;      Metadata:&#xA;        handler_name    : VideoHandler&#xA;        vendor_id       : FFMP&#xA;$ &#xA;&#xA;

    &#xA;

    Spent hours with all AI models, no help. Appeal to the human intelligence now

    &#xA;

  • Server-side tracking vs client-side tracking : What you need to know

    3 juillet, par Joe

    Server-side tracking vs client-side tracking : What you need to know

    Today, consumers are more aware of their online privacy rights, leading to an extensive use of ad blockers and stricter cookie policies. Organisations are facing some noteworthy challenges with this trend, including :

    • Limited data collection, which makes it harder to understand user behaviour and deliver personalised ads that resonate with customers
    • Rising compliance costs as businesses adapt to new regulations, straining resources and budgets.
    • Growing customer scepticism in data practices, affecting brand reputation.
    • Maintaining transparency and fostering trust with customers through clear communication about data practices.

    Server-side tracking can help resolve these problems. This article will cover server-side tracking, how it works, implementation methods and its benefits.

    What is server-side tracking ? 

    Server-side tracking refers to a method where user data is collected directly by a server rather than through a user’s browser.

    The key advantage of server-side tracking is that data collection, processing, and storage occur directly on the website’s server.

    For example, when a visitor interacts with any website, the server captures that activity through the backend system, allowing for greater data control and security. 

    Client-side tracking vs. server-side tracking 

    There are two methods to collect user data : client-side and server-side. 

    Let’s understand their differences. 

    Client-side tracking : Convenience with caveats

    Client-side tracking embeds JavaScript tags, pixels or other scripts directly into a website’s code. When a user interacts with the site, these tags fire, collecting data from their browser. This information might include page views, button clicks, form submissions and other user actions. 

    The collected data is then sent directly to third-party analytics platforms like Google Analytics or Adobe Analytics, or internal teams can also analyse it.

    This method is relatively easy to implement. That’s because marketers can often deploy these tags without needing extensive developer support, enabling quick adjustments and A/B testing. 

    However, there are some challenges. 

    Ad blockers and browser privacy settings, such as Intelligent Tracking Prevention (ITP), restrict the ability of third-party tags to collect data. 

    This results in data gaps and inaccuracies skewing analytics reports and potentially leading to misguided business decisions. 

    Reliance on numerous JavaScript tags can also negatively impact website performance, slowing down page load times and affecting user experience. This is especially true on mobile devices where processing power and network speeds are often limited.

    Am image illustrating the difference between client-server tracking and server-side tracking

    Now, let’s see how server-side tracking changes this.

    Server-side tracking : Control and reliability

    Server-side tracking shifts the burden of data collection from the user’s browser to a server controlled by the business. 

    Instead of relying on JavaScript tags firing directly from the user’s device, user interactions are first sent to the business’s own server. Here, the data can be processed, enriched, and analysed. 

    This method provides numerous advantages, including enhanced control over data integrity, improved privacy, and more, which we discuss in the next section.

    Benefits of server-side tracking 

    Server-side tracking offers a compelling alternative to traditional client-side methods, providing numerous business advantages. Let’s take a look at them.

    Improved data accuracy

    This method reduces inaccuracies caused by ad blockers or cookie restrictions by bypassing browser limitations. As a result, the data collected is more reliable, leading to better analytics and marketing attribution.

    Data minimisation

    Data minimisation is a fundamental principle in data protection. It emphasises that organisations should collect only data that is strictly needed for a specific purpose. 

    In server-side tracking, this translates into collecting just the essential data points and discarding anything extra before the data is sent to analytics platforms. It helps organisations avoid accumulating excessive personal information, reducing the risk of data breaches and misuse.

    For example, consider a scenario where a user purchases a product on an e-commerce website. 

    With client-side tracking scripts, the system might inadvertently collect a range of data, including the user’s IP address, browser type, operating system and even details about other websites they have visited. 

    However, for conversions, the organisation only needs to know the purchase amount, product IDs, user IDS, and timestamps. 

    Server-side tracking filters unnecessary information. This reduces the privacy impact and simplifies data analysis and storage.

    Cross-device tracking capabilities

    Server-side tracking provides a unified view of customer behaviour regardless of the device they use, allowing for more personalised and targeted marketing campaigns. 

    In-depth event tracking

    Server-side tracking helps businesses track events that occur outside their websites, such as payment confirmations. Companies gain insights into the entire customer journey, from initial interaction to final purchase, optimising every touchpoint. 

    Enhanced privacy compliance

    With increasing regulations like GDPR and CCPA, businesses can better manage user consent and data handling practices through server-side solutions. 

    Server-side setups make honouring user consent easier. If a user opts out, server-side logic can exclude their data from all outgoing analytics calls in one central place. 

    Various benefits of server-side tracking

    Server-side methods reassure users and regulators that data is collected and secured with minimal risk. 

    In sectors like government and banking, this level of control is often a non-negotiable part of their duty of care. 

    Extended cookie lifetime

    Traditional website tracking faces growing obstacles as modern browsers prioritise user privacy. Initiatives like Safari’s ITP block third-party cookies and also constrain the use of first-party cookies. 

    Other browsers, such as Firefox and Brave, are implementing similar methods, while Chrome is beginning to phase out third-party cookies. Retargeting and cross-site analytics, which rely on these cookies, encounter significant challenges.

    Server-side tracking overcomes this by allowing businesses to collect data over a longer duration. 

    When a website’s server directly sets a cookie, that cookie often lasts longer than cookies created by JavaScript code running inside the browser. This lets websites get around some of the limits browsers put on tracking and allows them to remember a visitor when they return to the site later, which gives better customer insights. Plus, server-side tracking typically classifies cookies as first-party data, which is less susceptible to blocking by browsers and ad blockers.

    Server-side tracking : Responsibilities and considerations

    While server-side tracking delivers powerful capabilities, remember that it also brings increased responsibility. Companies must remain vigilant in upholding privacy regulations and user consent. It’s up to the organisation to make sure the server follows user consent, for example, not sending data if someone has opted out.

    Server-side setups introduce technical complexity, which can potentially lead to data errors that are more difficult to identify and resolve. Therefore, monitoring processes and quality assurance practices are essential for data integrity. 

    How does server-side tracking work ? 

    When a user interacts with a website (e.g., clicking a button), this action triggers an event. The event could be anything from a page view to a form submission.

    The backend system captures relevant details such as the event type, user ID and timestamp. This information helps in understanding user behaviour and creating meaningful analytics.

    The captured data is processed directly on the organisation’s server, allowing for immediate validation. For example, organisations can add additional context or filter out irrelevant information.

    Instead of sending data to third-party endpoints, the organisation stores everything in its own database or data warehouse. This ensures full control over data privacy and security.

    Organisations can perform their own analysis using tools like SQL or Python. To visualise data, custom dashboards and reports can be created using self-hosted analytics tools. This way, businesses can present complex data in a clear and actionable manner.

    How to implement server-side tracking ?

    Server-side tracking can work in four common ways, each offering a different blend of control, flexibility and complexity.

    1. Server-side tag management

    In this method, organisations use platforms like Google Tag Manager Server-Side to manage tracking tags on the server, often using containers to isolate and manage different tagging environments. 

    Google Tag Manager server-side landing page

    (Image Source

    This approach offers a balance between control and ease of use. It allows for the deployment and management of tags without modifying the application code, which is particularly useful for marketers who want to adjust tracking configurations quickly.

    2. Direct server-to-server tracking via APIs

    This method involves sharing information between two servers without affecting the user’s browser or device. 

    A unique identifier is generated and stored on a server when a user interacts with an ad or webpage. 

    If a user takes some action, like making a purchase, the unique identifier is sent from the advertiser’s server directly to the platform’s server (Google or Facebook) via an API. 

    It requires more development effort but is ideal for organisations needing fine-grained data control.

    3. Using analytics platforms with built-in server SDKs

    Another way is to employ analytics platforms like Matomo that provide SDKs for various programming languages to instrument the server-side code. 

    This eases integration with the platform’s analytics features and is a good choice for organisations primarily using a single analytics platform and want to use its server-side capabilities.

    4. Hybrid approaches

    Finally, organisations can also combine client- and server-side tracking to capture different data types and maximise accuracy. 

    This method involves client-side scripts for specific interactions (like UI events) and server-side tracking for more sensitive or critical data (like transactions). 

    While these are general approaches, dedicated analytics platforms can also be helpful. Matomo, for example, facilitates server-side tracking through two specific methods.

    Using server logs

    Matomo can import existing web server logs, such as Apache or Nginx, that capture each request. Every page view or resource load becomes a data point. 

    Matomo’s log processing script reads log files, importing millions of hits. This removes the need to add code to the site, making it suitable for basic page analytics (like the URL) without client-side scripts, particularly on security-sensitive sites.

    Using the Matomo tracking API (Server-side SDKs)

    This method integrates application code with calls to Matomo’s API. For example, when a user performs a specific action, the server sends a request to Matomo.php, the tracking endpoint, which includes details like the user ID and action. 

    Matomo offers SDKs in PHP, Java C#, and community SDKs to simplify these calls. These allow tracking of not just page views but custom events such as downloads and transactions from the backend, functioning similarly to Google’s Measurement Protocol but sending data to the Matomo instance. 

    Data privacy, regulations and Matomo

    As privacy concerns grow and regulations like GDPR and CCPA become more stringent, businesses must adopt data collection methods that respect user consent and data protection rights. 

    Server-side tracking allows organisations to collect first-party data directly from their servers, which is generally considered more compliant with privacy regulations.

    Matomo is a popular open-source web analytics platform that is committed to privacy. It gives organisations 100% data ownership and control, and no data is sent to third parties by default.

    Screenshot illustrating the various offerings of Matomo's web analytics features like unique visitors and visits over time

    (Image Source

    Matomo is a full-featured analytics platform with dashboards and segmentation comparable to Google Analytics. It can self-host and provides DoNotTrack settings and the ability to anonymise IP addresses.

    Governments and organisations requiring data sovereignty, such as the EU Commission and the Swiss government, choose Matomo for web analytics due to its strong compliance posture.

    Balancing data collection and user privacy

    Ad blockers and other restrictions prevent data from being accurate. Server-side tracking helps get data on the server and makes it more reliable while respecting user privacy. Matomo supports server-side tracking, and over one million websites use Matomo to optimise their data strategies. 

    Get started today by trying Matomo for free for 21 days, no credit card required.