Recherche avancée

Médias (1)

Mot : - Tags -/stallman

Autres articles (111)

  • Publier sur MédiaSpip

    13 juin 2013

    Puis-je poster des contenus à partir d’une tablette Ipad ?
    Oui, si votre Médiaspip installé est à la version 0.2 ou supérieure. Contacter au besoin l’administrateur de votre MédiaSpip pour le savoir

  • Script d’installation automatique de MediaSPIP

    25 avril 2011, par

    Afin de palier aux difficultés d’installation dues principalement aux dépendances logicielles coté serveur, un script d’installation "tout en un" en bash a été créé afin de faciliter cette étape sur un serveur doté d’une distribution Linux compatible.
    Vous devez bénéficier d’un accès SSH à votre serveur et d’un compte "root" afin de l’utiliser, ce qui permettra d’installer les dépendances. Contactez votre hébergeur si vous ne disposez pas de cela.
    La documentation de l’utilisation du script d’installation (...)

  • Ajouter des informations spécifiques aux utilisateurs et autres modifications de comportement liées aux auteurs

    12 avril 2011, par

    La manière la plus simple d’ajouter des informations aux auteurs est d’installer le plugin Inscription3. Il permet également de modifier certains comportements liés aux utilisateurs (référez-vous à sa documentation pour plus d’informations).
    Il est également possible d’ajouter des champs aux auteurs en installant les plugins champs extras 2 et Interface pour champs extras.

