UTM 생성기로 광고효율 분석 기반 마련하기

나이트 개발자·2023년 3월 27일
0
post-thumbnail

회사의 광고효율성 분석을 위해 광고배너나 페이지에 우리 회사의 특정 랜딩 페이지로 넘어오는 링크를 남기게 된다. 이 때 해당 링크가 어떤 곳에서 생성되었는 지 확인하는 용도로 UTM을 사용하는데, 그 간 일정한 규칙없이 사용하고 있어 분석에 어려움이 다소 있다. 이를 바로 잡기 위해 UTM을 생성하는 규칙이 동작하는 React 앱을 만들었다.

UTM에 대한 이해를 시작으로 아주 간단한 React App 을 Typescript로 개발하는 예제라 초보 프론트 엔지니어에게도 도움이 될 것 같다.

UTM이란?

UTM은 웹 트래픽 추적 및 분석에 사용되는 파라미터로, 기존 URL에 추가하여 광고나 마케팅 채널이 어떻게 성과를 거두었는지 파악할 수 있다. 이를 통해 마케팅 전략을 더 효율적으로 진행할 수 있다.

Urchin Tracking Module의 약자로 Urchin Software Corporation이 개발한 Urchin은 구글에 인수되어 Google Analytics의 기반이 되었다. 이 때 남아 있던 이름이 아직까지 이용되고 있다.

UTM 파라미터

UTM 파라미터는 다음과 같이 5가지가 있으며, 각각에 대한 설명과 일반적으로 사용되는 값들은 다음과 같다.

  1. utm_source (광고 매체)
    설명: 광고를 게시한 트래픽 소스를 나타낸다.
    일반적인 값: 'google', 'facebook', 'twitter' 등

  2. utm_medium (마케팅 채널)
    설명: 광고가 게시된 마케팅 채널을 나타낸다.
    일반적인 값: 'cpc', 'email', 'social' 등

  3. utm_campaign (캠페인 이름)
    설명: 마케팅 캠페인의 이름을 나타낸다.
    일반적인 값: 'spring_sale', 'holiday_promotion' 등

  4. utm_term (키워드)
    설명: 키워드를 통해 검색된 광고를 추적하는데 사용된다. 주로 검색 광고를 집행할 때 사용한다.
    일반적인 값: 'running_shoes', 'red_dress' 등

  5. utm_content (광고 내용)
    설명: 동일한 캠페인 내에서 여러 광고를 구분하기 위해 사용된다.
    일반적인 값: 'banner1', 'textlink' 등

이러한 UTM 파라미터를 사용하여 웹 트래픽의 원천, 채널, 캠페인, 키워드, 광고 내용 등을 추적할 수 있어 마케팅 활동의 효과를 평가하고 개선하는 데 도움이 된다.

GTM과의 차별점

  1. Google Tag Manager (GTM):
    GTM은 웹사이트에 포함되는 다양한 태그(스크립트)를 중앙 집중적으로 관리하는 도구로써
    마케팅, 웹 분석, 개별 광고 캠페인에 관련된 다양한 태그를 웹사이트의 코드를 직접 수정하지 않고도 삽입, 수정 및 제거할 수 있게 한다.
    GTM을 사용하면 개발자의 도움 없이도 마케팅 및 분석 전문가들이 웹사이트의 행동 추적, 이벤트 트래킹, 전환 추적 등을 손쉽게 관리할 수 있다.

  2. UTM 파라미터:
    UTM 파라미터는 웹 트래픽의 광고 소스, 채널, 캠페인, 키워드 및 광고 내용을 추적하기 위해 URL에 추가되는 파라미터로써, 이를 사용하면 마케팅 활동의 성과를 평가하고 개선할 수 있습니다. 예를 들어, 어떤 광고 매체와 캠페인이 가장 효과적인지, 어떤 키워드가 광고에 더 많은 클릭을 이끌어내는지 등을 분석할 수 있다.

결론적으로, 구글 태그 매니저는 웹사이트에 포함되는 다양한 태그를 관리하는 도구로, 웹 트래픽을 추적하고 분석하는 방법을 제공하는 반면, UTM 파라미터는 URL에 추가되는 파라미터로써 광고 소스, 채널, 캠페인 등의 정보를 식별하고 추적하는데 사용된다. 두 도구 모두 마케팅 활동의 성과를 평가하고 개선하는 데 도움을 주지만, 사용 목적과 기능이 다르다.

React typescript 코딩

  1. Create react app
yarn global add create-react-app
yarn create react-app my-app --template typescript
cd my-app
yarn add @mui/material @mui/styled-engine-sc styled-components
yarn
  1. UTMGenerator.tsx 제작
import React, { useState } from "react";
import { Button, TextField, Container, Typography, Box, Grid } from "@mui/material";

interface UTMParams {
    source: string;
    medium: string;
    campaign: string;
    term?: string;
    content?: string;
}