Sur d’autres sites (10885)

  • Top 5 Web Analytics Tools for Your Site

    11 août 2023, par Erin — Analytics Tips

    At the start of July 2023, Universal Analytics (UA) users had to say goodbye to their preferred web analytics tool as Google discontinued it. While some find Google Analytics 4 (GA4) can do what they need, many GA4 users are starting to realise GA4 doesn’t meet all the needs UA once fulfilled. Consequently, they are actively seeking another web analytics tool to complement GA4 and address those unmet requirements effectively.

    In this article, we’ll break down five of the top web analytics tools on the market. You’ll find details about their core capabilities, pricing structures and some noteworthy pros and cons to help you decide which tool is the right fit for you. We’ve also included some key features a good web analytics tool should have to give you a baseline for comparison.

    Whether you’re a marketing manager focused on ROI of campaigns, a web analyst focused on conversions or simply interested in learning more about web analytics, there’s something for you on this list.

    What is a web analytics tool ?

    Web analytics tools collect and analyse information about your website’s visitors, their behaviour and the technical performance of your site. A web analytics tool compiles, measures and analyses website data to give you the information you need to improve site performance, boost conversions and increase your ROI.

    What makes a web analytics tool good ?

    Before we get into tool specifics, let’s go over some of the core features you can expect from a web analytics tool.

    For a web analytics tool to be worth your time (and money), it needs to cover the basics. For example :

    • Visitor reports : The number of visitors, whether they were unique or repeat visitors, the source of traffic (where they found your website), device information (if they’re using a desktop or mobile device) and demographic information like geographic location
    • Behaviour reports : What your visitors did while on your site, conversion rates (e.g., if they signed up for or purchased something), the pages they entered and exited from, average session duration, total time spent on a page and bounce rates (if they left without interacting with anything)
    • Technical information : Page loading speed and event tracking — where users are clicking, what they’re downloading or sharing from your site, if they’re engaging with the media on it and how far down the page they’re scrolling
    • Marketing campaign information : Breakdowns of ad campaigns by provider, showing if ads resulted in traffic to your site and lead to an eventual sale or conversion
    • Search Engine Optimisation (SEO) information : Which keywords on which pages are driving traffic to your site, and what search engines are they coming from
    • Real-time data tracking : Visitor, behaviour and technical information available in real-time, or close to it — allowing you to address to issues as they occur
    • Data visualisation : Charts and graphs illustrating the above information in an easily-readable format — helping identify opportunities and providing valuable insights you can leverage to improve site performance, conversion rates and the amount of time visitors spend on a page
    • Custom reporting : Create custom reports detailing the desired metrics and time frame you’re interested in
    • Security : User access controls and management tools to limit who can see and interact with user data
    • Resources : Official user guides, technical documentation, troubleshooting materials, customer support and community forums
    Google Analytics 4 dashboard

    Pros and Cons of Google Analytics 4

    Despite many users’ dissatisfaction, GA4 isn’t going away anytime soon. It’s still a powerful tool with all the standard features you’d expect. It’s the most popular choice for web analytics for a few other reasons, too, including :

    • It’s free to use
    • It’s easy to set up
    • It has a convenient mobile app
    • It has a wealth of user documentation and technical resources online
    • Its machine-learning capabilities help predict user behaviour and offer insights on how to grow your site
    • It integrates easily with other Google tools, like Google Search Console, Google Ads and Google Cloud

    That said, it comes with some serious drawbacks. Many users accustomed to UA have reported being unhappy with the differences between it and GA4. Their reasons range from changes to the user interface and bounce rate calculations, as well as Google’s switch from pageview-focused metrics to event-based ones. 

    Let’s take a look at some of the other cons :

    Now that you know GA4’s strengths and weaknesses, it’s time to explore other tools that can help fill in GA4’s gaps.

    Top 5 web analytics tools (that aren’t Google)

    Below is a list of popular web analytics tools that, unless otherwise stated, have all the features a good tool should have.

    Adobe Analytics

    Screenshot of the landing page for Adobe's web analytics tool

    Adobe is a trusted name in software, with tools that have shaped the technological landscape for decades, like Photoshop and Illustrator. With web design and UX tools Dreamweaver and XD, it makes sense that they’d offer a web analytics platform as well.

    Adobe Analytics provides not just web analytics but marketing analytics that tell you about customer acquisition and retention, ROI and ad campaign performance metrics. Its machine learning (ML) and AI-powered analytics predict future customer behaviour based on previously collected data.

    Key features : 

    • Multichannel data collection that covers computers, mobile devices and IoT devices
    • Adobe Sensei (AI/ML) for marketing attribution and anomaly detection
    • Tag management through Adobe Experience Platform Launch simplifies the tag creation and maintenance process to help you track how users interact with your site

    Pros :

    • User-friendly and simple to learn with a drag-and-drop interface
    • When integrated with other Adobe software, it becomes a powerful solution for enterprises
    • Saves your team a lot of time with the recommendations and insights automatically generated by Adobe’s AI/ML

    Cons :

    • No free version
    • Adobe Sensei and tag manager limited to premium version
    • Expensive, especially when combined with the company’s other software
    • Steep learning curve for both setup and use

    Mobile app : Yes

    Integrations : Integrates with Adobe Experience Manager Sites, the company’s CMS. Adobe Target, a CRO tool and part of the Adobe Marketing Cloud subscription, integrates with Analytics.

    Pricing : Available upon request

    Matomo

    Screenshot of Matomo Web Analytics Dashboard

    Matomo is the leading open-source web analytics solution designed to help you make more informed decisions and enhance your customer experience while ensuring GDPR compliance and user privacy. With Matomo Cloud, your data is stored in Europe, while Matomo On-Premise allows you to host your data on your own servers.

    Matomo is used on over 1 million websites, in over 190 countries, and in over 50 languages. Additionally, Matomo is an all-in-one solution, with traditional web analytics (visits, acquisition, etc.) alongside behavioural analytics (heatmaps, session recordings and more), plus a tag manager. No more inefficiently jumping back and forth between tabs in a huge tech stack. It’s all in Matomo, for one consistent, seamless and efficient experience. 

    Key features : 

    • Heatmaps and session recording to display what users are clicking on and how individual users interacted with your site 
    • A/B testing to compare different versions of the same content and see which gets better results
    • Robust API that lets you get insights by connecting your data to other platforms, like data visualisation or business intelligence tools

    Pros : 

    • Open-source, reviewed by experts to ensure that it’s secure
    • Offers On-Premise or Cloud-hosted options
    • Fully compliant with GDPR, so you can be data-driven without worrying. 
    • Option to run without cookies, meaning in most countries you can use Matomo without annoying cookie consent banners and while getting more accurate data
    • You retain complete ownership of your data, with no third parties using it for advertising or unspecified “own purposes”

    Cons : 

    • On-Premise is free, but that means an additional cost for advanced features (A/B testing, heatmaps, etc.) that are included by default on Matomo Cloud
    • Matomo On-Premise requires servers and technical expertise to setup and manage

    Mobile app : Matomo offers a free mobile app (iOS and Android) so you can access your analytics on the go. 

    Integrations : Matomo integrates easily with many other tools and platforms, including WordPress, Looker Studio, Magento, Jira, Drupal, Joomla and Cloudflare.

    Pricing : 

    • Varies based on monthly hits
    • Matomo On-Premise : free
    • Matomo Cloud : starting at €19/month

    Mixpanel

    Screenshot of Mixpanel's product page

    Mixpanel’s features are heavily geared toward e-commerce companies. From the moment a visitor lands on your website to the moment they enter their payment details and complete a transaction, Mixpanel tracks these events.

    Similar to GA4, Mixpanel is an event-focused analytics platform. While you can still track pageviews with Mixpanel, its main focus is on the specific actions users take that lead them to purchases. Putting your attention on this information allows you to find out which events on your site are going through the sales funnel.

    They’re currently developing a Warehouse Events feature to simplify the process of importing data lakes and data warehouses.

    Key features :

    • Custom alerts and anomaly detection
    • Boards, which allow you to share multiple reports and insights with your team in a range of visual styles 
    • Detailed segmentation reporting that lets you break down your data to the individual user, specific event or geographic level

    Pros :

    • Boards allow for emojis, gifs, images and videos to make collaboration fun
    • Powerful mobile analytics for iOS and Android apps
    • Free promotional credits for eligible startups 

    Cons :

    • Limited features in free plan
    • Best features limited to the Enterprise-tier subscription
    • Complicated set up
    • Steep learning curve

    Mobile app : No

    Integrations : Mixpanel has a load of integrations, including Figma, Google Cloud, Slack, HappyFox, Snowflake, Microsoft Azure, Optimizely, Mailchimp and Tenjin. They also have a WordPress plugin.

    Pricing : 

    • Starter : free plan available
    • Growth : $20/month
    • Enterprise $833/month

    HubSpot Marketing

    Screenshot of Hubspot Marketing's main page

    HubSpot is a customer relationship management (CRM) platform with marketing, sales, customer service, content management system (CMS) and operations tools. This greater ecosystem of HubSpot software allows you to practically run your entire business in one place.

    Even though HubSpot Marketing isn’t a dedicated web analytics tool, it provides comparable standard metrics as the other tools on this list, albeit without the more advanced analytical metrics they offer. If you’re already using HubSpot to host your website, it’s definitely worth consideration.

    Key features :

    • Customer Journey Analytics presents the steps your customers went through in the sales process, step-by-step, in a visual way
    • Dashboards for your reports, including both fully customisable options for power users and pre-made templates for new users

    Pros :

    • Integration with other HubSpot tools, like HubSpot CRM’s free live chat widget 
    • User-friendly interface with many features being drag-and-drop, like the report dashboard
    • 24/7 customer support

    Cons :

    • Can get expensive with upgrades and other HubSpot tool add ons
    • Not a dedicated web analytics tool, so it’s missing some of the features other tools have, like heatmaps
    • Not really worth it as a standalone tool
    • Some users report customer support is unhelpful

    Mobile app : Yes

    Integrations : The larger HubSpot CRM platform can connect with nearly 1,500 other apps through the HubSpot App Marketplace. These include Slack, Microsoft Teams, Salesforce, Make, WordPress, SurveyMonkey, Shopify, monday.com, Stripe, WooCommerce and hundreds of others.

    Pricing : 

    • Starter : $20/month ($18/month with annual plan) 
    • Professional : $890/month ($800/month with annual plan) 
    • Enterprise : $3,600/month ($43,200 billed annually)

    Kissmetrics

    Screenshot of the landing page of web analytics tool Kissmetrics

    Kissmetrics is a web analytics tool that is marketed toward SaaS and ecommerce companies. They label themselves as “person-based” because they combine event-based tracking with detailed user profiles of the visitors to your site, which allows you to gain insights into customer behaviour. 

    With user profiles, you can drill down to see how many times someone has visited your site, if they’ve purchased from you and the steps they took before completing a sale. This allows you to cater more to these users and drive growth.

    Key features : 

    • Person Profiles that give granular information about individual users and their activities on your site
    • Campaigns, an engagement messenger application, allows you to set up email automations that are triggered by specific events
    • Detailed reporting tools 

    Pros : 

    • No third-party cookies
    • No data sampling
    • APIs for Ruby on Rails, JavaScript, Python and PHP

    Cons : 

    • Difficult installation
    • Strongest reporting features only available in the most expensive plan
    • Reports can be slow to generate
    • Requires custom JavaScript code to tack single-page applications
    • Doesn’t track demographic data, bounce rate, exits, session length or time on page

    Mobile app : No

    Integrations : Kissmetrics integrates with HubSpot, Appcues, Slack, Mailchimp, Shopify, WooCommerce, Recurly and a dozen others. There is also a Kissmetrics WordPress plugin.

    Pricing : 

    • Silver : $299/month (small businesses)
    • Gold : $499/month (medium) 
    • Platinum : custom pricing (enterprises)

    Conclusion

    In this article, you learned about popular tools for web analytics to better inform you of your options. Despite all of GA4’s shortcomings, by complementing it with another web analytics tool, teams can gain a more comprehensive understanding of their website traffic and enhance their overall analytics capabilities.

    If you want an option that delivers powerful insights while keeping privacy, security and compliance at the forefront, you should try Matomo. 

    Try Matomo alongside Google Analytics now to see how it compares.

    Start your 21-day free trial now – no credit card required.

  • How can I fix a segmentation fault in a C program ? [duplicate]

    31 mars 2023, par ipegasus
    


    Possible Duplicate :
    
Segmentation fault

    


    


    Currently I am upgrading an open source program used for HTTP streaming. It needs to support the latest FFmpeg.
The code compiles fine without any warnings, although I am getting a segmentation fault error.

    


    How can I fix the issue ? And / or, what is the best way to debug ? Please find attached a portion of the code due to size. I will try to add the project to GitHub :)

    


    Sample Usage

    


    # segmenter --i out.ts --l 10 --o stream.m3u8 --d segments --f stream


    


    Makefile

    


    FFLIBS=`pkg-config --libs libavformat libavcodec libavutil`
FFFLAGS=`pkg-config --cflags libavformat libavcodec libavutil`

all:
    gcc -Wall -g segmenter.c -o segmenter ${FFFLAGS} ${FFLIBS}


    


    segmenter.c

    


    /*&#xA; * Copyright (c) 2009 Chase Douglas&#xA; *&#xA; * This program is free software; you can redistribute it and/or&#xA; * modify it under the terms of the GNU General Public License version 2&#xA; * as published by the Free Software Foundation.&#xA; *&#xA; * This program is distributed in the hope that it will be useful,&#xA; * but WITHOUT ANY WARRANTY; without even the implied warranty of&#xA; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&#xA; * GNU General Public License for more details.&#xA; *&#xA; * You should have received a copy of the GNU General Public License&#xA; * along with this program; if not, write to the Free Software&#xA; * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.&#xA; */&#xA;#include &#xA;#include &#xA;#include &#xA;#include &#xA;#include &#xA;#include "libavformat/avformat.h"&#xA;&#xA;#include "libavformat/avio.h"&#xA;&#xA;#include <sys></sys>stat.h>&#xA;&#xA;#include "segmenter.h"&#xA;#include "libavformat/avformat.h"&#xA;&#xA;#define IMAGE_ID3_SIZE 9171&#xA;&#xA;void printUsage() {&#xA;    fprintf(stderr, "\nExample: segmenter --i infile --d baseDir --f baseFileName --o playListFile.m3u8 --l 10 \n");&#xA;    fprintf(stderr, "\nOptions: \n");&#xA;    fprintf(stderr, "--i <infile>.\n");&#xA;    fprintf(stderr, "--o <outfile>.\n");&#xA;    fprintf(stderr, "--d basedir, the base directory for files.\n");&#xA;    fprintf(stderr, "--f baseFileName, output files will be baseFileName-#.\n");&#xA;    fprintf(stderr, "--l segment length, the length of each segment.\n");&#xA;    fprintf(stderr, "--a,  audio only decode for &lt; 64k streams.\n");&#xA;    fprintf(stderr, "--v,  video only decode for &lt; 64k streams.\n");&#xA;    fprintf(stderr, "--version, print version details and exit.\n");&#xA;    fprintf(stderr, "\n\n");&#xA;}&#xA;&#xA;void ffmpeg_version() {&#xA;    // output build and version numbers&#xA;    fprintf(stderr, "  libavutil version:   %s\n", AV_STRINGIFY(LIBAVUTIL_VERSION));&#xA;    fprintf(stderr, "  libavutil build:     %d\n", LIBAVUTIL_BUILD);&#xA;    fprintf(stderr, "  libavcodec version:  %s\n", AV_STRINGIFY(LIBAVCODEC_VERSION));&#xA;    fprintf(stdout, "  libavcodec build:    %d\n", LIBAVCODEC_BUILD);&#xA;    fprintf(stderr, "  libavformat version: %s\n", AV_STRINGIFY(LIBAVFORMAT_VERSION));&#xA;    fprintf(stderr, "  libavformat build:   %d\n", LIBAVFORMAT_BUILD);&#xA;    fprintf(stderr, "  built on " __DATE__ " " __TIME__);&#xA;#ifdef __GNUC__&#xA;    fprintf(stderr, ", gcc: " __VERSION__ "\n");&#xA;#else&#xA;    fprintf(stderr, ", using a non-gcc compiler\n");&#xA;#endif&#xA;}&#xA;&#xA;&#xA;static AVStream *add_output_stream(AVFormatContext *output_format_context, AVStream *input_stream) {&#xA;    AVCodecContext *input_codec_context;&#xA;    AVCodecContext *output_codec_context;&#xA;    AVStream *output_stream;&#xA;&#xA;    output_stream = avformat_new_stream(output_format_context, 0);&#xA;    if (!output_stream) {&#xA;        fprintf(stderr, "Segmenter error: Could not allocate stream\n");&#xA;        exit(1);&#xA;    }&#xA;&#xA;    input_codec_context = input_stream->codec;&#xA;    output_codec_context = output_stream->codec;&#xA;&#xA;    output_codec_context->codec_id = input_codec_context->codec_id;&#xA;    output_codec_context->codec_type = input_codec_context->codec_type;&#xA;    output_codec_context->codec_tag = input_codec_context->codec_tag;&#xA;    output_codec_context->bit_rate = input_codec_context->bit_rate;&#xA;    output_codec_context->extradata = input_codec_context->extradata;&#xA;    output_codec_context->extradata_size = input_codec_context->extradata_size;&#xA;&#xA;    if (av_q2d(input_codec_context->time_base) * input_codec_context->ticks_per_frame > av_q2d(input_stream->time_base) &amp;&amp; av_q2d(input_stream->time_base) &lt; 1.0 / 1000) {&#xA;        output_codec_context->time_base = input_codec_context->time_base;&#xA;        output_codec_context->time_base.num *= input_codec_context->ticks_per_frame;&#xA;    } else {&#xA;        output_codec_context->time_base = input_stream->time_base;&#xA;    }&#xA;&#xA;    switch (input_codec_context->codec_type) {&#xA;#ifdef USE_OLD_FFMPEG&#xA;        case CODEC_TYPE_AUDIO:&#xA;#else&#xA;        case AVMEDIA_TYPE_AUDIO:&#xA;#endif&#xA;            output_codec_context->channel_layout = input_codec_context->channel_layout;&#xA;            output_codec_context->sample_rate = input_codec_context->sample_rate;&#xA;            output_codec_context->channels = input_codec_context->channels;&#xA;            output_codec_context->frame_size = input_codec_context->frame_size;&#xA;            if ((input_codec_context->block_align == 1 &amp;&amp; input_codec_context->codec_id == CODEC_ID_MP3) || input_codec_context->codec_id == CODEC_ID_AC3) {&#xA;                output_codec_context->block_align = 0;&#xA;            } else {&#xA;                output_codec_context->block_align = input_codec_context->block_align;&#xA;            }&#xA;            break;&#xA;#ifdef USE_OLD_FFMPEG&#xA;        case CODEC_TYPE_VIDEO:&#xA;#else&#xA;        case AVMEDIA_TYPE_VIDEO:&#xA;#endif&#xA;            output_codec_context->pix_fmt = input_codec_context->pix_fmt;&#xA;            output_codec_context->width = input_codec_context->width;&#xA;            output_codec_context->height = input_codec_context->height;&#xA;            output_codec_context->has_b_frames = input_codec_context->has_b_frames;&#xA;&#xA;            if (output_format_context->oformat->flags &amp; AVFMT_GLOBALHEADER) {&#xA;                output_codec_context->flags |= CODEC_FLAG_GLOBAL_HEADER;&#xA;            }&#xA;            break;&#xA;        default:&#xA;            break;&#xA;    }&#xA;&#xA;    return output_stream;&#xA;}&#xA;&#xA;int write_index_file(const char index[], const char tmp_index[], const unsigned int planned_segment_duration, const unsigned int actual_segment_duration[],&#xA;        const char output_directory[], const char output_prefix[], const char output_file_extension[],&#xA;        const unsigned int first_segment, const unsigned int last_segment) {&#xA;    FILE *index_fp;&#xA;    char *write_buf;&#xA;    unsigned int i;&#xA;&#xA;    index_fp = fopen(tmp_index, "w");&#xA;    if (!index_fp) {&#xA;        fprintf(stderr, "Could not open temporary m3u8 index file (%s), no index file will be created\n", tmp_index);&#xA;        return -1;&#xA;    }&#xA;&#xA;    write_buf = malloc(sizeof (char) * 1024);&#xA;    if (!write_buf) {&#xA;        fprintf(stderr, "Could not allocate write buffer for index file, index file will be invalid\n");&#xA;        fclose(index_fp);&#xA;        return -1;&#xA;    }&#xA;&#xA;    unsigned int maxDuration = planned_segment_duration;&#xA;&#xA;    for (i = first_segment; i &lt;= last_segment; i&#x2B;&#x2B;)&#xA;        if (actual_segment_duration[i] > maxDuration)&#xA;            maxDuration = actual_segment_duration[i];&#xA;&#xA;&#xA;&#xA;    snprintf(write_buf, 1024, "#EXTM3U\n#EXT-X-TARGETDURATION:%u\n", maxDuration);&#xA;&#xA;    if (fwrite(write_buf, strlen(write_buf), 1, index_fp) != 1) {&#xA;        fprintf(stderr, "Could not write to m3u8 index file, will not continue writing to index file\n");&#xA;        free(write_buf);&#xA;        fclose(index_fp);&#xA;        return -1;&#xA;    }&#xA;&#xA;    for (i = first_segment; i &lt;= last_segment; i&#x2B;&#x2B;) {&#xA;        snprintf(write_buf, 1024, "#EXTINF:%u,\n%s-%u%s\n", actual_segment_duration[i], output_prefix, i, output_file_extension);&#xA;        if (fwrite(write_buf, strlen(write_buf), 1, index_fp) != 1) {&#xA;            fprintf(stderr, "Could not write to m3u8 index file, will not continue writing to index file\n");&#xA;            free(write_buf);&#xA;            fclose(index_fp);&#xA;            return -1;&#xA;        }&#xA;    }&#xA;&#xA;    snprintf(write_buf, 1024, "#EXT-X-ENDLIST\n");&#xA;    if (fwrite(write_buf, strlen(write_buf), 1, index_fp) != 1) {&#xA;        fprintf(stderr, "Could not write last file and endlist tag to m3u8 index file\n");&#xA;        free(write_buf);&#xA;        fclose(index_fp);&#xA;        return -1;&#xA;    }&#xA;&#xA;    free(write_buf);&#xA;    fclose(index_fp);&#xA;&#xA;    return rename(tmp_index, index);&#xA;}&#xA;&#xA;int main(int argc, const char *argv[]) {&#xA;    //input parameters&#xA;    char inputFilename[MAX_FILENAME_LENGTH], playlistFilename[MAX_FILENAME_LENGTH], baseDirName[MAX_FILENAME_LENGTH], baseFileName[MAX_FILENAME_LENGTH];&#xA;    char baseFileExtension[5]; //either "ts", "aac" or "mp3"&#xA;    int segmentLength, outputStreams, verbosity, version;&#xA;&#xA;&#xA;&#xA;    char currentOutputFileName[MAX_FILENAME_LENGTH];&#xA;    char tempPlaylistName[MAX_FILENAME_LENGTH];&#xA;&#xA;&#xA;    //these are used to determine the exact length of the current segment&#xA;    double prev_segment_time = 0;&#xA;    double segment_time;&#xA;    unsigned int actual_segment_durations[2048];&#xA;    double packet_time = 0;&#xA;&#xA;    //new variables to keep track of output size&#xA;    double output_bytes = 0;&#xA;&#xA;    unsigned int output_index = 1;&#xA;    AVOutputFormat *ofmt;&#xA;    AVFormatContext *ic = NULL;&#xA;    AVFormatContext *oc;&#xA;    AVStream *video_st = NULL;&#xA;    AVStream *audio_st = NULL;&#xA;    AVCodec *codec;&#xA;    int video_index;&#xA;    int audio_index;&#xA;    unsigned int first_segment = 1;&#xA;    unsigned int last_segment = 0;&#xA;    int write_index = 1;&#xA;    int decode_done;&#xA;    int ret;&#xA;    int i;&#xA;&#xA;    unsigned char id3_tag[128];&#xA;    unsigned char * image_id3_tag;&#xA;&#xA;    size_t id3_tag_size = 73;&#xA;    int newFile = 1; //a boolean value to flag when a new file needs id3 tag info in it&#xA;&#xA;    if (parseCommandLine(inputFilename, playlistFilename, baseDirName, baseFileName, baseFileExtension, &amp;outputStreams, &amp;segmentLength, &amp;verbosity, &amp;version, argc, argv) != 0)&#xA;        return 0;&#xA;&#xA;    if (version) {&#xA;        ffmpeg_version();&#xA;        return 0;&#xA;    }&#xA;&#xA;&#xA;    fprintf(stderr, "%s %s\n", playlistFilename, tempPlaylistName);&#xA;&#xA;&#xA;    image_id3_tag = malloc(IMAGE_ID3_SIZE);&#xA;    if (outputStreams == OUTPUT_STREAM_AUDIO)&#xA;        build_image_id3_tag(image_id3_tag);&#xA;    build_id3_tag((char *) id3_tag, id3_tag_size);&#xA;&#xA;    snprintf(tempPlaylistName, strlen(playlistFilename) &#x2B; strlen(baseDirName) &#x2B; 1, "%s%s", baseDirName, playlistFilename);&#xA;    strncpy(playlistFilename, tempPlaylistName, strlen(tempPlaylistName));&#xA;    strncpy(tempPlaylistName, playlistFilename, MAX_FILENAME_LENGTH);&#xA;    strncat(tempPlaylistName, ".", 1);&#xA;&#xA;    //decide if this is an aac file or a mpegts file.&#xA;    //postpone deciding format until later&#xA;    /*    ifmt = av_find_input_format("mpegts");&#xA;    if (!ifmt)&#xA;    {&#xA;    fprintf(stderr, "Could not find MPEG-TS demuxer.\n");&#xA;    exit(1);&#xA;    } */&#xA;&#xA;    av_log_set_level(AV_LOG_DEBUG);&#xA;&#xA;    av_register_all();&#xA;    ret = avformat_open_input(&amp;ic, inputFilename, NULL, NULL);&#xA;    if (ret != 0) {&#xA;        fprintf(stderr, "Could not open input file %s. Error %d.\n", inputFilename, ret);&#xA;        exit(1);&#xA;    }&#xA;&#xA;    if (avformat_find_stream_info(ic, NULL) &lt; 0) {&#xA;        fprintf(stderr, "Could not read stream information.\n");&#xA;        exit(1);&#xA;    }&#xA;&#xA;    oc = avformat_alloc_context();&#xA;    if (!oc) {&#xA;        fprintf(stderr, "Could not allocate output context.");&#xA;        exit(1);&#xA;    }&#xA;&#xA;    video_index = -1;&#xA;    audio_index = -1;&#xA;&#xA;    for (i = 0; i &lt; ic->nb_streams &amp;&amp; (video_index &lt; 0 || audio_index &lt; 0); i&#x2B;&#x2B;) {&#xA;        switch (ic->streams[i]->codec->codec_type) {&#xA;&#xA;#ifdef USE_OLD_FFMPEG&#xA;            case CODEC_TYPE_VIDEO:&#xA;#else&#xA;            case AVMEDIA_TYPE_VIDEO:&#xA;#endif&#xA;                video_index = i;&#xA;                ic->streams[i]->discard = AVDISCARD_NONE;&#xA;                if (outputStreams &amp; OUTPUT_STREAM_VIDEO)&#xA;                    video_st = add_output_stream(oc, ic->streams[i]);&#xA;                break;&#xA;#ifdef USE_OLD_FFMPEG&#xA;            case CODEC_TYPE_AUDIO:&#xA;#else&#xA;            case AVMEDIA_TYPE_AUDIO:&#xA;#endif&#xA;                audio_index = i;&#xA;                ic->streams[i]->discard = AVDISCARD_NONE;&#xA;                if (outputStreams &amp; OUTPUT_STREAM_AUDIO)&#xA;                    audio_st = add_output_stream(oc, ic->streams[i]);&#xA;                break;&#xA;            default:&#xA;                ic->streams[i]->discard = AVDISCARD_ALL;&#xA;                break;&#xA;        }&#xA;    }&#xA;&#xA;    if (video_index == -1) {&#xA;        fprintf(stderr, "Stream must have video component.\n");&#xA;        exit(1);&#xA;    }&#xA;&#xA;    //now that we know the audio and video output streams&#xA;    //we can decide on an output format.&#xA;    if (outputStreams == OUTPUT_STREAM_AUDIO) {&#xA;        //the audio output format should be the same as the audio input format&#xA;        switch (ic->streams[audio_index]->codec->codec_id) {&#xA;            case CODEC_ID_MP3:&#xA;                fprintf(stderr, "Setting output audio to mp3.");&#xA;                strncpy(baseFileExtension, ".mp3", strlen(".mp3"));&#xA;                ofmt = av_guess_format("mp3", NULL, NULL);&#xA;                break;&#xA;            case CODEC_ID_AAC:&#xA;                fprintf(stderr, "Setting output audio to aac.");&#xA;                ofmt = av_guess_format("adts", NULL, NULL);&#xA;                break;&#xA;            default:&#xA;                fprintf(stderr, "Codec id %d not supported.\n", ic->streams[audio_index]->id);&#xA;        }&#xA;        if (!ofmt) {&#xA;            fprintf(stderr, "Could not find audio muxer.\n");&#xA;            exit(1);&#xA;        }&#xA;    } else {&#xA;        ofmt = av_guess_format("mpegts", NULL, NULL);&#xA;        if (!ofmt) {&#xA;            fprintf(stderr, "Could not find MPEG-TS muxer.\n");&#xA;            exit(1);&#xA;        }&#xA;    }&#xA;    oc->oformat = ofmt;&#xA;&#xA;    if (outputStreams &amp; OUTPUT_STREAM_VIDEO &amp;&amp; oc->oformat->flags &amp; AVFMT_GLOBALHEADER) {&#xA;        oc->flags |= CODEC_FLAG_GLOBAL_HEADER;&#xA;    }&#xA;&#xA;&#xA;    /*  Deprecated: pass the options to avformat_write_header directly.&#xA;        if (av_set_parameters(oc, NULL) &lt; 0) {&#xA;            fprintf(stderr, "Invalid output format parameters.\n");&#xA;            exit(1);&#xA;        }&#xA;     */&#xA;&#xA;    av_dump_format(oc, 0, baseFileName, 1);&#xA;&#xA;&#xA;    //open the video codec only if there is video data&#xA;    if (video_index != -1) {&#xA;        if (outputStreams &amp; OUTPUT_STREAM_VIDEO)&#xA;            codec = avcodec_find_decoder(video_st->codec->codec_id);&#xA;        else&#xA;            codec = avcodec_find_decoder(ic->streams[video_index]->codec->codec_id);&#xA;        if (!codec) {&#xA;            fprintf(stderr, "Could not find video decoder, key frames will not be honored.\n");&#xA;        }&#xA;&#xA;        if (outputStreams &amp; OUTPUT_STREAM_VIDEO)&#xA;            ret = avcodec_open2(video_st->codec, codec, NULL);&#xA;        else&#xA;            avcodec_open2(ic->streams[video_index]->codec, codec, NULL);&#xA;        if (ret &lt; 0) {&#xA;            fprintf(stderr, "Could not open video decoder, key frames will not be honored.\n");&#xA;        }&#xA;    }&#xA;&#xA;    snprintf(currentOutputFileName, strlen(baseDirName) &#x2B; strlen(baseFileName) &#x2B; strlen(baseFileExtension) &#x2B; 10, "%s%s-%u%s", baseDirName, baseFileName, output_index&#x2B;&#x2B;, baseFileExtension);&#xA;&#xA;    if (avio_open(&amp;oc->pb, currentOutputFileName, URL_WRONLY) &lt; 0) {&#xA;        fprintf(stderr, "Could not open &#x27;%s&#x27;.\n", currentOutputFileName);&#xA;        exit(1);&#xA;    }&#xA;    newFile = 1;&#xA;&#xA;    int r = avformat_write_header(oc,NULL);&#xA;    if (r) {&#xA;        fprintf(stderr, "Could not write mpegts header to first output file.\n");&#xA;        debugReturnCode(r);&#xA;        exit(1);&#xA;    }&#xA;&#xA;    //no segment info is written here. This just creates the shell of the playlist file&#xA;    write_index = !write_index_file(playlistFilename, tempPlaylistName, segmentLength, actual_segment_durations, baseDirName, baseFileName, baseFileExtension, first_segment, last_segment);&#xA;&#xA;    do {&#xA;        AVPacket packet;&#xA;&#xA;        decode_done = av_read_frame(ic, &amp;packet);&#xA;&#xA;        if (decode_done &lt; 0) {&#xA;            break;&#xA;        }&#xA;&#xA;        if (av_dup_packet(&amp;packet) &lt; 0) {&#xA;            fprintf(stderr, "Could not duplicate packet.");&#xA;            av_free_packet(&amp;packet);&#xA;            break;&#xA;        }&#xA;&#xA;        //this time is used to check for a break in the segments&#xA;        //    if (packet.stream_index == video_index &amp;&amp; (packet.flags &amp; PKT_FLAG_KEY))&#xA;        //    {&#xA;        //    segment_time = (double)video_st->pts.val * video_st->time_base.num / video_st->time_base.den;&#xA;        //    }&#xA;#if USE_OLD_FFMPEG&#xA;        if (packet.stream_index == video_index &amp;&amp; (packet.flags &amp; PKT_FLAG_KEY))&#xA;#else&#xA;        if (packet.stream_index == video_index &amp;&amp; (packet.flags &amp; AV_PKT_FLAG_KEY))&#xA;#endif&#xA;        {&#xA;            segment_time = (double) packet.pts * ic->streams[video_index]->time_base.num / ic->streams[video_index]->time_base.den;&#xA;        }&#xA;        //  else if (video_index &lt; 0)&#xA;        //    {&#xA;        //        segment_time = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den;&#xA;        //    }&#xA;&#xA;        //get the most recent packet time&#xA;        //this time is used when the time for the final segment is printed. It may not be on the edge of&#xA;        //of a keyframe!&#xA;        if (packet.stream_index == video_index)&#xA;            packet_time = (double) packet.pts * ic->streams[video_index]->time_base.num / ic->streams[video_index]->time_base.den; //(double)video_st->pts.val * video_st->time_base.num / video_st->time_base.den;&#xA;        else if (outputStreams &amp; OUTPUT_STREAM_AUDIO)&#xA;            packet_time = (double) audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den;&#xA;        else&#xA;            continue;&#xA;        //start looking for segment splits for videos one half second before segment duration expires. This is because the&#xA;        //segments are split on key frames so we cannot expect all segments to be split exactly equally.&#xA;        if (segment_time - prev_segment_time >= segmentLength - 0.5) {&#xA;            fprintf(stderr, "looking to print index file at time %lf\n", segment_time);&#xA;            avio_flush(oc->pb);&#xA;            avio_close(oc->pb);&#xA;&#xA;            if (write_index) {&#xA;                actual_segment_durations[&#x2B;&#x2B;last_segment] = (unsigned int) rint(segment_time - prev_segment_time);&#xA;                write_index = !write_index_file(playlistFilename, tempPlaylistName, segmentLength, actual_segment_durations, baseDirName, baseFileName, baseFileExtension, first_segment, last_segment);&#xA;                fprintf(stderr, "Writing index file at time %lf\n", packet_time);&#xA;            }&#xA;&#xA;            struct stat st;&#xA;            stat(currentOutputFileName, &amp;st);&#xA;            output_bytes &#x2B;= st.st_size;&#xA;&#xA;            snprintf(currentOutputFileName, strlen(baseDirName) &#x2B; strlen(baseFileName) &#x2B; strlen(baseFileExtension) &#x2B; 10, "%s%s-%u%s", baseDirName, baseFileName, output_index&#x2B;&#x2B;, baseFileExtension);&#xA;            if (avio_open(&amp;oc->pb, currentOutputFileName, URL_WRONLY) &lt; 0) {&#xA;                fprintf(stderr, "Could not open &#x27;%s&#x27;\n", currentOutputFileName);&#xA;                break;&#xA;            }&#xA;&#xA;            newFile = 1;&#xA;            prev_segment_time = segment_time;&#xA;        }&#xA;&#xA;        if (outputStreams == OUTPUT_STREAM_AUDIO &amp;&amp; packet.stream_index == audio_index) {&#xA;            if (newFile &amp;&amp; outputStreams == OUTPUT_STREAM_AUDIO) {&#xA;                //add id3 tag info&#xA;                //fprintf(stderr, "adding id3tag to file %s\n", currentOutputFileName);&#xA;                //printf("%lf %lld %lld %lld %lld %lld %lf\n", segment_time, audio_st->pts.val, audio_st->cur_dts, audio_st->cur_pkt.pts, packet.pts, packet.dts, packet.dts * av_q2d(ic->streams[audio_index]->time_base) );&#xA;                fill_id3_tag((char*) id3_tag, id3_tag_size, packet.dts);&#xA;                avio_write(oc->pb, id3_tag, id3_tag_size);&#xA;                avio_write(oc->pb, image_id3_tag, IMAGE_ID3_SIZE);&#xA;                avio_flush(oc->pb);&#xA;                newFile = 0;&#xA;            }&#xA;&#xA;            packet.stream_index = 0; //only one stream in audio only segments&#xA;            ret = av_interleaved_write_frame(oc, &amp;packet);&#xA;        } else if (outputStreams &amp; OUTPUT_STREAM_VIDEO) {&#xA;            if (newFile) {&#xA;                //fprintf(stderr, "New File: %lld %lld %lld\n", packet.pts, video_st->pts.val, audio_st->pts.val);&#xA;                //printf("%lf %lld %lld %lld %lld %lld %lf\n", segment_time, audio_st->pts.val, audio_st->cur_dts, audio_st->cur_pkt.pts, packet.pts, packet.dts, packet.dts * av_q2d(ic->streams[audio_index]->time_base) );&#xA;                newFile = 0;&#xA;            }&#xA;            if (outputStreams == OUTPUT_STREAM_VIDEO)&#xA;                ret = av_write_frame(oc, &amp;packet);&#xA;            else&#xA;                ret = av_interleaved_write_frame(oc, &amp;packet);&#xA;        }&#xA;&#xA;        if (ret &lt; 0) {&#xA;            fprintf(stderr, "Warning: Could not write frame of stream.\n");&#xA;        } else if (ret > 0) {&#xA;            fprintf(stderr, "End of stream requested.\n");&#xA;            av_free_packet(&amp;packet);&#xA;            break;&#xA;        }&#xA;&#xA;        av_free_packet(&amp;packet);&#xA;    } while (!decode_done);&#xA;&#xA;    //make sure all packets are written and then close the last file.&#xA;    avio_flush(oc->pb);&#xA;    av_write_trailer(oc);&#xA;&#xA;    if (video_st &amp;&amp; video_st->codec)&#xA;        avcodec_close(video_st->codec);&#xA;&#xA;    if (audio_st &amp;&amp; audio_st->codec)&#xA;        avcodec_close(audio_st->codec);&#xA;&#xA;    for (i = 0; i &lt; oc->nb_streams; i&#x2B;&#x2B;) {&#xA;        av_freep(&amp;oc->streams[i]->codec);&#xA;        av_freep(&amp;oc->streams[i]);&#xA;    }&#xA;&#xA;    avio_close(oc->pb);&#xA;    av_free(oc);&#xA;&#xA;    struct stat st;&#xA;    stat(currentOutputFileName, &amp;st);&#xA;    output_bytes &#x2B;= st.st_size;&#xA;&#xA;&#xA;    if (write_index) {&#xA;        actual_segment_durations[&#x2B;&#x2B;last_segment] = (unsigned int) rint(packet_time - prev_segment_time);&#xA;&#xA;        //make sure that the last segment length is not zero&#xA;        if (actual_segment_durations[last_segment] == 0)&#xA;            actual_segment_durations[last_segment] = 1;&#xA;&#xA;        write_index_file(playlistFilename, tempPlaylistName, segmentLength, actual_segment_durations, baseDirName, baseFileName, baseFileExtension, first_segment, last_segment);&#xA;&#xA;    }&#xA;&#xA;    write_stream_size_file(baseDirName, baseFileName, output_bytes * 8 / segment_time);&#xA;&#xA;    return 0;&#xA;}&#xA;</outfile></infile>

    &#xA;

  • How to Choose the Optimal Multi-Touch Attribution Model for Your Organisation

    13 mars 2023, par Erin — Analytics Tips

    If you struggle to connect the dots on your customer journeys, you are researching the correct solution. 

    Multi-channel attribution models allow you to better understand the users’ paths to conversion and identify key channels and marketing assets that assist them.

    That said, each attribution model has inherent limitations, which make the selection process even harder.

    This guide explains how to choose the optimal multi-touch attribution model. We cover the pros and cons of popular attribution models, main evaluation criteria and how-to instructions for model implementation. 

    Pros and Cons of Different Attribution Models 

    Types of Attribution Models

    First Interaction 

    First Interaction attribution model (also known as first touch) assigns full credit to the conversion to the first channel, which brought in a lead. However, it doesn’t report other interactions the visitor had before converting.

    Marketers, who are primarily focused on demand generation and user acquisition, find the first touch attribution model useful to evaluate and optimise top-of-the-funnel (ToFU). 

    Pros 

    • Reflects the start of the customer journey
    • Shows channels that bring in the best-qualified leads 
    • Helps track brand awareness campaigns

    Cons 

    • Ignores the impact of later interactions at the middle and bottom of the funnel 
    • Doesn’t provide a full picture of users’ decision-making process 

    Last Interaction 

    Last Interaction attribution model (also known as last touch) shifts the entire credit allocation to the last channel before conversion. But it doesn’t account for the contribution of all other channels. 

    If your focus is conversion optimization, the last-touch model helps you determine which channels, assets or campaigns seal the deal for the prospect. 

    Pros 

    • Reports bottom-of-the-funnel events
    • Requires minimal data and configurations 
    • Helps estimate cost-per-lead or cost-per-acquisition

    Cons 

    • No visibility into assisted conversions and prior visitor interactions 
    • Overemphasise the importance of the last channel (which can often be direct traffic) 

    Last Non-Direct Interaction 

    Last Non-Direct attribution excludes direct traffic from the calculation and assigns the full conversion credit to the preceding channel. For example, a paid ad will receive 100% of credit for conversion if a visitor goes directly to your website to buy a product. 

    Last Non-Direct attribution provides greater clarity into the bottom-of-the-funnel (BoFU). events. Yet, it still under-reports the role other channels played in conversion. 

    Pros 

    • Improved channel visibility, compared to Last-Touch 
    • Avoids over-valuing direct visits
    • Reports on lead-generation efforts

    Cons 

    • Doesn’t work for account-based marketing (ABM) 
    • Devalues the quality over quantity of leads 

    Linear Model

    Linear attribution model assigns equal credit for a conversion to all tracked touchpoints, regardless of their impact on the visitor’s decision to convert.

    It helps you understand the full conversion path. But this model doesn’t distinguish between the importance of lead generation activities versus nurturing touches.

    Pros 

    • Focuses on all touch points associated with a conversion 
    • Reflects more steps in the customer journey 
    • Helps analyse longer sales cycles

    Cons 

    • Doesn’t accurately reflect the varying roles of each touchpoint 
    • Can dilute the credit if too many touchpoints are involved 

    Time Decay Model 

    Time decay models assumes that the closer a touchpoint is to the conversion, the greater its influence. Pre-conversion touchpoints get the highest credit, while the first ones are ranked lower (5%-5%-10%-15%-25%-30%).

    This model better reflects real-life customer journeys. However, it devalues the impact of brand awareness and demand-generation campaigns. 

    Pros 

    • Helps track longer sales cycles and reports on each touchpoint involved 
    • Allows customising the half-life of decay to improve reporting 
    • Promotes conversion optimization at BoFu stages

    Cons 

    • Can prompt marketers to curtail ToFU spending, which would translate to fewer qualified leads at lower stages
    • Doesn’t reflect highly-influential events at earlier stages (e.g., a product demo request or free account registration, which didn’t immediately lead to conversion)

    Position-Based Model 

    Position-Based attribution model (also known as the U-shaped model) allocates the biggest credit to the first and the last interaction (40% each). Then distributes the remaining 20% across other touches. 

    For many marketers, that’s the preferred multi-touch attribution model as it allows optimising both ToFU and BoFU channels. 

    Pros 

    • Helps establish the main channels for lead generation and conversion
    • Adds extra layers of visibility, compared to first- and last-touch attribution models 
    • Promotes budget allocation toward the most strategic touchpoints

    Cons 

    • Diminishes the importance of lead nurturing activities as more credit gets assigned to demand-gen and conversion-generation channels
    • Limited flexibility since it always assigns a fixed amount of credit to the first and last touchpoints, and the remaining credit is divided evenly among the other touchpoints

    How to Choose the Right Multi-Touch Attribution Model For Your Business 

    If you’re deciding which attribution model is best for your business, prepare for a heated discussion. Each one has its trade-offs as it emphasises or devalues the role of different channels and marketing activities.

    To reach a consensus, the best strategy is to evaluate each model against three criteria : Your marketing objectives, sales cycle length and data availability. 

    Marketing Objectives 

    Businesses generate revenue in many ways : Through direct sales, subscriptions, referral fees, licensing agreements, one-off or retainer services. Or any combination of these activities. 

    In each case, your marketing strategy will look different. For example, SaaS and direct-to-consumer (DTC) eCommerce brands have to maximise both demand generation and conversion rates. In contrast, a B2B cybersecurity consulting firm is more interested in attracting qualified leads (as opposed to any type of traffic) and progressively nurturing them towards a big-ticket purchase. 

    When selecting a multi-touch attribution model, prioritise your objectives first. Create a simple scoreboard, where your team ranks various channels and campaign types you rely on to close sales. 

    Alternatively, you can survey your customers to learn how they first heard about your company and what eventually triggered their conversion. Having data from both sides can help you cross-validate your assumptions and eliminate some biases. 

    Then consider which model would best reflect the role and importance of different channels in your sales cycle. Speaking of which….

    Sales Cycle Length 

    As shoppers, we spend less time deciding on a new toothpaste brand versus contemplating a new IT system purchase. Factors like industry, business model (B2C, DTC, B2B, B2BC), and deal size determine the average cycle length in your industry. 

    Statistically, low-ticket B2C sales can happen within just several interactions. The average B2B decision-making process can have over 15 steps, spread over several months. 

    That’s why not all multi-touch attribution models work equally well for each business. Time-decay suits better B2B companies, while B2C usually go for position-based or linear attribution. 

    Data Availability 

    Businesses struggle with multi-touch attribution model implementation due to incomplete analytics data. 

    Our web analytics tool captures more data than Google Analytics. That’s because we rely on a privacy-focused tracking mechanism, which allows you to collect analytics without showing a cookie consent banner in markets outside of Germany and the UK. 

    Cookie consent banners are mandatory with Google Analytics. Yet, almost 40% of global consumers reject it. This results in gaps in your analytics and subsequent inconsistencies in multi-touch attribution reports. With Matomo, you can compliantly collect more data for accurate reporting. 

    Some companies also struggle to connect collected insights to individual shoppers. With Matomo, you can cross-attribute users across browning sessions, using our visitors’ tracking feature

    When you already know a user’s identifier (e.g., full name or email address), you can track their on-site behaviours over time to better understand how they interact with your content and complete their purchases. Quick disclaimer, though, visitors’ tracking may not be considered compliant with certain data privacy laws. Please consult with a local authority if you have doubts. 

    How to Implement Multi-Touch Attribution

    Multi-touch attribution modelling implementation is like a “seek and find” game. You have to identify all significant touchpoints in your customers’ journeys. And sometimes also brainstorm new ways to uncover the missing parts. Then figure out the best way to track users’ actions at those stages (aka do conversion and events tracking). 

    Here’s a step-by-step walkthrough to help you get started. 

    Select a Multi-Touch Attribution Tool 

    The global marketing attribution software is worth $3.1 billion. Meaning there are plenty of tools, differing in terms of accuracy, sophistication and price.

    To make the right call prioritise five factors :

    • Available models : Look for a solution that offers multiple options and allows you to experiment with different modelling techniques or develop custom models. 
    • Implementation complexity : Some providers offer advanced data modelling tools for creating custom multi-touch attribution models, but offer few out-of-the-box modelling options. 
    • Accuracy : Check if the shortlisted tool collects the type of data you need. Prioritise providers who are less dependent on third-party cookies and allow you to identify repeat users. 
    • Your marketing stack : Some marketing attribution tools come with useful add-ons such as tag manager, heatmaps, form analytics, user session recordings and A/B testing tools. This means you can collect more data for multi-channel modelling with them instead of investing in extra software. 
    • Compliance : Ensure that the selected multi-attribution analytics software wouldn’t put you at risk of GDPR non-compliance when it comes to user privacy and consent to tracking/analysis. 

    Finally, evaluate the adoption costs. Free multi-channel analytics tools come with data quality and consistency trade-offs. Premium attribution tools may have “hidden” licensing costs and bill you for extra data integrations. 

    Look for a tool that offers a good price-to-value ratio (i.e., one that offers extra perks for a transparent price). 

    Set Up Proper Data Collection 

    Multi-touch attribution requires ample user data. To collect the right type of insights you need to set up : 

    • Website analytics : Ensure that you have all tracking codes installed (and working correctly !) to capture pageviews, on-site actions, referral sources and other data points around what users do on page. 
    • Tags : Add tracking parameters to monitor different referral channels (e.g., “facebook”), campaign types (e.g., ”final-sale”), and creative assets (e.g., “banner-1”). Tags help you get a clearer picture of different touchpoints. 
    • Integrations : To better identify on-site users and track their actions, you can also populate your attribution tool with data from your other tools – CRM system, A/B testing app, etc. 

    Finally, think about the ideal lookback window — a bounded time frame you’ll use to calculate conversions. For example, Matomo has a default windows of 7, 30 or 90 days. But you can configure a custom period to better reflect your average sales cycle. For instance, if you’re selling makeup, a shorter window could yield better results. But if you’re selling CRM software for the manufacturing industry, consider extending it.

    Configure Goals and Events 

    Goals indicate your main marketing objectives — more traffic, conversions and sales. In web analytics tools, you can measure these by tracking specific user behaviours. 

    For example : If your goal is lead generation, you can track :

    • Newsletter sign ups 
    • Product demo requests 
    • Gated content downloads 
    • Free trial account registration 
    • Contact form submission 
    • On-site call bookings 

    In each case, you can set up a unique tag to monitor these types of requests. Then analyse conversion rates — the percentage of users who have successfully completed the action. 

    To collect sufficient data for multi-channel attribution modelling, set up Goal Tracking for different types of touchpoints (MoFU & BoFU) and asset types (contact forms, downloadable assets, etc). 

    Your next task is to figure out how users interact with different on-site assets. That’s when Event Tracking comes in handy. 

    Event Tracking reports notify you about specific actions users take on your website. With Matomo Event Tracking, you can monitor where people click on your website, on which pages they click newsletter subscription links, or when they try to interact with static content elements (e.g., a non-clickable banner). 

    Using in-depth user behavioural reports, you can better understand which assets play a key role in the average customer journey. Using this data, you can localise “leaks” in your sales funnel and fix them to increase conversion rates.

    Test and Validated the Selected Model 

    A common challenge of multi-channel attribution modelling is determining the correct correlation and causality between exposure to touchpoints and purchases. 

    For example, a user who bought a discounted product from a Facebook ad would act differently than someone who purchased a full-priced product via a newsletter link. Their rate of pre- and post-sales exposure will also differ a lot — and your attribution model may not always accurately capture that. 

    That’s why you have to continuously test and tweak the selected model type. The best approach for that is lift analysis. 

    Lift analysis means comparing how your key metrics (e.g., revenue or conversion rates) change among users who were exposed to a certain campaign versus a control group. 

    In the case of multi-touch attribution modelling, you have to monitor how your metrics change after you’ve acted on the model recommendations (e.g., invested more in a well-performing referral channel or tried a new brand awareness Twitter ad). Compare the before and after ROI. If you see a positive dynamic, your model works great. 

    The downside of this approach is that you have to invest a lot upfront. But if your goal is to create a trustworthy attribution model, the best way to validate is to act on its suggestions and then test them against past results. 

    Conclusion

    A multi-touch attribution model helps you measure the impact of different channels, campaign types, and marketing assets on metrics that matter — conversion rate, sales volumes and ROI. 

    Using this data, you can invest budgets into the best-performing channels and confidently experiment with new campaign types. 

    As a Matomo user, you also get to do so without breaching customers’ privacy or compromising on analytics accuracy.

    Start using accurate multi-channel attribution in Matomo. Get your free 21-day trial now. No credit card required.