const UTMGenerator: React.FC = () => {
    const [url, setUrl] = useState("");
    const [utmParams, setUtmParams] = useState<UTMParams>({
        source: "",
        medium: "",
        campaign: "",
        term: "",
        content: "",
    });
    const [generatedUrl, setGeneratedUrl] = useState("");

    const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>, param: keyof UTMParams) => {
        setUtmParams({ ...utmParams, [param]: e.target.value });
    };

    // const handleChange = (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
    //     const { name, value } = event.target;
    //     console.log("name", name, "value", value, event.target);
    //     setUtmParams({ ...utmParams, [name]: value });
    // };
    const generateUTM = () => {
        const encodedParams = Object.entries(utmParams)
            .filter(([_, value]) => value)
            .map(([key, value]) => `utm_${key}=${encodeURIComponent(value.trim().replace(/\s+/g, "-"))}`)
            .join("&");

        setGeneratedUrl(`${url}?${encodedParams}`);
    };

    return (
        <Container>
            <Typography variant="h4" gutterBottom>
                Cleanbedding UTM 생성기
            </Typography>
            <Box mb={2}>
                <Grid container spacing={2}>
                    <Grid item xs={5}>
                        <TextField label="URL" variant="outlined" fullWidth value={url} onChange={(e) => setUrl(e.target.value)} />
                    </Grid>
                    <Grid item xs={7}>
                        <Typography variant="body1" color="textSecondary" gutterBottom align="left">
                            링크를 올릴 사이트 또는 게시글을 입력해주세요.
                        </Typography>
                    </Grid>
                </Grid>
            </Box>
            <Box mb={2}>
                <Grid container spacing={2}>
                    <Grid item xs={5}>
                        <TextField label="Source" variant="outlined" fullWidth value={utmParams.source} onChange={(e) => handleChange(e, "source")} />
                    </Grid>
                    <Grid item xs={7}>
                        <Typography variant="body1" color="textSecondary" gutterBottom align="left">
                            광고 또는 이벤트 소스를 입력하세요.
                        </Typography>
                    </Grid>
                </Grid>
            </Box>
            <Box mb={2}>
                <Grid container spacing={2}>
                    <Grid item xs={5}>
                        <TextField label="Medium" variant="outlined" fullWidth value={utmParams.medium} onChange={(e) => handleChange(e, "medium")} />
                    </Grid>
                    <Grid item xs={7}>
                        <Typography variant="body1" color="textSecondary" gutterBottom align="left">
                            링크가 게시되는 매체의 종류
                        </Typography>
                    </Grid>
                </Grid>
            </Box>
            <Box mb={2}>
                <Grid container spacing={2}>
                    <Grid item xs={5}>
                        <TextField
                            label="Campaign"
                            variant="outlined"
                            fullWidth
                            value={utmParams.campaign}
                            onChange={(e) => handleChange(e, "campaign")}
                        />
                    </Grid>
                    <Grid item xs={7}>
                        <Typography variant="body1" color="textSecondary" gutterBottom align="left">
                            한글로 된 캠페인 이름
                        </Typography>
                    </Grid>
                </Grid>
            </Box>
            <Box mb={2}>
                <Grid container spacing={2}>
                    <Grid item xs={5}>
                        <TextField
                            label="Term (optional)"
                            variant="outlined"
                            fullWidth
                            value={utmParams.term}
                            onChange={(e) => handleChange(e, "term")}
                        />
                    </Grid>
                    <Grid item xs={7}>
                        <Typography variant="body1" color="textSecondary" gutterBottom align="left">
                            광고 컨텐츠의 키워드- 해시태크, SEO키워드, 광고키워드  (수동)
                            <br />
                            (블로그등의 게시글일 경우 컨텐츠 입력하여 자동 생성)
                        </Typography>
                    </Grid>
                </Grid>
            </Box>
            <Box mb={2}>
                <Grid container spacing={2}>
                    <Grid item xs={5}>
                        <TextField
                            label="Content (optional)"
                            variant="outlined"
                            fullWidth
                            value={utmParams.content}
                            onChange={(e) => handleChange(e, "content")}
                        />
                    </Grid>
                    <Grid item xs={7}>
                        <Typography variant="body1" color="textSecondary" gutterBottom align="left">
                            타게팅하는 고객군 이름
                        </Typography>
                    </Grid>
                </Grid>
            </Box>
            <Box mb={2}>
                <Button variant="contained" color="primary" onClick={generateUTM}>
                    생성
                </Button>
            </Box>
            {generatedUrl && (
                <Box>
                    <Typography variant="h6">생성된 UTM 링크</Typography>
                    <TextField
                        variant="outlined"
                        fullWidth
                        value={generatedUrl}
                        InputProps={{
                            readOnly: true,
                        }}
                    />
                    <Box mt={2}>
                        <Button
                            variant="contained"
                            color="secondary"
                            onClick={() => {
                                navigator.clipboard.writeText(generatedUrl);
                            }}
                        >
                            복사
                        </Button>
                    </Box>
                </Box>
            )}
        </Container>
    );
};

export default UTMGenerator;
  1. App.tsx 수정
import React from "react";
import logo from "./logo.svg";
import "./App.css";
import UTMGenerator from "./UTMGenerator";

function App() {
    return (
        <div className="App">
            <UTMGenerator />
        </div>
    );
}

export default App;

완성화면

다음단계

TextField로 입력 받는 부분은 우리 회사 사정에 맞는 값들을 선택할 수 있도록 수정할 예정이며 각종 지능화 된 기능들을 연계할 예정이다. 이렇게 인터넷 상에 우리회사 광고컨텐츠에 UTM들을 포함하여 배포해두면 GA4가 연계된 랜딩페이지에 들어온 고객들은 체계적으로 추적 가능해지고 GA4에 기록된 고객들은 이전에 남긴 포스트와 같이 광고 효율을 측정하는 단계와 연계할 수 있다.

profile
개발하면서 또는 프러덕 관리하면서 겪는 기억해둬야하는 내용을 메모장 삼아 남긴다. Google Keep이나 메모 도구에 남기는 것과는 달리 잘 정리할 수 있어서 언젠가 들춰봐야할 내용들을 담은 글들이 게시된다.

0개의 댓글